Docker Compose em produção: configuração correta
Para produção, um docker-compose.yml precisa de: restart: always (para subir automaticamente após reinicialização do servidor), healthchecks (para depends_on funcionar de verdade), logging com rotação (para não encher o disco), limites de recursos (para isolar falhas) e variáveis sensíveis em arquivo .env separado — nunca hard-coded no Compose.
Template base para produção
Estrutura mínima de um serviço de produção com todas as configurações essenciais:
services:
app:
image: minha-app:1.2.3 # versão fixa, nunca :latest em prod
restart: always
env_file: .env # variáveis sensíveis fora do compose
ports:
- "127.0.0.1:3000:3000" # bind apenas no localhost, NGINX expõe externamente
depends_on:
db:
condition: service_healthy # aguarda o banco estar pronto
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
db:
image: postgres:16
restart: always
env_file: .env
volumes:
- pg_data:/var/lib/postgresql/data
deploy:
resources:
limits:
memory: 1G
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pg_data:restart: always vs unless-stopped
Escolha a política de restart correta para cada tipo de serviço:
Arquivo .env e segredos
Variáveis sensíveis (senhas, API keys) nunca devem aparecer no docker-compose.yml — use arquivo .env:
# .env (nunca commite no git — adicione ao .gitignore)
POSTGRES_USER=appuser
POSTGRES_PASSWORD=senha_super_segura_aqui
POSTGRES_DB=producao
SECRET_KEY=chave_jwt_256_bits_aqui
# No docker-compose.yml, referencie:
# env_file: .env
# Ou por variável individual:
# environment:
# POSTGRES_USER: ${POSTGRES_USER}
# Verificar quais variáveis estão sendo resolvidas:
docker compose configVersões fixas de imagem em produção
Nunca use :latest em produção — uma atualização automática pode quebrar seu serviço silenciosamente:
# Ruim — :latest pode mudar a qualquer momento
image: postgres:latest
# Bom — versão major/minor fixa, patch automático
image: postgres:16
# Melhor — versão completamente fixa com digest (imutável)
image: postgres:16.3Estratégia de deploy sem downtime
Para deploys com downtime mínimo usando Compose puro (sem Swarm/Kubernetes):
# Pull da nova imagem enquanto a versão atual ainda está rodando
docker compose pull app
# Recria apenas o serviço atualizado (outros serviços continuam)
docker compose up -d --no-deps app
# Verificar se o healthcheck passou antes de considerar o deploy OK
docker compose ps
docker inspect app_container_1 | grep -A5 '"Health"'$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o Docker em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.