YAML para Docker Compose: Padrões de Configuração e Dicas
O Docker Compose usa YAML para definir aplicações multi-contêiner. Um docker-compose.yml bem estruturado é a diferença entre um ambiente de desenvolvimento tranquilo e horas depurando problemas de contêineres. Este guia aborda padrões essenciais e armadilhas comuns.
Estrutura Básica
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- api
api:
build: ./api
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://db:5432/myapp
depends_on:
- db
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: secret
volumes:
pgdata:
Variáveis de Ambiente
Inline
services:
api:
environment:
NODE_ENV: production
PORT: "3000"
DEBUG: "false"
A Partir de Arquivo
services:
api:
env_file:
- .env
- .env.local # Sobrescreve valores do .env
Substituição de Variáveis
Referencie variáveis de ambiente do host:
services:
api:
image: myapp:${TAG:-latest} # Padrão "latest"
environment:
API_KEY: ${API_KEY} # Obrigatório - falha se não definido
LOG_LEVEL: ${LOG_LEVEL:-info} # Padrão "info"
Rede
Redes Personalizadas
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:
internal: true # Sem acesso externo
Serviços na mesma rede podem se comunicar pelo nome do serviço. O serviço db é acessível apenas a partir do api, não do web.
Mapeamento de Portas
ports:
- "8080:80" # host:contêiner
- "443:443"
- "127.0.0.1:3000:3000" # Vincular apenas ao localhost
- "3000" # Porta do host aleatória
Volumes
Volumes Nomeados (Persistentes)
services:
db:
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
driver: local
Bind Mounts (Desenvolvimento)
services:
api:
volumes:
- ./src:/app/src # Código-fonte
- /app/node_modules # Volume anônimo (previne sobrescrita)
O padrão de volume anônimo (/app/node_modules) impede que o bind mount do host sobrescreva as dependências instaladas no contêiner.
Verificações de Saúde
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
api:
depends_on:
db:
condition: service_healthy
Isso garante que o api só inicie após o db passar nas verificações de saúde — não apenas quando o contêiner inicia.
Campos de Extensão (Padrões DRY)
Use campos com prefixo x- com âncoras YAML para reduzir repetição:
x-common: &common
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
x-env: &common-env
TZ: UTC
LOG_FORMAT: json
services:
api:
<<: *common
build: ./api
environment:
<<: *common-env
PORT: "3000"
worker:
<<: *common
build: ./worker
environment:
<<: *common-env
QUEUE: default
Para mais informações sobre âncoras YAML, veja nosso guia de âncoras e aliases YAML.
Compose Multi-Estágio
Desenvolvimento vs Produção
# docker-compose.yml (base)
services:
api:
build: ./api
environment:
DATABASE_URL: postgres://db:5432/myapp
# docker-compose.override.yml (dev - carregado automaticamente)
services:
api:
volumes:
- ./api/src:/app/src
environment:
NODE_ENV: development
DEBUG: "true"
ports:
- "3000:3000"
- "9229:9229" # Porta de depuração
# docker-compose.prod.yml
services:
api:
environment:
NODE_ENV: production
deploy:
replicas: 3
# Desenvolvimento (carrega override automaticamente)
docker compose up
# Produção
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
Armadilhas Comuns
1. Números de Porta Sem Aspas
# ARRISCADO - YAML interpreta 80:80 como um número base-60
ports:
- 80:80
# SEGURO - sempre use aspas
ports:
- "80:80"
2. Variáveis de Ambiente Booleanas
# ERRADO - YAML converte para booleano
environment:
DEBUG: true # Torna-se Python True, não a string "true"
# CORRETO - coloque aspas em todos os valores de env
environment:
DEBUG: "true"
3. Timing do depends_on
depends_on aguarda apenas o início do contêiner, não a prontidão:
# O contêiner inicia, mas o DB pode não estar pronto
depends_on:
- db
# Aguardar a verificação de saúde
depends_on:
db:
condition: service_healthy
Valide seus arquivos Docker Compose com nosso Validador YAML.
FAQ
Qual é a diferença entre docker-compose.yml e compose.yml?
Ambos os nomes de arquivo funcionam. compose.yml é a convenção mais recente recomendada pelo Docker. docker-compose.yml é o nome legado. O Docker Compose v2+ procura ambos, preferindo compose.yml se ambos existirem. Para novos projetos, use compose.yml.
Devo usar Docker Compose em produção?
O Docker Compose é excelente para desenvolvimento e deploys simples. Para produção em escala, considere Docker Swarm (usa arquivos Compose nativamente) ou Kubernetes. A vantagem do Compose é que sua configuração de desenvolvimento informa diretamente a produção, reduzindo diferenças entre ambientes.
Recursos Relacionados
- Validador YAML — Valide YAML do Docker Compose
- Âncoras e Aliases YAML — Padrões de configuração DRY
- Tutorial de Sintaxe YAML — Fundamentos de YAML