Pular para o conteúdo

Debugar um container que não sobe

Iniciante12 min de leituracontainers

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.

Janela do terminal
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”
Janela do terminal
docker logs <container> 2>&1 | tail -50
docker logs --tail 100 --timestamps <container>

No Kubernetes, o container atual pode ter acabado de nascer:

Janela do terminal
kubectl logs <pod> -n <ns> --previous
kubectl 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).

O comando padrão falha, mas a imagem continua inspecionável:

Janela do terminal
docker run --rm -it --entrypoint sh loja:1.8.3
# e então, lá dentro:
ls -l /app
which python || ls -l /bin/loja
echo $PATH

Se a imagem não tem shell (distroless, scratch), copie os arquivos para fora e inspecione:

Janela do terminal
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âmico

No Kubernetes, o equivalente é um container efêmero ao lado do Pod:

Janela do terminal
kubectl debug -it <pod> -n <ns> --image=busybox --target=<container>
Janela do terminal
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 +x no 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 (fsGroup resolve no Kubernetes).
Janela do terminal
docker inspect <container> --format '{{json .Config.Env}}' | jq
docker inspect <container> --format '{{json .Mounts}}' | jq
kubectl get pod <pod> -n <ns> -o jsonpath='{.spec.containers[0].env}' | jq

Variá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:

Janela do terminal
kubectl get secret,configmap -n <ns>
kubectl describe pod <pod> -n <ns> | grep -iE 'secret|configmap|mount'

Se a aplicação faz uma conexão obrigatória no boot (banco, cache, fila) e ela falha, o processo pode encerrar direto.

Janela do terminal
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.

  • 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 history das duas imagens mostra o que mudou.
  • Arquitetura: docker inspect --format '{{.Architecture}}' — imagem arm64 em host amd64 dá exec format error.
  • Aumente o log da aplicação para debug temporariamente, com uma variável de ambiente.
  • 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.