Configure e otimize ambientes de desenvolvimento Docker para projetos NestJS com hot-reload, persistência de dados, health checks e debugging eficiente.
Esta Skill orienta a configuração de ambientes Docker otimizados para desenvolvimento de aplicações NestJS, com foco em produtividade, hot-reload, debugging e boas práticas de containerização.
Configurar e manter ambientes Docker eficientes para desenvolvimento NestJS, garantindo:
Ative esta Skill quando o usuário:
NÃO use esta Skill para:
tipo_projeto: NestJS (versão, dependências principais)servicos_externos: Lista de serviços necessários (PostgreSQL, MySQL, Redis, RabbitMQ, etc.)estrutura_atual: Arquivos Docker existentes (se houver) e estrutura do projetoproblemas_atuais: Descrição de problemas de performance ou configuração (opcional)Analise a estrutura do projeto NestJS:
Crie um Dockerfile otimizado para desenvolvimento com as seguintes características:
Princípios obrigatórios:
node:20.5.1-slim (ou versão apropriada do projeto)@nestjs/cli globalmente para comandos nestUSER node para segurançaWORKDIR /home/node/appCMD que mantém container ativo (tail -f /dev/null ou npm run start:dev)Template base:
FROM node:20.5.1-slim
# Instalar NestJS CLI globalmente
RUN npm install -g @nestjs/cli@10.1.17
# Segurança: usuário não-root
USER node
# Diretório de trabalho
WORKDIR /home/node/app
# Manter container ativo para desenvolvimento
CMD ["tail", "-f", "/dev/null"]
Explique ao usuário:
Configure docker-compose.yaml com:
Serviço da Aplicação:
services:
app:
build: .
command: ./.docker/start.sh
ports:
- "3000:3000"
volumes:
- .:/home/node/app # Hot-reload
- /home/node/app/node_modules # Volume anônimo (performance)
- '/etc/timezone:/etc/timezone:ro'
- '/etc/localtime:/etc/localtime:ro'
extra_hosts:
- "host.docker.internal:host-gateway" # Acesso ao host
env_file:
- ./envs/.env
depends_on:
db:
condition: service_healthy
networks:
- backend
Decisões críticas a explicar:
Volume anônimo para node_modules:
volumes:
- .:/home/node/app
- /home/node/app/node_modules # ✅ CRUCIAL
host.docker.internal:
extra_hosts:
- "host.docker.internal:host-gateway"
Timezone sync:
volumes:
- '/etc/timezone:/etc/timezone:ro'
- '/etc/localtime:/etc/localtime:ro'
Para cada serviço externo necessário, configure com health checks:
PostgreSQL:
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: ${DB_DATABASE:-dev_db}
POSTGRES_USER: ${DB_USER:-dev_user}
POSTGRES_PASSWORD: ${DB_PASSWORD:-dev_pass}
ports:
- "${DB_PORT:-5432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-dev_user}"]
interval: 5s
timeout: 3s
retries: 10
start_period: 30s
networks:
- backend
MySQL:
db:
image: mysql:8.0.30-debian
environment:
MYSQL_DATABASE: ${DB_DATABASE:-dev_db}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-dev_pass}
ports:
- "${DB_PORT:-3306}:3306"
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u$$MYSQL_USER", "-p$$MYSQL_ROOT_PASSWORD"]
interval: 5s
timeout: 3s
retries: 10
start_period: 30s
networks:
- backend
Redis:
redis:
image: redis:7-alpine
ports:
- "${REDIS_PORT:-6379}:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
networks:
- backend
RabbitMQ:
rabbitmq:
image: rabbitmq:3-management-alpine
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-dev_user}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS:-dev_pass}
ports:
- "${RABBITMQ_PORT:-5672}:5672"
- "${RABBITMQ_MGMT_PORT:-15672}:15672"
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
interval: 5s
timeout: 3s
retries: 10
networks:
- backend
Explique ao usuário:
Crie .docker/start.sh:
#!/bin/bash
# Verifica se node_modules existe e se package.json foi modificado
if [ ! -d "node_modules" ] || [ package.json -nt node_modules ]; then
echo "📦 Instalando dependências..."
npm ci
fi
echo "🚀 Iniciando aplicação em modo desenvolvimento..."
npm run start:dev
Torne o script executável:
chmod +x .docker/start.sh
Explique ao usuário:
npm ci é mais rápido e determinísticoCrie docker-compose.dev.yaml para ajustes específicos de desenvolvimento:
version: '3.8'
services:
app:
environment:
NODE_ENV: development
DEBUG: '*' # Habilita debug logs
stdin_open: true # Para debugging interativo
tty: true
# Override para persistência em dev
db:
volumes:
- ./.docker/dbdata:/var/lib/postgresql/data:delegated
Uso:
# Desenvolvimento local com persistência
docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml up
Crie .dockerignore completo para otimizar COPY:
# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build outputs
dist/
build/
# Tests
coverage/
.nyc_output/
# IDE
.vscode/
.idea/
*.swp
*.swo
# Git
.git/
.gitignore
.github/
# Docker
.docker/dbdata/
.docker/logs/
docker-compose*.yaml
Dockerfile*
.dockerignore
# Environment
.env
.env.*
envs/
# Documentation
*.md
docs/
# OS
.DS_Store
Thumbs.db
# Misc
.history/
tmp/
temp/
Explique ao usuário:
Estruture envs/ com templates:
envs/.env.example:
# Application
NODE_ENV=development
APP_PORT=3000
# Database
DB_HOST=db
DB_PORT=5432
DB_DATABASE=dev_db
DB_USER=dev_user
DB_PASSWORD=dev_pass
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
# RabbitMQ
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_USER=dev_user
RABBITMQ_PASS=dev_pass
Instruções ao usuário:
# Setup inicial
cp envs/.env.example envs/.env
# Edite .env com valores locais
nano envs/.env
Configure .vscode/launch.json para debug remoto:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Docker: Attach to Node",
"remoteRoot": "/home/node/app",
"localRoot": "${workspaceFolder}",
"protocol": "inspector",
"port": 9229,
"restart": true,
"sourceMaps": true,
"skipFiles": ["<node_internals>/**"]
}
]
}
Modifique docker-compose.dev.yaml:
services:
app:
command: npm run start:debug # Em vez de start:dev
ports:
- "3000:3000"
- "9229:9229" # Debug port
Adicione script em package.json:
{
"scripts": {
"start:debug": "nest start --debug 0.0.0.0:9229 --watch"
}
}
Forneça ao usuário esta lista de comandos:
Iniciar ambiente:
# Primeira vez (build)
docker-compose up --build
# Starts subsequentes (mais rápido)
docker-compose up
# Background
docker-compose up -d
# Com override de dev
docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml up
Executar comandos no container:
# Shell interativo
docker-compose exec app bash
# Executar comando único
docker-compose exec app npm run test
docker-compose exec app npm run lint
docker-compose exec app npx nest g module users
# Como root (se necessário)
docker-compose exec -u root app bash
Logs e debugging:
# Ver logs
docker-compose logs -f app
# Ver logs de todos os serviços
docker-compose logs -f
# Últimas 100 linhas
docker-compose logs --tail=100 app
Limpeza:
# Parar containers
docker-compose down
# Parar e remover volumes (⚠️ perde dados)
docker-compose down -v
# Remover imagens
docker-compose down --rmi all
# Limpeza completa do sistema
docker system prune -a --volumes
Resetar banco de dados:
# Parar, remover volumes e reiniciar
docker-compose down -v
docker-compose up -d db
docker-compose exec app npm run migrate
Cache de node_modules (melhor abordagem):
Se performance for crítica, use esta estratégia:
services:
app:
volumes:
- .:/home/node/app
- node_modules:/home/node/app/node_modules # Volume nomeado
- '/etc/timezone:/etc/timezone:ro'
- '/etc/localtime:/etc/localtime:ro'
volumes:
node_modules: # Volume nomeado (mais rápido que anônimo)
Ganho: 50-70% mais rápido que volume mount normal
Delegated/Cached mount modes (macOS):
volumes:
- .:/home/node/app:delegated # Prioriza performance do container
Trade-off: Pequeno delay entre salvamento no host e detecção no container
Usar tmpfs para dados temporários:
services:
db:
tmpfs:
- /tmp
- /var/run/postgresql # Unix sockets em RAM
Problema: Hot-reload não funciona
Diagnóstico:
# Verificar se volumes estão corretos
docker-compose config
# Verificar se start:dev está configurado
docker-compose exec app npm run start:dev
Soluções:
.:/home/node/app)start:dev usa --watch flag:delegated ao volumeProblema: Permissões negadas
Diagnóstico:
# Verificar usuário do processo
docker-compose exec app whoami # Deve ser 'node'
# Verificar ownership dos arquivos
docker-compose exec app ls -la
Soluções:
USER node no Dockerfilesudo chown -R $USER:$USER .Problema: Database connection refused
Diagnóstico:
# Verificar se DB está healthy
docker-compose ps
# Testar conexão manualmente
docker-compose exec app nc -zv db 5432
Soluções:
depends_on com condition: service_healthyDB_HOST aponta para nome do serviço ('db', não 'localhost')Problema: Container sai imediatamente
Diagnóstico:
# Ver logs de erro
docker-compose logs app
# Verificar exit code
docker-compose ps
Soluções:
#!/bin/bash na primeira linhachmod +x .docker/start.shtail -f /dev/null temporariamente para debuggingEsta Skill é focada EXCLUSIVAMENTE em ambientes de desenvolvimento. NÃO use estas configurações para:
❌ Produção:
❌ CI/CD:
Mesmo em desenvolvimento, mantenha boas práticas:
✅ Faça:
❌ Nunca:
Decisões desta Skill priorizam velocidade de desenvolvimento:
Prioridade ALTA:
Prioridade BAIXA:
Após aplicar esta Skill, valide:
docker-compose logs -fdocker-compose up subsequente leva menos de 30sEntrada do usuário: "Configure Docker para meu projeto NestJS com PostgreSQL e Redis."
Ações esperadas:
Saída esperada:
Entrada do usuário: "Hot-reload está lento, demora 10 segundos para refletir mudanças."
Ações esperadas:
Saída esperada:
Entrada do usuário: "Como fazer debug remoto do NestJS rodando no Docker?"
Ações esperadas:
Entrada do usuário: "Tenho um projeto NestJS sem Docker, quero containerizar para desenvolvimento."
Ações esperadas:
Esta Skill assume:
No host:
No projeto:
Ferramentas opcionais:
Versão: 1.0.0 Data: 2025-11-18 Autor: SuperClaude Framework Compatibilidade: NestJS 9+, Docker Compose 2.0+