Claude Code e Devcontainer: ambiente de desenvolvimento reproduzível
Monte um devcontainer Claude Code com Dockerfile, permissões, segredos, volumes e portas.
Claude Code rende mais quando o ambiente de desenvolvimento é previsível. Se uma pessoa usa Node.js 22, outra ainda está no Node.js 20, PostgreSQL está instalado de maneiras diferentes e Redis só existe em algumas máquinas, o agente passa tempo demais lidando com diferenças locais. Um devcontainer transforma essas decisões em configuração versionada.
Dev Container é um contêiner de desenvolvimento ao qual o editor se conecta. Terminal, servidor de linguagem, testes, ferramentas de banco de dados e Claude Code rodam dentro do mesmo ambiente Docker. Neste guia, vamos montar uma base para Next.js e TypeScript com PostgreSQL, Redis, Dockerfile, postCreateCommand, permissões, segredos, volumes e port-forward.
Em 2 de junho de 2026, a documentação oficial do Claude Code inclui uma página de Development containers, com orientações sobre a Feature oficial, persistência de credenciais, limites de rede e riscos de pular confirmações de permissão. Para o padrão do ambiente, consulte também a documentação de VS Code Dev Containers e a Dev Container Specification.
Por que devcontainer combina com Claude Code
Claude Code lê arquivos, altera código, executa comandos e interpreta falhas de teste. Isso é poderoso, mas depende de um ambiente claro. No shell do host, o agente pode enxergar pacotes globais antigos, credenciais pessoais, variáveis de outros projetos ou um banco local diferente do banco usado pelo time.
Com devcontainer, a superfície de trabalho vira código revisável. Versão do Node.js, pacotes do sistema, versão do CLI do Claude Code, extensões do VS Code, lifecycle commands, volumes e portas encaminhadas ficam no repositório. Quando Claude Code informa que executou npm test, o revisor sabe em qual contexto isso aconteceu.
flowchart LR
Host["Máquina host"] --> Editor["VS Code / Cursor"]
Editor --> Container["Dev Container"]
Container --> Claude["Claude Code CLI"]
Container --> Tools["Node.js / npm / psql / redis-cli"]
Container --> Services["PostgreSQL / Redis"]
Container --> Repo["Repositório montado"]
Claude --> Repo
Claude --> Tools
Os três casos de uso mais fortes são onboarding, desenvolvimento remoto e depuração assistida por IA. No onboarding, a pessoa nova reconstrói o contêiner e recebe o mesmo conjunto de ferramentas. Em Codespaces ou máquinas remotas, a mesma pasta .devcontainer funciona sem depender do sistema operacional local. Na depuração, lint, typecheck e testes deixam de ser “funcionou na minha máquina”.
Arquivos da configuração
A configuração separa aplicação, serviços e estado do Claude Code. Isso evita montar o diretório home inteiro do host por conveniência.
| Arquivo | Função | O que revisar |
|---|---|---|
.devcontainer/devcontainer.json | Entrada lida pelo editor | remoteUser, portas, mounts, lifecycle commands |
.devcontainer/Dockerfile | Instala ferramentas e Claude Code | versão do CLI, usuário não root, pacotes do sistema |
.devcontainer/docker-compose.yml | Sobe app, PostgreSQL e Redis | volumes, health checks, portas publicadas |
.devcontainer/post-create.sh | Setup após criação | lockfile, Prisma, tratamento de falhas |
.claude/settings.json | Regras de permissão | .env, segredos, git push e comandos Docker destrutivos |
devcontainer.json pronto para copiar
Crie .devcontainer/devcontainer.json. O arquivo precisa ser JSON válido, sem comentários.
{
"name": "claude-code-next-dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/app",
"remoteUser": "node",
"shutdownAction": "stopCompose",
"waitFor": "postCreateCommand",
"postCreateCommand": "bash .devcontainer/post-create.sh",
"postStartCommand": "git config --global --add safe.directory /workspaces/app || true",
"forwardPorts": [3000, 5432, 6379],
"portsAttributes": {
"3000": { "label": "Next.js", "onAutoForward": "notify" },
"5432": { "label": "PostgreSQL", "onAutoForward": "silent" },
"6379": { "label": "Redis", "onAutoForward": "silent" }
},
"mounts": [
"source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume"
],
"containerEnv": {
"NODE_ENV": "development",
"DISABLE_AUTOUPDATER": "1",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
},
"customizations": {
"vscode": {
"extensions": [
"anthropic.claude-code",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-azuretools.vscode-docker"
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"typescript.tsdk": "node_modules/typescript/lib",
"terminal.integrated.defaultProfile.linux": "bash"
}
}
}
}
remoteUser deve ser um usuário não root. O contêiner reduz o risco, mas o workspace continua montado a partir do host. Se Claude Code apagar arquivos em /workspaces/app, o repositório local também muda. O volume em /home/node/.claude preserva a configuração do Claude Code entre rebuilds sem expor todo o home do host.
Docker Compose, Dockerfile e postCreateCommand
O arquivo .devcontainer/docker-compose.yml sobe app, PostgreSQL e Redis. Comece com forwardPorts; publicar portas de banco com Compose só faz sentido quando uma ferramenta externa realmente precisa.
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
command: sleep infinity
volumes:
- ..:/workspaces/app:cached
- node_modules:/workspaces/app/node_modules
- claude_code_config:/home/node/.claude
environment:
DATABASE_URL: postgresql://app:app_password@db:5432/app
REDIS_URL: redis://redis:6379
NEXT_TELEMETRY_DISABLED: "1"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app_password
POSTGRES_DB: app
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 5s
retries: 20
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 20
volumes:
node_modules:
claude_code_config:
postgres_data:
redis_data:
No Dockerfile, fixe a versão do Claude Code. Em 2 de junho de 2026, npm view @anthropic-ai/claude-code version retornou 2.1.160.
FROM mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm
ARG CLAUDE_CODE_VERSION=2.1.160
ENV DISABLE_AUTOUPDATER=1
ENV NEXT_TELEMETRY_DISABLED=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
jq \
postgresql-client \
redis-tools \
ripgrep \
&& rm -rf /var/lib/apt/lists/*
RUN npm install -g "@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}" \
&& npm cache clean --force
USER node
WORKDIR /workspaces/app
RUN mkdir -p /home/node/.claude
O setup inicial fica em .devcontainer/post-create.sh.
#!/usr/bin/env bash
set -euo pipefail
cd /workspaces/app
corepack enable
if [ -f pnpm-lock.yaml ]; then
pnpm install --frozen-lockfile
elif [ -f yarn.lock ]; then
yarn install --immutable
elif [ -f package-lock.json ]; then
npm ci
elif [ -f package.json ]; then
npm install
fi
if [ -f prisma/schema.prisma ]; then
npx prisma generate
fi
node --version
npm --version
claude --version || true
Esse script respeita o lockfile do projeto e falha cedo quando algo está quebrado. Não coloque npm run dev em postCreateCommand; servidor permanente deve rodar em terminal, task ou serviço próprio.
Permissões, segredos, volumes e port-forward
Não monte ~/.ssh, ~/.aws, ~/.config/gcloud ou .env de produção por padrão. O segredo mais seguro é o que nunca entra no contêiner. Variáveis de desenvolvimento podem apontar para serviços internos do Compose; segredos reais devem usar secrets gerenciados ou tokens temporários.
As regras do Claude Code podem ficar em .claude/settings.json.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)",
"Bash(npm run typecheck)",
"Bash(claude --version)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(printenv *)",
"Bash(git push *)",
"Bash(docker system prune *)"
]
}
}
Volumes ajudam, mas também guardam estado ruim. node_modules deve ficar em volume do contêiner para evitar mistura de módulos nativos de Windows ou macOS com Linux. O volume do PostgreSQL precisa de regra de limpeza, porque migrações de teste podem deixar o banco em um estado antigo.
Erros comuns e verificação
Erros comuns: rodar Claude Code como root, não fixar o CLI, montar segredos de produção, iniciar processos longos em postCreateCommand e publicar portas de banco sem necessidade. Cada item parece pequeno, mas juntos quebram a confiança no resultado do agente.
Depois do rebuild, verifique node --version, npm --version, claude --version, pelo menos um lint ou test, e http://localhost:3000. Confirme que .env, .env.local e secrets/** não estão acessíveis ao Claude Code e que PostgreSQL e Redis não foram expostos além do necessário.
Para aprofundar Compose, leia o guia Docker Compose com Claude Code. Para ligar isso ao fluxo de deploy, veja o guia de CI/CD com Claude Code. Se o time quer padronizar devcontainer, CLAUDE.md, permissões e revisão de qualidade, comece por training / consultation.
Resultado prático
Em um repositório pequeno de Next.js, o maior ganho veio de separar postCreateCommand em script, colocar node_modules em volume do contêiner e preservar /home/node/.claude por projeto. A cada rebuild, versão do Claude Code, instalação de dependências, geração do Prisma e porta 3000 eram verificáveis do mesmo jeito. O ponto de atenção foi o volume do banco após várias migrações de teste. Reprodutibilidade depende de versão fixa, fronteira de segredos, regra de volume e disciplina de portas ao mesmo tempo.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Escada de segurança de permissões no Claude Code
Amplie de read-only para edições limitadas, comandos de prova e deploy checks sem perder controle.
Claude Code Small PR Proof Pack: pequenas mudanças fáceis de revisar
Um pacote de prova para PRs do Claude Code: diff, checks, URL pública, CTA e rollback.
Gate de revisão antes do commit com Claude Code
Revisão antes do commit com Claude Code: diff, build, URL pública, Gumroad, consultoria, testes e arquivos fora do escopo.