Saudações.
Hoje vou ensinar como usar o Claude Code no Docker.
O Claude Code é hoje o “estado de arte” em agentes de IA, com a única desvantagem o preço do mega token!
Pré-requisitos:
- Servidor, VPS ou VM com Linux;
- Docker;
1 – Sobre o Claude Code
O Claude Code é um atente em interface de terminal (TUI – Terminal User Interface), e recentemente lançaram o Claude Desktop para ajudar os usuários que tem medinho de digitar em tela preta.
Visto que ele pode ser instalado no Linux, ele é totalmente apto a rodar em containers.
2 – Claude Code no Docker
Publiquei a imagem no Docker Hub em tmsoftbrasil/claude-code: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:
| Volume | Propósito |
|---|---|
| Volume para todas as informações do Claude, memória, credenciais, skills, etc, requer explicitamente montagem em volume |
/cache | Cache 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. |
| Pasta de trabalho padrão do agente. Montar volume em uma pasta do host onde os resultados do Claude 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 porta22/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);
3 – Rodando Claude Code no Docker
Vamos rodar o OC no Docker, criando o container tmsoftbrasil/claude-code.
3.1 – Rede Docker
Criando a rede para containers (network_public):
# 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 dentro do container deve ser mapeada na pasta onde estará seu projeto de software no HOST, pasta: /workspace./storage/claude-code-test/workspace
A pasta retem as informações do próprio Claude Code, nesse exemplo vou armazenar tudo em /data para você testar e aprender (depois você personaliza)./storage/claude-code-test/data
3.3 – Container do Claude
Comando para rodar no “docker run” completo, personalize a gosto:
#!/bin/sh
# Variaveis
NAME="claude-code-test";
IMAGE="tmsoftbrasil/claude-code:latest";
# Diretorio de dados persistentes:
mkdir -p /storage/claude-code-test/data;
mkdir -p /storage/claude-code-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.202 \
-p 8822:22 \
\
--tmpfs /run:rw,size=32m \
--tmpfs /cache:rw,exec,suid,mode=1777,dev,size=1024m \
\
-v /storage/claude-code-test/data:/data \
-v /storage/claude-code-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 \
\
$IMAGE $ARG;
# Acesso
echo;
echo;
echo "claude-code";
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:
# docker-compose.yml
services:
claude-code-test:
image: tmsoftbrasil/claude-code:latest
container_name: claude-core-test
hostname: claude-code-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.204
ports:
- "8022:22"
# 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
networks:
network_public:
external: true
4 – Primeiro acesso
Obtenha shell no container “claude-code-test“:
# Obter shell no container:
docker exec -it claude-code-test bash;
# Rodar Claude:
claude;
# Ou, rodar direto o claude dentro do container:
docker exec -it claude-code-test claude;
5 – Diversidade
Algumas dicas e truques!
5.1 – Desviando para outros modelos
Usando API do DeepSeek no Claude Code:
# Exporte no terminal ou inclua no container
export ANTHROPIC_BASE_URL="https://api.deepseek.com/anthropic";
export ANTHROPIC_AUTH_TOKEN="your_actual_deepseek_api_key";
export ANTHROPIC_MODEL="deepseek-v4-pro";
export CLAUDE_CODE_EFFORT_LEVEL="max";
# Entrar na pasta de trabalho
cd /workspace;
# Rodar o claude:
claude;
.
.
Agora é contigo. Use sua criatividade.
Terminamos por hoje!
Patrick Brandão, patrickbrandao@gmail.com
“Se até uma formiga tem um propósito,
quem é você para não ter?“
Gui Fleury
