O que são containers
Containers são unidades de software que empacotam código e todas as suas dependências — bibliotecas, configurações, runtime — de forma que a aplicação rode de maneira isolada e consistente em qualquer ambiente.
A diferença fundamental entre containers e máquinas virtuais: VMs virtualizam hardware, containers virtualizam o sistema operacional. Containers são mais leves, iniciam em segundos e compartilham o kernel do host.
# Comparação de overhead: VM tradicional: ~500MB RAM + tempo de boot ~30s Container Docker: ~5-50MB RAM adicional + boot em <1s
Vantagens reais
Consistência de ambiente
O problema clássico "funciona na minha máquina" desaparece. O container carrega tudo que precisa para rodar — se funciona no desenvolvimento, funciona em produção com a mesma imagem.
Isolamento de dependências
Duas aplicações com versões conflitantes de Python, Node ou PHP podem rodar no mesmo servidor sem conflito, cada uma em seu container.
Deploy simplificado
Deploy se torna: docker pull + docker run. Rollback é: docker run com a tag da versão anterior.
Recursos com limites definidos
docker run -d \ --memory="512m" \ --cpus="1.0" \ --restart=unless-stopped \ nginx:alpine
Quando usar containers
- Aplicações web e APIs: o caso de uso mais natural para Docker. Nginx, PHP-FPM, Node.js, Python rodando em containers.
- Múltiplos serviços no mesmo servidor: isolar aplicações distintas sem o overhead de VMs.
- Ambientes de desenvolvimento padronizados: toda a equipe roda o mesmo ambiente com
docker compose up. - CI/CD: pipelines de build e test em containers efêmeros garantem reprodutibilidade.
- Microserviços: cada serviço em seu container, com deploy independente.
- Serviços com versões fixas: fixar a versão do Postgres, Redis ou outro serviço e garantir que não muda sem intenção.
Quando não usar containers
- Bancos de dados em produção de alta escala: o overhead de I/O do volume Docker pode impactar performance. Para ambientes menores é aceitável; para alto volume, bare metal ou VMs com storage dedicado são melhores.
- Aplicações que precisam de acesso ao hardware: GPU passthrough, devices seriais, etc. — é possível, mas complexo.
- Sistemas legados com dependências profundas do OS: aplicações que assumem uma versão específica de kernel ou que modificam configurações do sistema são difíceis de containerizar.
- Quando a equipe não tem familiaridade: container mal configurado em produção é pior que servidor bem configurado. Invista em treinamento antes.
Boas práticas
Docker Compose para múltiplos serviços
# docker-compose.yml — exemplo prático
services:
app:
image: php:8.2-fpm-alpine
volumes:
- ./app:/var/www/html
depends_on:
- db
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./app:/var/www/html
depends_on:
- app
restart: unless-stopped
db:
image: mariadb:11
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_pass
MYSQL_DATABASE: wsul_app
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
volumes:
db_data:
Segurança em containers
- Nunca rode containers como root — use
USERno Dockerfile - Use imagens Alpine ou Distroless para reduzir a superfície de ataque
- Escanear imagens com
docker scanou Trivy antes de produção - Mantenha imagens atualizadas — vulnerabilidades em imagens base são comuns
Conclusão
Containers resolvem problemas reais de consistência, isolamento e deploy. Mas não são a solução universal que o hype sugere. A decisão deve ser baseada nos requisitos do workload, na maturidade da equipe e no trade-off de complexidade operacional versus benefícios concretos.