Dev containers com Docker + VS Code: ambiente reproduzível do zero
1. Fundamentos dos Dev Containers
Dev Containers representam uma evolução no desenvolvimento de software, combinando o isolamento do Docker com a flexibilidade do VS Code. O conceito central é simples: todo o ambiente de desenvolvimento — incluindo runtime, ferramentas, extensões e configurações — roda dentro de um container Docker, garantindo que cada desenvolvedor da equipe trabalhe exatamente no mesmo ambiente.
A diferença fundamental entre usar Docker tradicional e Dev Containers está na experiência do desenvolvedor. No Docker tradicional, você gerencia containers manualmente via terminal, monta volumes e configura redes. Com Dev Containers, o VS Code gerencia todo esse ciclo automaticamente: ao abrir uma pasta, ele detecta a configuração, constrói a imagem, inicia o container e conecta o editor diretamente ao ambiente isolado.
O maior benefício prático é a eliminação do clássico "funciona na minha máquina". Se o ambiente está versionado no repositório, qualquer pessoa com Docker e VS Code pode começar a contribuir em minutos, sem instalar nada além das ferramentas base.
2. Configuração inicial do ambiente
Para começar, você precisa de dois pré-requisitos:
- Docker Desktop (ou Docker Engine no Linux)
- VS Code com a extensão Dev Containers (ms-vscode-remote.remote-containers)
Crie a estrutura básica do projeto:
meu-projeto/
├── .devcontainer/
│ └── devcontainer.json
├── src/
└── README.md
O arquivo .devcontainer/devcontainer.json é o coração da configuração. Um exemplo mínimo para Node.js 20:
{
"name": "Node.js Dev Container",
"image": "mcr.microsoft.com/devcontainers/javascript-node:20",
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
],
"settings": {
"editor.formatOnSave": true
}
}
},
"postCreateCommand": "npm install"
}
3. Personalização da imagem com Dockerfile
Para projetos com dependências específicas, crie um Dockerfile dentro de .devcontainer/ e referencie-o no devcontainer.json:
# .devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/javascript-node:20
# Instalar ferramentas adicionais
RUN apt-get update && apt-get install -y \
postgresql-client \
redis-tools \
&& rm -rf /var/lib/apt/lists/*
# Instalar dependências globais do Node
RUN npm install -g nodemon typescript
# Definir diretório de trabalho
WORKDIR /workspace
No devcontainer.json, substitua "image" por "build":
{
"name": "Projeto Customizado",
"build": {
"dockerfile": "Dockerfile"
},
// ... demais configurações
}
Boas práticas para o Dockerfile:
- Use imagens oficiais da Microsoft (mcr.microsoft.com/devcontainers/...) como base
- Agrupe comandos RUN para reduzir camadas
- Limpe o cache do apt-get na mesma camada da instalação
4. Gerenciamento de extensões e configurações do VS Code
Declare extensões obrigatórias no devcontainer.json para que todos usem as mesmas ferramentas:
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-azuretools.vscode-docker",
"github.copilot",
"eamodio.gitlens"
]
Para configurações do editor, use o campo settings:
"settings": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"files.autoSave": "onFocusChange",
"typescript.updateImportsOnFileMove.enabled": "always"
}
Crie também um .vscode/tasks.json para tarefas de build e teste:
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "npm run build",
"group": "build"
},
{
"label": "Test",
"type": "shell",
"command": "npm test",
"group": "test"
}
]
}
5. Integração com ferramentas de produtividade
Para projetos que dependem de serviços como banco de dados, crie um docker-compose.yml dentro de .devcontainer/:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- ..:/workspace:cached
- node_modules:/workspace/node_modules
command: sleep infinity
ports:
- "3000:3000"
depends_on:
- db
- redis
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app123
POSTGRES_DB: appdb
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
node_modules:
No devcontainer.json, referencie o compose:
{
"name": "Projeto com Serviços",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"postCreateCommand": "npm install && npx prisma generate"
}
Os volumes são essenciais para persistir dados do banco e cache de dependências (node_modules) entre rebuilds.
6. Fluxo de trabalho no dia a dia
Para abrir um projeto existente em Dev Container:
- No VS Code, pressione
F1e execute Dev Containers: Reopen in Container - Ou clique no ícone verde no canto inferior esquerdo e selecione a opção
Comandos essenciais:
- Rebuild Container: Dev Containers: Rebuild Container — reconstrói a imagem do zero
- Reopen in Container: reconecta sem rebuild
- Dev Containers: Attach to Running Container: conecta a um container já em execução
Para depuração (debug), configure um launch.json dentro de .vscode/:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug App",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"port": 9229,
"restart": true
}
]
}
O VS Code mapeia automaticamente as portas do container para sua máquina local, permitindo testar APIs e interfaces web normalmente.
7. Compartilhamento e versionamento do ambiente
Versionar a pasta .devcontainer no Git é obrigatório:
git add .devcontainer/
git commit -m "Adiciona configuração Dev Container"
No README do projeto, inclua instruções mínimas:
# Meu Projeto
## Setup
1. Instale Docker Desktop e VS Code com extensão Dev Containers
2. Clone o repositório
3. Abra a pasta no VS Code
4. Clique em "Reopen in Container" (canto inferior esquerdo)
5. Aguarde o build e instalação das dependências
6. Execute `npm run dev` para iniciar
Pronto! Ambiente configurado em menos de 5 minutos.
Para onboarding de novos desenvolvedores, o tempo de setup cai de horas para minutos. Basta clonar, abrir e aguardar o build automático.
8. Limitações e boas práticas avançadas
Performance em Windows: O compartilhamento de arquivos entre Windows e Linux via bind mount pode ser lento. Soluções:
- Use WSL2 com Docker configurado para WSL
- Armazene o projeto no sistema de arquivos WSL (\\wsl$\)
- Use volumes nomeados para diretórios com muitos arquivos (node_modules, vendor)
Projetos monolíticos vs microsserviços:
- Monolíticos: um único Dev Container com todos os serviços em docker-compose
- Microsserviços: Dev Containers separados por serviço, cada um com seu próprio .devcontainer/
Segurança e recursos:
- Nunca exponha portas do container desnecessariamente
- Use "runArgs": ["--memory=2g", "--cpus=2"] para limitar recursos
- Configure "remoteUser": "node" para evitar usar root dentro do container
Monitoramento: Use o explorador do Docker no VS Code para visualizar logs, recursos e containers em execução.
Referências
- Documentação oficial Dev Containers — Guia completo da Microsoft sobre configuração e uso de Dev Containers no VS Code
- Configuração de devcontainer.json — Referência detalhada de todas as opções do arquivo devcontainer.json
- Imagens base oficiais para Dev Containers — Catálogo de imagens pré-configuradas no Microsoft Container Registry
- Docker Compose com Dev Containers — Tutorial oficial sobre integração de múltiplos serviços com docker-compose
- Boas práticas para Dockerfiles — Guia da Docker sobre otimização de camadas, redução de tamanho e segurança em Dockerfiles
- Extensão Dev Containers no Marketplace — Página oficial da extensão com exemplos e documentação adicional