OpenCode no Docker

Saudações.

Hoje vou ensinar como usar o OpenCode no Docker.

Ao enlatar o OpenCode em container eu ganho a liberdade de ter um container para cada projeto e acessá-lo puramente por SSH ou WEB de qualquer lugar, alem de automatizar execuções com gatilhos próprios.

Pré-requisitos:

  • Servidor, VPS ou VM com Linux;
  • Docker;

1 – Sobre o OpenCode

O OpenCode (OC) é um agente de IA especializado e refinado para planejar (plan) e construir (build) softwares.

Ele é uma “versão gratuita e aberta do Claude Code” e se tornou muito famoso ser simples e poderoso.

Embora essa seja a principal função dele, você pode usá-lo como agente genérico para qualquer tarefa, basta que você ensine-o.

É normal rodar vários agentes ao mesmo tempo, basta que para cada projeto você abra uma tela no terminal (TUI) ou web, vá até a pasta do seu projeto e rode o comando “opencode“.

Ele é executado de duas formas:

  • Terminal do Agente: Ao rodar o comando “opencode” ele inicia um terminal moderno para interação com você, o usuário, nesse terminal você insere o prompt ou comandos específicos que iniciam com “/”;
  • Comando para o Agente: Permite acionar o comando para tarefas onshot:
    • opencode promopt “seu prompt aqui
  • WebUI dos Agentes: Pelo navegador (PC ou smartphone) você acessa o OC com toda a flexibilidade.

Para funcionar ele precisa:

  • Acesso a Internet durante a execução;
  • Chave de API para algum modelo de IA, o OC oferece APIs gratuitas sem precisar fazer login ou cadastro, o que é MUITO bom para uso rápido no dia-a-dia.

Links:

2 – OpenCode no Docker

Essa parte foi um pouco difícil. Por ser feito em Javascript/TypeScript e por padrão rodando no framework do nodejs o OpenCode espalha arquivos em vários lugares.

Publiquei a imagem no Docker Hub em tmsoftbrasil/opencode:latest, logo você pode pular esse capítulo e usá-lo no capítulo 3.

Leia os tópicos abaixo para entender a engenharia da imagem.

2.1 – Caminhos e volumes

Esses caminhos precisam ser mapeados e direcionado para volumes, assim o container separa:

  • Programas: Os binários e bibliotecas de códigos;
  • Dados: Configurações e informações acumuladas pelo OC;
  • Cache: Arquivos gerados para acelerar a execução;
  • Workspace: Projeto de código onde serão produzidos os artefatos do agente, como códigos, documentações, etc;

Caminhos que configurei:

VolumePropósito
/dataVolume para todas as informações do OpenCode, memória, credenciais, skills, etc, requer explicitamente montagem em volume
/cacheCache e arquivos que não precisam ser armazenados a longo prazo, não requer montagem em volume, recomendado usar em tmpfs com opções rw,exec,suid,mode=1777,dev,size=1024m, se preferir reinicializações rápidas, crie um volume persistente.
/workspacePasta de trabalho padrão do agente. Montar volume em uma pasta do host onde os resultados do OpenCode serão armazenados e retidos.

2.2 – Serviços

Criei os seguintes serviços no container usando supervisor (supervisord como init, pid 1):

  • cron: O crontab foi criado e iniciado, cada pasta em /data/cron/ possui um temporizador de execução de scripts que forem hospedados nessas pastas, exemplo:
    • /data/cron/hourly/: Todo script aqui será executado a cada hora;
    • /data/cron/daily/: Todo script aqui será executado uma vez por dia.
  • ssh: O OpenSSH Server foi iniciado e opera na porta 22/tcp, arquivos para mapear cadastro de chaves públicas:
    • /data/ssh/trusted_keys: Chaves públicas de usuários do container;
    • /data/.ssh/authorized_keys: Chaves públicas de usuários do host (mapeie via volume bind em /root/.ssh/authorized_keys);
  • opencode-web: Interface web na porta HTTP 8080/tcp do container, mapear em porta externa ou via proxy-reverso (Traefik);
  • opencode-acp: Porta de servidor Agent Client Protocol para integração com editores (VS Code, etc) na porta 8090/tcp do container.

3 – Rodando OpenCode no Docker

Vamos rodar o OC no Docker, criando o container tmsoftbrasil/opencode.

3.1 – Rede Docker

Criando a rede para containers (network_public):

Bash
# Rede de containers
docker network create network_public \
    -d bridge \
    -o com.docker.network.bridge.name=br-net-public \
    -o com.docker.network.driver.mtu=1500 \
    -o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected \
    --subnet 10.249.0.0/16 \
    --gateway 10.249.255.254;

3.2 – Volume

A pasta /workspace dentro do container deve ser mapeada na pasta onde estará seu projeto de software no HOST, vou colocar em /storage/opencode-test/workspace.

A pasta /data retem as informações do próprio OpenCode, nesse exemplo vou armazenar tudo em /storage/opencode-test/data para você testar e aprender (depois você personaliza).

3.3 – Container do OC

Comando para rodar no “docker run” completo, personalize a gosto:

Bash
#!/bin/sh

