Docker container exited: como descobrir por que o contêiner encerra logo após iniciar
Publicado em 2026-08-29T20:13:00Z · atualizado em 2026-08-29T19:13:41+00:00
Você executa `docker run`, o terminal volta imediatamente e `docker ps` não mostra nada. Ao usar `docker ps -a`, o contêiner aparece como **Exited**. Isso não significa que o Docker “fechou sozinho”: um contêiner permanece ativo enquanto se
Docker container exited: como descobrir por que o contêiner encerra logo após iniciar
Você executa docker run, o terminal volta imediatamente e docker ps não mostra nada. Ao usar docker ps -a, o contêiner aparece como Exited. Isso não significa que o Docker “fechou sozinho”: um contêiner permanece ativo enquanto seu processo principal está ativo. Se esse processo termina, por sucesso ou falha, o estado do contêiner passa a encerrado.
Este guia apresenta uma sequência de diagnóstico baseada em evidências: localizar o contêiner, ler logs, interpretar o código de saída, inspecionar comando e configuração, testar o processo em primeiro plano, validar variáveis, portas, volumes, permissões, arquitetura, limites e sinais. A política de reinício aparece somente depois da causa.
Legenda: a vida do contêiner acompanha o processo principal; quando o PID 1 termina, o contêiner termina.
Encontre o contêiner que sumiu do docker ps
docker ps lista apenas contêineres em execução. Inclua os encerrados:
docker ps -a
docker ps -a --filter status=exited
docker ps -a --latest
Anote CONTAINER ID, nome, imagem, status e comando. Se um sistema cria e remove contêineres com --rm, o objeto pode desaparecer ao terminar; durante o diagnóstico, retire essa opção em um ambiente de teste para preservar os metadados.
Formate uma visão objetiva:
docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}'
Não remova todos os contêineres ou volumes para “começar limpo”. Essa ação elimina evidências e pode apagar dados não persistidos. Trabalhe em uma cópia ou serviço de desenvolvimento.
Leia logs e código de saída primeiro
Os logs do contêiner mostram a saída padrão e de erro do processo:
docker logs nome-ou-id
docker logs --timestamps --tail 200 nome-ou-id
Depois inspecione estado:
docker inspect nome-ou-id --format '{{json .State}}'
docker inspect nome-ou-id --format 'exit={{.State.ExitCode}} erro={{.State.Error}} oom={{.State.OOMKilled}}'
Código 0 significa que o processo terminou com sucesso. Para um comando em lote, isso pode ser exatamente o esperado. Para servidor web, geralmente indica que o comando executou uma tarefa curta ou colocou o servidor em segundo plano. Códigos diferentes de zero indicam falha definida pelo programa ou pelo ambiente.
Os valores 126 e 127 frequentemente apontam, respectivamente, para comando não executável e comando não encontrado. 137 costuma corresponder a encerramento por SIGKILL, que pode envolver falta de memória ou ação externa; confirme .State.OOMKilled e eventos em vez de assumir. 143 costuma representar SIGTERM, comum em desligamento controlado.
Reproduza um encerramento normal
Este comando imprime uma mensagem e termina com zero:
docker run --name demo-exit alpine:latest sh -c 'echo tarefa concluida'
docker ps -a --filter name=demo-exit
docker inspect demo-exit --format '{{.State.ExitCode}}'
O estado Exited (0) é correto porque echo acabou. Compare com um processo duradouro:
docker run --name demo-http -d -p 8080:80 nginx:alpine
docker ps --filter name=demo-http
docker logs demo-http
Ao terminar, remova apenas os objetos do laboratório pelos comandos normais do Docker. Não use esse exercício em um host compartilhado sem autorização.
CMD, ENTRYPOINT e o comando real
A imagem define ENTRYPOINT e CMD; argumentos de docker run podem substituir parte da configuração. Veja o resultado:
docker inspect nome-ou-id --format 'entrypoint={{json .Config.Entrypoint}} cmd={{json .Config.Cmd}}'
docker image inspect nome-da-imagem --format 'entrypoint={{json .Config.Entrypoint}} cmd={{json .Config.Cmd}}'
Um erro comum é trocar o comando do servidor por um script de migração que termina. Outro é usar a forma shell e criar comportamento inesperado de sinais e expansão.
Forma executável recomendada no Dockerfile:
ENTRYPOINT ["python", "-m", "meu_app"]
CMD ["--host", "0.0.0.0", "--port", "8000"]
A forma JSON não passa automaticamente por um shell. Variáveis como $PORT não são expandidas da mesma maneira; se a aplicação precisa delas, leia-as dentro do programa ou use um script de entrada bem escrito que finalize com exec.
O servidor foi enviado para segundo plano
Serviços antigos podem usar a opção --daemon, iniciar um filho e encerrar o processo pai. Em uma máquina tradicional isso é útil; no contêiner, o serviço principal deve ficar em primeiro plano.
Exemplo conceitual:
# Evite: o comando retorna e o contêiner termina
CMD ["meu-servidor", "--daemon"]
# Prefira: processo principal em primeiro plano
CMD ["meu-servidor", "--foreground"]
Não mantenha o contêiner vivo com tail -f /dev/null como correção de produção. Isso mascara que o serviço real morreu e faz o orquestrador acreditar que existe algo útil em execução. Use esse recurso apenas em laboratório temporário, com propósito explícito.
Variáveis de ambiente e segredos ausentes
Aplicações encerram na inicialização quando falta URL do banco, chave, ambiente ou configuração. Compare os nomes esperados com os enviados:
docker inspect nome-ou-id --format '{{range .Config.Env}}{{println .}}{{end}}'
Esse comando pode exibir segredos. Não cole a saída em tickets ou logs públicos. Prefira uma verificação que mostre apenas presença:
docker run --rm --env-file .env imagem sh -c '
test -n "$DATABASE_URL" && echo DATABASE_URL=presente || echo DATABASE_URL=ausente
'
Arquivos .env têm sintaxe própria e não são scripts shell completos. Espaços, aspas e quebras de linha podem virar parte do valor. Confirme a documentação da ferramenta que carrega o arquivo. Em Compose, use docker compose config com cautela, pois a saída resolvida pode incluir valores sensíveis.
Volumes, caminhos e permissões
Um volume montado sobre o diretório da aplicação pode esconder arquivos que existiam na imagem. Se a imagem contém /app/config.yml e você monta uma pasta vazia em /app, o arquivo deixa de aparecer dentro do contêiner.
Inspecione montagens:
docker inspect nome-ou-id --format '{{json .Mounts}}'
Teste a imagem sem o volume em ambiente isolado. Depois confira o caminho e permissões. Aplicações modernas frequentemente executam com usuário não root; o diretório do host precisa permitir leitura ou escrita conforme a necessidade.
Não “corrija” com permissão total recursiva. Descubra UID e GID do processo:
docker run --rm imagem id
docker image inspect imagem --format '{{.Config.User}}'
Ajuste propriedade e modo mínimos no ambiente controlado. Em Windows e macOS com Docker Desktop, compartilhamento de pastas e tradução de permissões também podem influenciar.
Legenda: cada evidência reduz o espaço de causas antes de qualquer política de reinício.
Porta ocupada não é a mesma coisa que processo encerrado
Se a publicação -p 8080:80 falha porque a porta do host está em uso, o daemon pode nem iniciar o contêiner corretamente. A mensagem aparece no comando e em .State.Error. Já uma aplicação pode iniciar dentro do contêiner e falhar ao abrir sua porta interna.
Confira mapeamentos:
docker port nome-ou-id
docker inspect nome-ou-id --format '{{json .NetworkSettings.Ports}}'
O processo deve escutar em 0.0.0.0 dentro do contêiner, não apenas em 127.0.0.1, se precisa receber tráfego pela rede do contêiner. Porém, escutar incorretamente geralmente deixa o processo vivo e causa falha de conexão; não confunda indisponibilidade com estado Exited.
Imagem e arquitetura incompatíveis
Uma imagem construída para arquitetura diferente pode falhar com “exec format error”. Confira:
docker info --format '{{.Architecture}}'
docker image inspect imagem --format '{{.Architecture}}/{{.Os}}'
Imagens multi-plataforma publicam manifestos para mais de uma arquitetura. Ao construir, use uma base compatível e ferramentas de build multi-plataforma quando realmente precisar. Emulação pode funcionar, mas traz diferenças de desempenho e compatibilidade.
Outro erro vem de scripts com final de linha incompatível ou shebang apontando para interpretador inexistente. Verifique se o arquivo é executável, usa LF quando necessário e referencia um caminho presente na imagem, como #!/bin/sh.
Memória, CPU e encerramento externo
Se .State.OOMKilled é verdadeiro, o processo ultrapassou a memória disponível e foi encerrado. Consulte os limites configurados:
docker inspect nome-ou-id --format 'memory={{.HostConfig.Memory}} cpu={{.HostConfig.NanoCpus}}'
docker stats --no-stream
Não aumente memória antes de medir. Uma carga legítima pode precisar de limite maior; um vazamento continuará crescendo. Colete métricas, reproduza com entrada controlada e ajuste aplicação e capacidade.
Também verifique quem solicitou parada. docker events --since 30m mostra eventos recentes do daemon. Sistemas de implantação, scripts de limpeza e verificações externas podem executar stop ou substituir o contêiner. Preserve horários com fuso e correlacione com logs do orquestrador.
Healthcheck não mantém o processo vivo
Um HEALTHCHECK avalia se o serviço está saudável enquanto o contêiner roda. Ele não substitui o processo principal. Um contêiner pode estar running (unhealthy) ou pode encerrar antes de qualquer verificação.
Inspecione:
docker inspect nome-ou-id --format '{{json .State.Health}}'
docker image inspect imagem --format '{{json .Config.Healthcheck}}'
O teste deve verificar o serviço real, ter timeout curto e não depender de ferramenta ausente na imagem. Evite uma verificação que sempre retorna zero; ela produz confiança falsa. Também não use healthcheck para iniciar processos ou corrigir dados.
Docker Compose: veja a configuração realmente aplicada
Em Compose, o arquivo base pode ser combinado com sobrescritas, perfis e variáveis. O comando final nem sempre é o que aparece no primeiro YAML. Inspecione a configuração resolvida em ambiente seguro:
docker compose config
docker compose ps -a
docker compose logs --timestamps --tail 200 nome-do-servico
command substitui o CMD da imagem; entrypoint substitui o ENTRYPOINT. Uma lista e uma string podem ter semânticas diferentes em relação ao shell. Compare o serviço resolvido com docker inspect do contêiner criado.
Tenha cuidado: docker compose config pode interpolar valores. Redija segredos antes de anexar a saída. Prefira docker compose config --services para listar serviços quando não precisar dos detalhes.
Dependência entre serviços também confunde o diagnóstico. depends_on ordena criação conforme a configuração, mas disponibilidade do banco pode exigir healthcheck e uma política de espera na aplicação. Um banco “iniciado” ainda pode não aceitar conexões. O cliente deve tratar falhas transitórias com limite, atraso e mensagem clara, não encerrar e reiniciar sem fim.
Use docker compose run --rm serviço comando-de-diagnostico apenas quando compreender volumes, rede e variáveis herdados. Ele cria outro contêiner e pode não reproduzir portas ou ciclo de vida idênticos ao serviço normal.
Sinais, PID 1 e desligamento correto
O processo PID 1 dentro do contêiner recebe sinais de parada e tem responsabilidades especiais. Scripts de entrada que iniciam um servidor sem exec podem manter o shell como PID 1; o sinal não chega ao filho como esperado, o Docker aguarda o timeout e força encerramento.
Um script de entrada simples deve validar configuração e substituir-se pelo processo final:
#!/bin/sh
set -eu
: "${DATABASE_URL:?DATABASE_URL ausente}"
exec python -m meu_app
exec faz o aplicativo ocupar o lugar do shell. A aplicação deve tratar SIGTERM, parar de aceitar trabalho, concluir o que for seguro dentro do prazo e sair. Não prenda o desligamento indefinidamente.
Teste:
docker stop --time 15 nome-ou-id
docker inspect nome-ou-id --format 'exit={{.State.ExitCode}} inicio={{.State.StartedAt}} fim={{.State.FinishedAt}}'
Se o processo precisa de um inicializador para coletar filhos, avalie --init ou a configuração equivalente, conforme a documentação da plataforma. Isso não corrige uma aplicação que ignora sinais; apenas ajuda na gestão de processos filhos.
Um serviço que inicia bem mas termina somente em implantações pode estar recebendo SIGTERM normalmente durante substituição. Correlacione eventos e código de saída antes de classificar o encerramento como defeito.
Política de reinício só depois do diagnóstico
O Docker oferece políticas como no, on-failure, always e unless-stopped. A documentação oficial explica seus comportamentos. Reiniciar pode recuperar uma falha transitória, mas cria um ciclo rápido quando configuração ou comando estão errados.
Veja a política atual:
docker inspect nome-ou-id --format '{{json .HostConfig.RestartPolicy}}'
Para um serviço, on-failure:5 limita tentativas; para uma tarefa em lote que termina com zero, reiniciar pode executá-la de novo indevidamente. Defina a política conforme a natureza do processo e configure alertas para reinícios repetidos.
Procedimento completo de investigação
Use esta ordem:
docker ps -apara preservar identidade e status;docker logs --timestampspara a mensagem da aplicação;docker inspectpara código, erro, OOM e comando;- validação de variáveis sem expor valores;
- inspeção de volumes, usuário, arquitetura e limites;
- reprodução da imagem sem sobrescritas desnecessárias;
- correção da causa e novo contêiner imutável;
- política de reinício e healthcheck adequados;
- teste de parada e inicialização controladas.
Desenhe o fluxo no criador de fluxogramas do IATechNerds e registre os testes nas ferramentas. Para analisar inventários exportados, use o iatnGrid sem enviar a planilha a um servidor externo.
Checklist para encerrar o diagnóstico
- contêiner encerrado foi localizado com
docker ps -a; - logs e
.Stateforam preservados; - código de saída foi interpretado com evidências;
- processo principal roda em primeiro plano;
ENTRYPOINTeCMDcorrespondem ao serviço desejado;- variáveis obrigatórias existem sem exposição de segredos;
- volumes não escondem arquivos e possuem permissões mínimas;
- arquitetura e interpretador do script são compatíveis;
- limites e
OOMKilledforam verificados; - healthcheck mede o serviço real;
- política de reinício não mascara falha permanente;
- a imagem corrigida passou por inicialização e desligamento controlados.
Documentação primária
- Docker — logs de contêiner
- Docker — inspect
- Docker — políticas de reinício
- Dockerfile — ENTRYPOINT
- Dockerfile — HEALTHCHECK
Nota de produção
Rascunho autoral orientado à busca “Docker container exited immediately”. Os laboratórios usam imagens públicas conhecidas e objetos descartáveis, sem comandos de limpeza ampla. O comportamento de logs, inspeção, processo principal e reinício foi baseado na documentação oficial do Docker. A revisão humana deve testar os exemplos em Docker Engine ou Docker Desktop suportado e ajustar a nomenclatura editorial antes de publicar.
Camada extra: como tomar uma decisão melhor neste cenário
A parte mais importante de Docker container exited: como descobrir por que o contêiner encerra logo após iniciar não é decorar um botão: é entender quais sinais confirmam o diagnóstico e quais sinais indicam que estamos resolvendo o problema errado.
Você executa `docker run`, o terminal volta imediatamente e `docker ps` não mostra nada. Ao usar `docker ps -a`, o contêiner aparece como **Exited**. Isso não significa que o Docker “fechou sozinho”: um contêiner permanece ativo enquanto se A ideia central pode ser testada com quatro perguntas: o que foi observado, qual hipótese explica o sintoma, qual mudança é reversível e qual evidência prova que funcionou. Esse encadeamento evita que uma coincidência seja confundida com causa e torna o procedimento repetível por outra pessoa.
Qualidade de IA precisa de um teste, não de uma impressão
Para Docker, contêiner, DevOps, logs, escolha três tarefas representativas: uma simples, uma ambígua e uma em que a resposta possa ser conferida em fonte primária. Compare utilidade, rastreabilidade, privacidade, velocidade e quantidade de correção humana necessária. Uma resposta elegante não compensa uma citação inexistente ou uma conclusão que não pode ser reproduzida.
Separe ainda o que pode sair do dispositivo do que deve permanecer local. Dados públicos toleram fluxos diferentes de documentos internos, contratos, informações pessoais ou bases de clientes. A escolha entre processamento local e nuvem deve ser feita pelo risco do conteúdo, não apenas pela conveniência da interface.
Grade de avaliação prática
| Critério | Pergunta | Evidência |
|---|---|---|
| Correção | A resposta bate com a fonte? | Checagem independente |
| Rastreabilidade | É possível localizar de onde veio? | Citação ou trecho verificável |
| Privacidade | Que dado sai do dispositivo? | Política e configuração |
| Esforço | Quanto trabalho humano resta? | Tempo de revisão |
O ponto em que a IA deixa de ajudar
Se a tarefa exige precisão absoluta e a saída não pode ser validada, a automação deve ser limitada a apoio: localizar trechos, organizar opções ou preparar uma primeira versão. A decisão final precisa permanecer com alguém capaz de verificar a fonte e assumir a responsabilidade pelo resultado.
Checklist de fechamento
- Registre o estado inicial antes de alterar qualquer coisa.
- Faça uma mudança por rodada e anote o efeito.
- Teste um caso normal, um caso-limite e o cenário que originalmente falhou.
- Confirme que a solução continua válida depois de reiniciar, reabrir ou repetir o fluxo.
- Guarde uma forma de voltar ao estado anterior quando a alteração for destrutiva.
Esse método acrescenta profundidade sem transformar o artigo em teoria abstrata: o leitor entende por que cada passo existe e como reconhecer quando a situação exige uma decisão diferente.
