Un conteneur meurt au démarrage : par où commencez-vous ?

Questions d’entrevue Docker

Intermédiairedebugruntime

La réponse courte

Je ne commence pas par docker exec. Un conteneur déjà mort n’a plus de process à joindre. Je commence par ce qu’il a dit en mourant.

bash
docker ps -a          # statut, code de sortie
docker logs web       # stdout / stderr du PID 1
docker inspect web --format '{{.State.ExitCode}} {{.State.Error}} {{.State.OOMKilled}}'

Les codes qu’on revoit en entretien :

  • 127 / 126 : binaire introuvable ou non exécutable. Mauvais ENTRYPOINT, CRLF sur un script, binaire amd64 sur ARM, CMD qui pointe vers un fichier jamais COPY.
  • 1 (et piles applicatives) : l’app a démarré assez pour se plaindre — config manquante, port pris, connexion refusée. Les logs parlent.
  • 137 : souvent SIGKILL, fréquemment OOM. OOMKilled à true dans l’inspect. Ce n’est pas un bug métier dans docker logs.
  • 0 alors que « ça devrait tourner » : le process n’était pas un serveur. Un script qui finit, un npm run build en CMD, un conteneur one-shot. Il n’est pas mort : il a terminé.

Ensuite seulement : relancer avec une commande de debug (docker run --rm -it image sh) si l’image a un shell, ou docker run en remplaçant l’entrypoint pour echo / ls. Pas installer vim dans l’image de prod.

Ce que l’intervieweur vérifie

Une démarche, dans cet ordre : inspect, logs, hypothèse, reproduction. Le candidat qui tape dix restart et un exec sur un exited montre qu’il n’a pas compris le cycle de vie.

Deux causes à nommer parce qu’elles piègent encore :

  1. La forme shell et les signaux, moins au crash qu’au « je n’arrive pas à l’arrêter ». Au démarrage, le cousin est un ENTRYPOINT qui lance un script sans exec : le vrai serveur n’est pas PID 1, le script se termine, le conteneur sort 0.
  2. Écouter 127.0.0.1 ou une variable d’environnement absente. Ça peut tuer tout de suite (fail-fast) ou laisser un Up qui n’accepte aucun trafic — autre question, même discipline de lecture.

La relance probable

« Les logs sont vides. »

Le process n’a jamais atteint un logger, ou il bufferise stdout (Python sans -u, Java selon l’appender). Je relance avec une commande plus bête que l’app (ls, id, echo) pour valider l’image, puis je force le flush. Si OOMKilled, je lève la limite pour comprendre, je ne « mets 16 Go » comme correctif définitif.

« Ça meurt seulement avec Compose. »

Alors ce n’est probablement pas l’image : depends_on trop tôt, un nom DNS, une variable déclarée dans un fichier que le service ne charge pas. Je compare docker compose config au docker run qui marchait.

Toutes les questions Docker