Deploy de aplicações com Docker Compose
1. Introdução ao Docker Compose para Deploy
Docker Compose é uma ferramenta que permite definir e gerenciar aplicações multi-contêiner através de um arquivo YAML declarativo. Embora seja amplamente utilizado em ambientes de desenvolvimento, o Docker Compose também é uma solução viável para deploy em produção, especialmente em cenários de pequena e média escala.
A principal diferença entre desenvolvimento local e deploy real está na configuração: em produção, é necessário considerar aspectos como persistência de dados, segurança, logs centralizados e estratégias de atualização sem downtime. Cenários ideais para deploy com Docker Compose incluem aplicações web com banco de dados, sistemas de microserviços simples, plataformas CMS e ferramentas internas de equipe.
2. Estrutura do Projeto e Arquivo docker-compose.yml
Um projeto bem estruturado facilita o deploy e a manutenção. A organização recomendada inclui:
meu-projeto/
├── docker-compose.yml
├── .env
├── app/
│ ├── Dockerfile
│ └── src/
├── db/
│ └── init.sql
└── nginx/
└── default.conf
O arquivo docker-compose.yml define serviços, redes e volumes. Exemplo básico:
version: '3.8'
services:
web:
build: ./app
ports:
- "80:3000"
env_file: .env
depends_on:
- db
networks:
- app-network
db:
image: postgres:15-alpine
volumes:
- postgres-data:/var/lib/postgresql/data
env_file: .env
networks:
- app-network
volumes:
postgres-data:
networks:
app-network:
driver: bridge
Boas práticas incluem o uso de arquivos .env para separar configurações sensíveis do código, evitando hardcoding de senhas e variáveis de ambiente.
3. Configuração de Serviços para Produção
Imagens otimizadas são essenciais para deploys eficientes. O uso de Dockerfile multi-stage reduz o tamanho da imagem final:
# Estágio de build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Estágio de produção
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]
O mapeamento de portas deve ser controlado: apenas expor portas necessárias para o mundo externo. Serviços internos (como bancos de dados) não devem ser expostos publicamente.
Dependências entre serviços são gerenciadas com depends_on e healthchecks:
services:
web:
depends_on:
db:
condition: service_healthy
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
4. Gerenciamento de Dados e Persistência
Volumes nomeados são a forma recomendada para dados persistentes em produção. Diferente de bind mounts, volumes são gerenciados pelo Docker e não dependem da estrutura de diretórios do host:
volumes:
postgres-data:
redis-data:
uploads:
Bind mounts podem ser úteis para configurações e logs que precisam ser acessados diretamente no host:
services:
nginx:
volumes:
- ./nginx/logs:/var/log/nginx
- ./nginx/conf.d:/etc/nginx/conf.d:ro
Para backup de volumes em produção, utilize comandos como:
docker run --rm -v postgres-data:/data -v $(pwd):/backup alpine tar czf /backup/postgres-backup.tar.gz -C /data .
A restauração segue o processo inverso:
docker run --rm -v postgres-data:/data -v $(pwd):/backup alpine tar xzf /backup/postgres-backup.tar.gz -C /data
5. Redes e Segurança no Deploy
Redes isoladas garantem que apenas serviços autorizados se comuniquem entre si. Crie redes específicas para diferentes camadas da aplicação:
networks:
frontend:
backend:
database:
A exposição de portas deve ser mínima. Apenas o serviço de entrada (geralmente nginx ou um API gateway) deve ter portas mapeadas para o host:
services:
nginx:
ports:
- "80:80"
- "443:443"
networks:
- frontend
api:
expose:
- "3000"
networks:
- frontend
- backend
db:
expose:
- "5432"
networks:
- backend
Para variáveis sensíveis, utilize Docker Secrets (modo swarm) ou arquivos .env protegidos com permissões restritas:
services:
app:
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
6. Estratégias de Deploy e Atualização
Comandos essenciais para gerenciamento em produção:
# Iniciar serviços em background
docker-compose up -d
# Parar e remover contêineres
docker-compose down
# Reiniciar serviços
docker-compose restart
# Visualizar status
docker-compose ps
Para atualizações sem downtime, utilize a estratégia de scale com versões:
# Subir nova versão sem parar a atual
docker-compose up -d --no-deps --scale web=2 --no-recreate
# Verificar se a nova versão está saudável
docker-compose ps
# Remover versão antiga
docker-compose up -d --no-deps --scale web=1
O versionamento de imagens facilita rollbacks:
services:
web:
image: registry.exemplo.com/app:v2.1.0
Para rollback, basta alterar a tag da imagem e executar docker-compose up -d.
7. Monitoramento e Logs em Produção
Logs centralizados são fundamentais para debugging. O Docker Compose oferece coleta nativa:
# Visualizar logs em tempo real
docker-compose logs -f
# Logs de serviço específico
docker-compose logs web
# Últimas 100 linhas
docker-compose logs --tail=100 web
Para monitoramento avançado, integre com Prometheus e Grafana:
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
Healthchecks automáticos garantem que serviços sejam reiniciados em caso de falha:
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
8. Considerações Finais e Próximos Passos
O Docker Compose é uma ferramenta poderosa para deploy de aplicações multi-serviço, mas possui limitações em ambientes de grande escala. Para clusters com múltiplos nós, alta disponibilidade e balanceamento de carga avançado, considere migrar para orquestradores como Kubernetes ou Docker Swarm.
Checklist de boas práticas para deploy seguro:
- [ ] Utilizar imagens oficiais e atualizadas
- [ ] Implementar healthchecks em todos os serviços
- [ ] Configurar restart policies (always, unless-stopped)
- [ ] Separar ambientes com arquivos docker-compose.override.yml
- [ ] Realizar backups periódicos dos volumes
- [ ] Utilizar redes isoladas e exposição mínima de portas
- [ ] Versionar imagens e manter histórico de releases
- [ ] Monitorar logs e métricas continuamente
Com essas práticas, o Docker Compose se torna uma solução robusta e confiável para deploy de aplicações em produção, oferecendo simplicidade sem abrir mão da segurança e da escalabilidade.
Referências
- Documentação Oficial do Docker Compose — Guia completo sobre instalação, configuração e uso do Docker Compose em produção.
- Docker Compose em Produção: Boas Práticas — Orientações específicas da Docker para deploy de aplicações em ambiente produtivo.
- Multi-stage Builds no Docker — Tutorial oficial sobre otimização de imagens com builds multi-estágio.
- Healthchecks em Docker Compose — Documentação detalhada sobre configuração de healthchecks para serviços.
- Gerenciamento de Secrets no Docker — Guia oficial sobre como gerenciar informações sensíveis em contêineres Docker.
- Monitoramento com Prometheus e Grafana — Tutorial prático de integração do Prometheus com Docker Compose para monitoramento.
- Estratégias de Deploy com Docker Compose — Artigo técnico da DigitalOcean sobre deploy de aplicações Node.js com Docker Compose.