Docker: Ajuste de Performance e Resolução de Problemas
Última atualização: 2026-08-26
Está enfrentando problemas com contêineres no ambiente de produção — alto uso de CPU? Sobrecarga de memória? I/O lento? Você precisa de uma abordagem sistemática de resolução de problemas.
1. O Que Você Vai Aprender
- Métodos para Identificar Gargalos de Performance
- Cenários Comuns de Falha e Causas Raiz
- Ferramentas de Depuração de Contêineres
- Resolução de Problemas de Latência de Rede
- Gestão de Espaço em Disco
2. Uma História Sobre um Alerta de Madrugada
(1) Ponto de Dor: Latência da API disparou de 50 ms para 5 s
A latência da API no ambiente de produção disparou de 50 ms para 5 s, gerando uma enxurrada de reclamações de usuários. Alice usou docker stats para descobrir que, embora o uso da CPU não estivesse alto, os tempos de espera de I/O estavam extremamente altos, e os contêineres pareciam estar "travados."
(2) Uma Abordagem Sistemática para Resolução de Problemas
Alice usou iostat para identificar que o driver de log estava causando o I/O de disco no limite; após trocar o driver de log, o problema foi resolvido.
# Etapa 1: Verificar uso de recursos
docker stats --no-stream
# Etapa 2: Verificar I/O do host
iostat -x 1 5
# Etapa 3: Identificar o gargalo
docker system df -v
(3) Benefícios: 5 segundos → 50 milissegundos, 10 minutos de tempo de recuperação
Levou apenas 10 minutos do alerta até a resolução — a resolução sistemática de problemas é 100 vezes mais eficiente do que simplesmente "tentar reiniciar."
3. Árvore de Decisão para Resolução de Problemas de Performance
(1) Os Quatro Principais Gargalos e Suas Ferramentas Correspondentes
graph TB
START["Problema de Performance"] --> CPU{"CPU alta?"}
CPU -->|Sim| C1["docker stats<br/>top / htop"]
CPU -->|Não| MEM{"Uso de memória alto?"}
MEM -->|Sim| M1["docker stats<br/>/proc/meminfo"]
MEM -->|Não| IO{"Espera de I/O alta?"}
IO -->|Sim| I1["iostat -x<br/>docker system df"]
IO -->|Não| NET{"Rede lenta?"}
NET -->|Sim| N1["iperf / ping<br/>tcpdump"]
(2) Ferramentas Comuns de Resolução de Problemas
| Ferramenta | Função | Caso de Uso |
|---|---|---|
docker stats |
Uso de Recursos do Contêiner | Visão Geral de CPU/Memória/I/O |
docker system df |
Uso de Disco do Docker | Resolução de Disco Cheio |
docker events |
Fluxo de Eventos do Contêiner | OOM/Reinício/Saída Anormal |
docker logs |
Logs do Contêiner | Erros de Aplicação |
docker inspect |
Configuração do Contêiner | Status/Código de Saída/Rede |
iostat |
Estatísticas de I/O de Disco | Gargalos de I/O |
iperf |
Teste de Largura de Banda de Rede | Gargalos de Rede |
nsenter |
Entrar no Namespace do Contêiner | Depuração Avançada |
4. Resolução de Gargalos de CPU
▶ Exemplo: Monitorando Recursos com docker stats (Dificuldade: ⭐)
# Estatísticas em tempo real para todos os contêineres
docker stats
# Snapshot único
docker stats --no-stream
# Formato personalizado
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
▶ Exemplo: Contêiner stress simula carga de CPU (Dificuldade: ⭐⭐)
# Executar stress para simular carga de CPU
docker run --rm --name stress-test \
--cpus=1 \
progrium/stress --cpu 1 --timeout 30s
# Monitorar com docker stats (em outro terminal)
docker stats stress-test --no-stream
5. Resolução de Gargalos de Memória
(1) Problemas Comuns de Memória
| Sintoma | Código de Saída | Causa | Solução |
|---|---|---|---|
| OOM Kill | 137 | Excedeu o limite --memory | Aumentar o limite ou otimizar o uso de memória |
| Vazamento de Memória | Aumento Gradual | Bug na Aplicação | Analisar um Heap Dump |
| Alto uso de cache | 0 | Cache do sistema de arquivos | Comportamento normal (pode ser recuperado) |
▶ Exemplo: Simulando um OOM de Contêiner (Dificuldade: ⭐⭐⭐)
# Iniciar contêiner com limite de 50 MB de memória
docker run -d --name oom-test \
--memory=50m \
--restart=on-failure:3 \
progrium/stress --vm 1 --vm-bytes 100M --timeout 10s
# Observar eventos OOM
docker events --filter event=oom --since 1m
# Verificar código de saída
docker inspect oom-test --format='ExitCode: {{.State.ExitCode}}, OOMKilled: {{.State.OOMKilled}}'
6. Resolução de Gargalos de I/O de Disco
▶ Exemplo: Análise de Disco com docker system df (Dificuldade: ⭐⭐)
# Mostrar uso de disco do Docker
docker system df
# Detalhamento completo
docker system df -v
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 12 5 4.2GB 2.8GB (66%)
Containers 8 3 350MB 280MB (80%)
Local Volumes 5 3 1.2GB 500MB (41%)
Build Cache 45 0 800MB 800MB (100%)
▶ Exemplo: Política de Limpeza de Disco (Dificuldade: ⭐⭐)
# Remover dados não utilizados (imagens, contêineres, volumes, cache de build)
docker system prune
# Mais agressivo: remover todas as imagens não utilizadas (não apenas dangling)
docker system prune -a
# Remover apenas o cache de build
docker builder prune
# Remover volumes (AVISO: exclui dados)
docker volume prune
(1) Comparação de Drivers de Armazenamento
| Driver | Performance | Estabilidade | Recomendação |
|---|---|---|---|
| overlay2 | Alta | ✅ Estável | ✅ Recomendação padrão |
| aufs | Média | ❌ Kernel antigo | ❌ Obsoleto |
| devicemapper | Baixa | ❌ Configuração complexa | ❌ Não recomendado |
| zfs | Média | ✅ Estável | Cenários específicos |
| btrfs | Média | ❌ Instável | ❌ Não recomendado |
7. Resolução de Problemas de Rede
▶ Exemplo: Teste de Largura de Banda de Rede com iperf (Dificuldade: ⭐⭐⭐)
# Iniciar servidor iperf3 em um contêiner
docker run -d --name iperf-server --network host networkstatic/iperf3 -s
# Executar cliente iperf3 de outro contêiner
docker run --rm --network host networkstatic/iperf3 -c localhost -t 10
# Testar entre dois contêineres em redes diferentes
docker run --rm --network app-net networkstatic/iperf3 -c db -t 5
▶ Exemplo: Rastreamento de Eventos com Docker Events (Dificuldade: ⭐⭐)
# Monitorar eventos do ciclo de vida do contêiner
docker events --filter type=container
# Filtrar por eventos específicos
docker events --filter event=oom --filter event=die --filter event=restart
# Filtro baseado em tempo
docker events --since "2024-01-15T03:00:00" --until "2024-01-15T04:00:00"
8. Depuração Avançada: nsenter
▶ Exemplo: nsenter para entrar no namespace do contêiner (Dificuldade: ⭐⭐⭐)
# Obter o PID principal do contêiner
PID=$(docker inspect --format='{{.State.Pid}}' myapp)
# Entrar no namespace de rede do contêiner para depuração
nsenter -t $PID -n tcpdump -i eth0 -c 100 port 8080
# Entrar no namespace de processos do contêiner
nsenter -t $PID -p -m strace -p 1
docker exec — ele entra diretamente no namespace Linux do contêiner, sem exigir um shell dentro do contêiner. É adequado para depurar imagens scratch ou distroless.
9. Guia de Resolução de Problemas: Problemas Comuns e Soluções
| Sintoma | Comando de Diagnóstico | Causas Comuns | Solução |
|---|---|---|---|
| Reinícios frequentes do contêiner | docker ps -a + docker logs |
OOM / Falhas na aplicação | Aumentar memória / Corrigir bugs / Política de restart |
| Espaço em disco cheio | docker system df -v |
Acúmulo de logs/imagens/volumes | docker system prune + Rotação de logs |
| Tempo limite de conexão de rede | docker exec ping + nc |
Erro de configuração de rede | Verificar rede/DNS/porta |
| Build Lento | docker build --progress=plain |
Cache Expirado | Ajustar Ordem do COPY |
| Falha na inicialização do contêiner | docker logs + docker inspect |
Erro de configuração/dependências ausentes | Corrigir configuração/verificar dependências |
| Alta Espera de I/O | iostat -x |
Driver de log/escritas pesadas | Trocar driver de log/otimizar escritas |
10. Exemplo Completo: Resolvendo Problemas de OOM em Contêineres
# ============================================
# Passo a passo completo: Diagnóstico e correção de OOM
# Abrange: stats, events, logs, inspect, correção
# ============================================
# 1. Implantar o contêiner problemático
docker run -d \
--name leaky-app \
--memory=100m \
--restart=on-failure:5 \
-p 8080:8080 \
myapp:1.0
# 2. Monitorar uso de recursos
docker stats leaky-app --no-stream
# 3. Simular vazamento de memória (acionar OOM)
docker exec leaky-app python -c "
import itertools
data = []
for i in itertools.count():
data.append('x' * 1024 * 1024) # 1 MB cada
if i % 10 == 0:
import time; time.sleep(0.1)
"
# 4. Capturar evento OOM
docker events --filter container=leaky-app --filter event=oom --since 1m
# 5. Verificar código de saída e status OOM
docker inspect leaky-app --format='
ExitCode: {{.State.ExitCode}}
OOMKilled: {{.State.OOMKilled}}
Memory Limit: {{.HostConfig.Memory}}
'
# 6. Verificar logs da aplicação para padrões de memória
docker logs --tail 100 leaky-app 2>&1 | grep -i "memory\|alloc\|oom"
# 7. Corrigir: aumentar limite de memória
docker stop leaky-app && docker rm leaky-app
docker run -d \
--name leaky-app \
--memory=512m \
--restart=on-failure:5 \
--log-opt max-size=10m \
--log-opt max-file=3 \
-p 8080:8080 \
myapp:1.0
# 8. Configurar alerta de monitoramento
docker events --filter event=oom | while read event; do
echo "ALERT: OOM detected at $(date)" >> /var/log/docker-alerts.log
done
❓ Perguntas Frequentes
P: Como resolver problemas de performance de contêineres em camadas? R: Um método de quatro etapas: ① Use
docker statspara ver uma visão geral de CPU, memória e I/O; ② Selecione a ferramenta apropriada com base na métrica mais alta (CPU →top, memória →smem, I/O →iostat, rede →iperf); ③ Identifique o contêiner ou processo específico; ④ Analise os logs da aplicação para encontrar a causa raiz.
P: Qual é melhor, overlay2 ou aufs? R: overlay2 é melhor; é o driver de armazenamento padrão e único recomendado do Docker. aufs foi descontinuado e não é mais suportado no Docker 24 e posteriores. overlay2 oferece melhor performance, implementação mais simples e suporte comunitário mais ativo.
P: Como liberar espaço quando o disco do contêiner está cheio? R:
docker system df -vVerifique o que está ocupando mais espaço → Limpe de acordo: ① Imagens:docker image prune -a; ② Cache de build:docker builder prune; ③ Contêineres:docker container prune; ④ Volumes:docker volume prune(Proceda com cautela — isso excluirá dados); ⑤ Tudo:docker system prune -a.
P: Como resolver problemas de I/O lento em contêineres? R: ①
docker statsVerifique a coluna BlockIO; ② No hostiostat -x 1, verifique %util e await; ③docker system df -vVerifique o uso do driver de armazenamento; ④ Causas comuns: o driver de log encheu o disco, muitas camadas overlay2 ou um bind mount para um disco lento.
P: Como testar a latência de rede para contêineres? R: Use iperf3: contêiner servidor
iperf3 -s, contêiner clienteiperf3 -c server. Teste taxa de transferência e latência. Para testar entre contêineres, eles devem estar na mesma rede ou usar a opção --network host.
📖 Resumo
- Árvore de Decisão de Performance: CPU → Memória → I/O → Rede; resolva camada por camada
docker statsMonitoramento em tempo real,docker system dfAnálise de disco- Resolução de OOM: Use
docker eventseinspectpara verificar o problema, depois aumente a memória ou corrija a aplicação - Limpeza de Disco:
docker system pruneLimpeza com um clique, rotação de logs para evitar acúmulo - overlay2 é o único driver de armazenamento recomendado
- nsenter: Entre no namespace do contêiner para depuração avançada
📝 Exercícios
- Exercício Básico (Dificuldade: ⭐): Use o contêiner
stresspara simular carga de CPU e usedocker statspara monitorar as mudanças no uso da CPU. - Exercício Avançado (Dificuldade: ⭐⭐): Use
docker system df -vpara analisar o uso de disco, executedocker system prune -apara limpar e compare a diferença de espaço em disco antes e depois da limpeza. - Desafio (Dificuldade: ⭐⭐⭐): Use iperf3 para testar a largura de banda de rede entre dois contêineres e compare as diferenças de performance entre redes bridge e host.