# Variaveis
    NAME="opencode-test";
    IMAGE="tmsoftbrasil/opencode:latest";
    #FQDN="$NAME.$(hostname -f)";
    FQDN="opencode.seudominio.com.br";

# Diretorio de dados persistentes:
    #rm     -rf /storage/opencode-test;
    mkdir  -p  /storage/opencode-test;
    mkdir  -p  /storage/opencode-test/data;
    mkdir  -p  /storage/opencode-test/workspace;

# Renovar/rodar
    docker container rm -f $NAME 2>/dev/null
    docker container run \
        -d \
        --user               root \
        --restart            always \
        --name               $NAME \
        --hostname           $NAME.intranet.br \
        \
        --cpus                2.0  \
        --cpu-shares         1024 \
        --memory               2g \
        --memory-swap          2g \
        --memory-reservation   1g \
        --shm-size             1g \
        \
        --network            network_public \
        --ip                 10.249.111.134 \
        -p                   9622:22 \
        -p                   9680:8080 \
        \
        --tmpfs /run:rw,size=32m \
        --tmpfs /cache:rw,exec,suid,mode=1777,dev,size=1024m \
        \
        -v /storage/opencode-test/data:/data \
        -v /storage/opencode-test/workspace:/workspace \
        \
        -v /var/run/docker.sock:$(readlink -f /var/run/docker.sock) \
        -v /root/.ssh/authorized_keys:/data/.ssh/authorized_keys:ro \
        \
        -w /workspace \
        \
        --label "traefik.enable=true" \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=web,websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=8080" \
        \
        $IMAGE;

# Acesso
    echo;
    echo;
    echo "OpenCode";
    echo "    Container.......:  $NAME";
    echo "    Acesso ssh......:  ssh root@$FQDN -p 9622";
    echo "    Acesso web......:  https://$FQDN";
    echo "    Docker shell....:  docker exec -it $NAME bash;";
    echo;
    echo;

3.4 – Stack para Compose

Caso prefira no modelo de Stack para docker compose:

YAML
# docker-compose.yml
services:
  opencode-test:
    image: tmsoftbrasil/opencode:latest
    container_name: opencode-test
    hostname: opencode-test.intranet.br
    user: root
    restart: always
    working_dir: /workspace

    # Recursos
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 2g
        reservations:
          memory: 1g
    cpu_shares: 1024
    mem_swappiness: 0
    shm_size: 1g

    # Limites extras (sem suporte em deploy, usando extensão direta)
    memswap_limit: 2g

    # Rede
    networks:
      network_public:
        ipv4_address: 10.249.111.134

    ports:
      - "9622:22"
      - "9680:8080"

    # tmpfs
    tmpfs:
      - /run:rw,size=32m
      - /cache:rw,exec,suid,mode=1777,dev,size=1024m

    # Volumes
    volumes:
      - /storage/opencode-test/data:/data
      - /storage/opencode-test/workspace:/workspace
      - /var/run/docker.sock:/var/run/docker.sock
      - /root/.ssh/authorized_keys:/data/.ssh/authorized_keys:ro

    # Labels Traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.opencode-test.rule=Host(`opencode.seudominio.com.br`)"
      - "traefik.http.routers.opencode-test.entrypoints=web,websecure"
      - "traefik.http.routers.opencode-test.tls=true"
      - "traefik.http.routers.opencode-test.tls.certresolver=letsencrypt"
      - "traefik.http.services.opencode-test.loadbalancer.server.port=8080"

networks:
  network_public:
    external: true

4 – Primeiro acesso

Obtenha shell no container “opencode-test“:

Bash
# Obter shell no container:
docker exec -it opencode-test bash;

# Rodar opencode:
opencode;

# Ou, rodar direto o opencode dentro do container:
docker exec -it opencode-test opencode;

4.1 – Tela inicial

Você verá a seguinte tela:

4.2 – Conectando OC a um modelo de IA

O primeiro passo é fornecer um modelo usando o comando “/connect“.

Gratuitamente: Escolha “OpenCode Zen“, acesse https://opencode.ai/zen para obter uma chave, você pode escolher algum modelo “Free” para usar se precisar pagar nada.

Pagos e baratos: Escolha “OpenRouter“, acesse https://openrouter.ai, cadastre-se, coloque algum crédito (15 dólares), recomendo usar o DeepSeek V4 ou algum modelo focado em código com o preço baixo.

Eu uso OpenRouter com DeepSeek V4 PRO. Custa alguns centavos de dolar por hora e produz software com muita precisão.

Após rodar o /connect escolhe OpenRouter:

Inserindo a chave de API gerada no site:

Escolha o modelo:

E por fim, pronto para usar:

Para fechar o OpenCode (não para o container):

4.3 – Criando alguma coisa com IA

Com o OpenCode aberto, basta pedir alguma coisa, o resultado por padrão será gerado em /workspace (dentro do container) que fica na pasta do HOST onde esse volume foi mapeado.

Prompt:

Agente OC trabalho:

Resultado pronto:

Resultado (abri arquivo aviso.html no navegador):

.

Agora é contigo. Use sua criatividade.

Terminamos por hoje!

Patrick Brandão, patrickbrandao@gmail.com

Sábio não é aquele que sabe
de tudo e sim usa tudo que sabe
Provérbio Chinês