Container parou, aplicação não responde, disco encheu do nada. Se você roda Docker em produção, já passou por isso. Aqui vai o que eu aprendi resolvendo esses problemas no mundo real.
Diagnóstico rápido: os primeiros comandos
Antes de qualquer coisa, entenda o estado atual:
| |
O docker system df é o primeiro lugar para olhar quando disco enche. Imagens antigas, volumes órfãos e build cache acumulam rápido.
Container reiniciando em loop
O clássico Restarting (1) 5 seconds ago. O container sobe e morre, sobe e morre:
| |
Exit codes que importam:
- 0: Saiu normalmente (mas não deveria ter saído)
- 1: Erro genérico da aplicação
- 137: Killed (OOM killer ou
docker kill) - 139: Segmentation fault
- 143: SIGTERM (graceful shutdown)
Se o exit code é 137 e OOMKilled é true, aumente o limite de memória ou investigue memory leak.
Disco cheio: o vilão silencioso
Docker é um devorador de disco. As causas mais comuns:
| |
Mas o problema mais traiçoeiro é o log do container. Por padrão, Docker não limita o tamanho dos logs:
| |
A solução é configurar log rotation no /etc/docker/daemon.json:
| |
Isso limita cada container a 30MB de logs (3 arquivos de 10MB). Aplique e reinicie o Docker — mas atenção: isso só vale para containers novos. Os existentes mantêm a config antiga.
Rede: container não conecta
Problemas de rede em Docker são frustrantes porque parecem aleatórios:
| |
Se DNS externo não funciona, geralmente é porque o /etc/resolv.conf do host aponta para 127.0.0.53 (systemd-resolved) e o container não consegue usar. Solução:
| |
Investigando dentro do container
Às vezes você precisa entrar no container para investigar, mas ele não tem as ferramentas:
| |
O nsenter é a arma secreta. Ele entra no namespace do container usando o PID do processo no host. Funciona mesmo quando o container não tem shell.
Container saudável mas aplicação lenta
O container está rodando, health check passa, mas a aplicação está lenta:
| |
Se strace mostra tempo em futex = lock contention. Se mostra tempo em epoll_wait = esperando I/O ou conexão. Se mostra tempo em read/write = I/O lento.
Docker Compose: problemas comuns
| |
O docker compose config é essencial para debugar problemas de variáveis de ambiente. Ele mostra o YAML final com todas as variáveis resolvidas.
Overlay2: quando o storage driver dá problema
| |
Se /var/lib/docker/overlay2 está enorme e docker system prune não resolve, provavelmente tem layers de imagens antigas que ainda são referenciadas. O nuclear é:
| |
Health checks que funcionam
Um health check mal configurado é pior que nenhum:
| |
O start_period é crucial. Sem ele, o container pode ser marcado como unhealthy antes de terminar de inicializar. 30 segundos é um bom padrão para a maioria das aplicações.
Checklist de produção
Antes de colocar qualquer container em produção:
- Log rotation configurado (
max-size,max-file) - Limites de memória definidos (
mem_limit) - Health check configurado
- Restart policy (
unless-stoppedouon-failure) - Volumes para dados persistentes (não depender do writable layer)
- Rede dedicada (não usar a bridge default)
- Usuário não-root no Dockerfile (
USER) -
.dockerignoreconfigurado (build mais rápido e seguro)
Docker em produção é simples até dar problema. Quando dá, ter esses comandos na ponta dos dedos faz a diferença entre resolver em 5 minutos ou ficar 2 horas no escuro. Salve esse post — você vai precisar dele às 3 da manhã.