Debugar um container que não sobe
Container que morre logo depois de iniciar quase sempre falha por um destes cinco motivos: comando errado, permissão, variável ausente, arquivo que não está onde deveria, ou dependência inalcançável. Este roteiro elimina um por vez.
1. Leia o código de saída
Seção intitulada “1. Leia o código de saída”docker ps -a --format '{{.Names}}\t{{.Status}}'docker inspect <container> --format '{{.State.ExitCode}} {{.State.Error}} {{.State.OOMKilled}}'| Código | Significado usual |
|---|---|
0 |
Terminou normalmente — o processo não era de longa duração |
1 |
Erro genérico da aplicação; leia o log |
126 |
Arquivo encontrado, mas sem permissão de execução |
127 |
Comando não encontrado (caminho errado, ou binário ausente na imagem) |
137 |
SIGKILL — quase sempre OOM, falta de memória |
139 |
Segfault — binário incompatível com a arquitetura ou libc |
143 |
SIGTERM — alguém pediu parada |
OOMKilled: true no inspect encerra a investigação: aumente a memória disponível ou reduza
o consumo.
2. Veja os logs, inclusive os da execução anterior
Seção intitulada “2. Veja os logs, inclusive os da execução anterior”docker logs <container> 2>&1 | tail -50docker logs --tail 100 --timestamps <container>No Kubernetes, o container atual pode ter acabado de nascer:
kubectl logs <pod> -n <ns> --previouskubectl describe pod <pod> -n <ns> | sed -n '/Events/,$p'Se o log está vazio, a aplicação provavelmente nem começou — o problema é anterior a ela (passo 3 em diante).
3. Entre no container sobrescrevendo o entrypoint
Seção intitulada “3. Entre no container sobrescrevendo o entrypoint”O comando padrão falha, mas a imagem continua inspecionável:
docker run --rm -it --entrypoint sh loja:1.8.3# e então, lá dentro:ls -l /appwhich python || ls -l /bin/lojaecho $PATHSe a imagem não tem shell (distroless, scratch), copie os arquivos para fora e inspecione:
id=$(docker create loja:1.8.3)docker cp "$id:/bin/loja" ./loja-binario && docker rm "$id"file ./loja-binario # arquitetura e se é estático ou dinâmicoNo Kubernetes, o equivalente é um container efêmero ao lado do Pod:
kubectl debug -it <pod> -n <ns> --image=busybox --target=<container>4. Confira permissões e usuário
Seção intitulada “4. Confira permissões e usuário”docker run --rm -it --entrypoint sh loja:1.8.3 -c 'id; ls -l /app; ls -l /bin/loja'Causas frequentes quando a imagem roda como não-root:
- Binário sem bit de execução (
chmod +xno build). - Diretório de trabalho ou de cache sem permissão de escrita — com
readOnlyRootFilesystem, monte um volume em/tmp. - Porta abaixo de 1024 exigindo privilégio: use 8080 em vez de 80.
- Volume montado com dono diferente do usuário do container (
fsGroupresolve no Kubernetes).
5. Confira variáveis e montagens
Seção intitulada “5. Confira variáveis e montagens”docker inspect <container> --format '{{json .Config.Env}}' | jqdocker inspect <container> --format '{{json .Mounts}}' | jqkubectl get pod <pod> -n <ns> -o jsonpath='{.spec.containers[0].env}' | jqVariável obrigatória ausente costuma matar a aplicação em milissegundos, às vezes sem mensagem clara. Verifique também se o Secret ou ConfigMap referenciado existe:
kubectl get secret,configmap -n <ns>kubectl describe pod <pod> -n <ns> | grep -iE 'secret|configmap|mount'6. Teste a dependência externa
Seção intitulada “6. Teste a dependência externa”Se a aplicação faz uma conexão obrigatória no boot (banco, cache, fila) e ela falha, o processo pode encerrar direto.
docker run --rm -it --network container:<container> nicolaka/netshoot \ sh -c 'nc -zv db 5432; nslookup db'O padrão robusto é a aplicação tentar novamente com backoff em vez de morrer — mas, no diagnóstico, o que importa é descobrir se a dependência responde.
Se ainda não achou
Seção intitulada “Se ainda não achou”- Rode o comando na mão dentro do container, com o entrypoint sobrescrito, e leia o erro completo.
- Compare com uma versão que funcionava:
docker historydas duas imagens mostra o que mudou. - Arquitetura:
docker inspect --format '{{.Architecture}}'— imagemarm64em hostamd64dáexec format error. - Aumente o log da aplicação para debug temporariamente, com uma variável de ambiente.
Checklist de pronto
Seção intitulada “Checklist de pronto”- Código de saída identificado e interpretado.
- Logs da execução que falhou (inclusive
--previous) lidos. - Comando e caminho verificados dentro da imagem.
- Usuário e permissões conferidos.
- Variáveis, Secrets e montagens confirmados.
- Dependências externas testadas do mesmo contexto de rede.