Changer le thème

Le conteneur Docker quitte dès le démarrage ? Guide complet de dépannage (codes 137/1)

Easton editorial illustration: bottleneck pressure gauge

J’allais éteindre l’ordinateur en fin de journée quand mon téléphone a vibré — alerte production. En ouvrant l’application, les conteneurs de quatre services critiques étaient tous passés en Exited. J’ouvre le terminal, je tape docker ps. Vide. Complètement vide.

C’est comme ouvrir le frigo pour prendre une boisson et découvrir qu’il est entièrement vide. La panique monte.

Franchement, ma première pensée a été « c’est foutu, mon week-end est ruiné ». Mais une fois calmé, j’ai réalisé que ce n’était pas la première fois que je voyais un échec de démarrage de conteneur. Cette fois, le problème est arrivé plus brutalement et l’impact était plus large.

Après plus de deux heures de dépannage, la cause s’est avérée assez simple : le chemin d’un fichier de configuration d’un service était incorrect, la connexion à la base de données dépendante a échoué et le conteneur s’est arrêté immédiatement au démarrage. Avec une procédure systématique, dix minutes auraient suffi.

Cet article est le guide de dépannage que j’ai consolidé après d’innombrables galères. Que vous voyiez Exit Code 1, 137 ou un autre code, cette méthode vous aide à identifier rapidement la cause racine.

Comprendre le cycle de vie du conteneur et les codes de sortie

Avant de dépanner, clarifions une question de base : pourquoi un conteneur quitte-t-il ?

L’essence du conteneur : le cycle de vie d’un processus

Un conteneur Docker, au fond, n’est qu’un processus isolé. Tant que ce processus vit, le conteneur tourne ; quand il s’arrête — fin normale, crash ou kill forcé — le conteneur passe immédiatement en Exited.

Imaginez un conteneur Web : le processus principal peut être nginx ou node. Tant qu’il tourne, docker ps l’affiche. S’il quitte pour une raison quelconque, le conteneur devient Exited.

C’est pourquoi docker ps seul peut ne rien montrer : il faut ajouter -a pour voir les conteneurs déjà arrêtés.

Table de référence des codes de sortie

À chaque arrêt, Docker enregistre un code de sortie (Exit Code). Ce nombre indique ce qui s’est passé.

Exit Code 0 : tout va bien, la tâche est terminée.
Par exemple un script d’import de données qui se termine normalement. Ce n’est pas un problème.

Exit Code 1 : l’application a échoué elle-même.
C’est le code d’erreur le plus courant : mauvaise configuration, dépendance manquante, bug dans le code, etc.

Je me souviens d’un déploiement MySQL bloqué en Exit Code 1 : après des heures de logs, j’avais remplacé un = par : dans le fichier de configuration. MySQL détectait une erreur de syntaxe et refusait de démarrer.

Exit Code 137 : mémoire insuffisante ou arrêt forcé.
Deux cas fréquents :

  1. Dépassement de la limite mémoire — l’OOM Killer du noyau Linux tue le processus
  2. docker kill ou kill -9 exécuté par quelqu’un ou par le système

Pour distinguer : docker inspect et le champ OOMKilled. Si true, c’est un problème mémoire ; si false, plutôt une terminaison manuelle.

Exit Code 127 : commande introuvable.
Souvent un CMD ou ENTRYPOINT avec un mauvais chemin, ou un binaire absent de l’image.

Exit Code 139 : segmentation fault.
Typique des programmes C/C++ qui accèdent à une zone mémoire invalide. Rare en dehors du bas niveau.

Règles générales des codes de sortie

  • 0 : sortie normale
  • 1-128 : problème interne à l’application (erreur, configuration, etc.)
  • 129-255 : intervention externe (signal, kill système, etc.)

Connaître ces plages oriente déjà le dépannage.

Dépannage en quatre étapes pour localiser le problème

Savoir lire un code de sortie ne suffit pas : il faut creuser méthodiquement.

J’utilise une procédure en quatre étapes qui couvre environ 90 % des échecs de démarrage. En la suivant, le problème devient beaucoup moins opaque.

Étape 1 : confirmer l’état du conteneur

Avant les logs, vérifiez que le conteneur existe bien et qu’il est arrêté.

docker ps -a

Cette commande liste tous les conteneurs, y compris ceux arrêtés. Points clés :

CONTAINER ID : identifiant unique ; les commandes suivantes en ont besoin. Les premiers caractères suffisent souvent.

Colonne STATUS : un conteneur actif affiche Up X minutes ; un conteneur arrêté affiche Exited (code) X minutes ago.

Exemple :

CONTAINER ID   IMAGE         STATUS
a1b2c3d4e5f6   mysql:8.0     Exited (1) 2 minutes ago

Un code 1 suggère un problème applicatif ; un code 137, plutôt la mémoire.

Regardez aussi les horodatages : sortie en moins d’une seconde → souvent commande de démarrage ou configuration ; sortie après un certain temps → ressources ou dépendance.

Étape 2 : consulter les logs du conteneur

C’est souvent l’étape décisive. Avant de quitter, le conteneur laisse des indices dans les logs.

Consultation de base :

docker logs <container_id>

Affiche stdout et stderr. Souvent vous verrez directement Permission denied, No such file or directory, Connection refused, etc.

Suivi en temps réel (utile pendant un redémarrage) :

docker logs -f <container_id>

Comme tail -f. Moins utile sur un conteneur déjà arrêté, mais pratique si vous relancez pour observer le démarrage.

Dernières lignes uniquement :

docker logs --tail 100 <container_id>

Les dernières lignes suffisent souvent.

Avec horodatage :

docker logs -t <container_id>

-t ajoute un horodatage à chaque ligne.

Filtrer les erreurs :

docker logs <container_id> 2>&1 | grep -i error

Pour isoler rapidement les messages d’erreur dans un flux volumineux.

Étape 3 : inspecter la configuration du conteneur

Quand les logs ne suffisent pas, il faut regarder la configuration et l’état en détail.

Configuration complète :

docker inspect <container_id>

Sortie JSON volumineuse : variables d’environnement, montages, réseau, etc.

Informations ciblées :

Code de sortie :

docker inspect --format '{{.State.ExitCode}}' <container_id>

OOM Killed :

docker inspect --format '{{.State.OOMKilled}}' <container_id>

Si la sortie est true, c’est confirmé : problème mémoire.

Variables d’environnement :

docker inspect --format '{{.Config.Env}}' <container_id>

Chaînes de connexion base de données, clés API, etc.

Montages :

docker inspect --format '{{.Mounts}}' <container_id>

Vérifiez que les chemins de configuration et de données sont corrects.

Chemin du fichier de log sur l’hôte :

docker inspect --format='{{.LogPath}}' <container_id>

Si docker logs échoue, vous pouvez lire le fichier directement sur l’hôte.

Étape 4 : validation par démarrage interactif

Les trois premières étapes n’ont pas suffi ? Entrez dans le conteneur.

Démarrage interactif :

Si vous lanciez :

docker run -d my-app

Remplacez -d par -it pour un premier plan :

docker run -it my-app

Vous voyez alors toute la sortie du démarrage en direct.

Shell manuel dans le conteneur :

Si le conteneur quitte trop vite :

docker run -it my-app /bin/bash

ou :

docker run -it my-app /bin/sh

À l’intérieur, vous pouvez :

  • Vérifier les fichiers : ls /etc/app/config.yaml
  • Tester la syntaxe de configuration (ex. MySQL : mysqld --verbose --help)
  • Exécuter manuellement la commande de démarrage
  • Tester les dépendances : ping database, telnet redis 6379

Particulièrement efficace pour chemins, permissions et dépendances.

En pratique, la majorité des cas se résout à l’étape 2. Seuls les cas difficiles exigent les quatre étapes.

Cinq scénarios d’échec courants et leurs solutions

Voici les situations que je rencontre le plus souvent au quotidien, regroupées en cinq catégories.

Scénario 1 : fichier de configuration incorrect ou chemin inexistant

Signes typiques :

  • Exit Code 1
  • Logs avec No such file or directory, config file not found, syntax error, etc.

Cas réel :

Déploiement d’une application Node.js qui ne démarrait pas. Logs :

Error: ENOENT: no such file or directory, open '/app/config/prod.json'

La commande docker run montait :

-v /home/user/config:/app/conf  # attention : conf

L’application lisait /app/config. Une lettre de différence, fichier introuvable, échec au démarrage.

Méthode de dépannage :

  1. docker inspect --format '{{.Mounts}}' pour les montages
  2. ls dans le conteneur pour confirmer la présence des fichiers
  3. Pour une erreur de syntaxe, la plupart des applications indiquent la ligne en cause dans les logs

Solutions :

Chemin de montage incorrect :

# Exemple incorrect
docker run -v /host/path:/wrong/path my-app

# Bonne pratique
docker run -v /host/path:/app/config my-app

Erreur de syntaxe dans le fichier :

  • YAML : outil en ligne ou yamllint
  • JSON : jq . config.json
  • MySQL : mysqld --verbose --help dans le conteneur

Scénario 2 : mémoire insuffisante (OOM Killed)

Signes typiques :

  • Exit Code 137
  • docker inspect --format '{{.State.OOMKilled}}' retourne true
  • Logs éventuels : Cannot allocate memory, Out of memory

Cas réel :

Application Java stable en local, redémarrages en boucle sur le serveur de test. Logs :

OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory failed; error='Cannot allocate memory' (errno=12)

Docker Desktop sur le serveur de test n’allouait que 512 Mo ; l’application Java en demandait environ 600 Mo au démarrage.

Méthode de dépannage :

# Confirmer l'OOM
docker inspect --format '{{.State.OOMKilled}}' <container_id>

# Mémoire de l'hôte
free -h

# Consommation du conteneur
docker stats <container_id>

Solutions :

Augmenter la limite mémoire du conteneur :

docker run -m 1g my-app  # limite max 1 Go
docker run -m 512m --memory-swap 1g my-app  # avec swap

Sur Docker Desktop :

  • macOS : Docker Desktop → Preferences → Resources → Memory
  • Windows : Docker Desktop → Settings → Resources → Memory

Optimiser l’application :

  • Java : java -Xmx512m -jar app.jar
  • Node.js : node --max-old-space-size=512 app.js
  • Vérifier les fuites mémoire dans le code

En production :

  • Définir une limite adaptée au besoin réel
  • Utiliser --memory-reservation comme limite souple
  • Surveiller la tendance mémoire et anticiper le scale

Scénario 3 : conflit de ports

Signes typiques :

  • Exit Code 1
  • Logs : port is already allocated, address already in use, bind: address already in use

Cas réel :

Lundi matin, docker-compose up et Nginx ne démarre pas :

Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use

Vendredi, j’avais testé un Nginx local et oublié de l’arrêter. Le port 80 était occupé.

Méthode de dépannage :

Vérifier l’occupation du port (Linux/macOS) :

lsof -i :8080
netstat -tuln | grep 8080

Windows :

netstat -ano | findstr 8080

Ports mappés par d’autres conteneurs :

docker ps --format "table {{.Names}}\t{{.Ports}}"

Solutions :

Option 1 : changer le port mappé

# Commande d'origine
docker run -p 8080:8080 my-app

# Autre port hôte
docker run -p 8081:8080 my-app

Option 2 : arrêter le service qui occupe le port

# Trouver le PID
lsof -i :8080

# Terminer le processus
kill -9 <PID>

Option 3 : arrêter le conteneur conflictuel

docker stop <conflicting_container>

Note : avec --network=host, le conteneur utilise directement le réseau de l’hôte — les conflits de ports sont plus fréquents.

Scénario 4 : permissions insuffisantes

Signes typiques :

  • Exit Code 1
  • Logs : Permission denied, Operation not permitted, chown: changing ownership failed

Cas réel :

Conteneur MongoDB avec répertoire de données monté depuis l’hôte :

chown: changing ownership of '/data/db': Permission denied

Le répertoire hôte appartenait à root ; le processus MongoDB dans le conteneur utilisait l’utilisateur mongodb (UID 999) sans droit d’écriture.

Méthode de dépannage :

Permissions sur l’hôte :

ls -la /host/data/path

Utilisateur dans le conteneur :

docker run -it my-app /bin/bash
whoami
id

SELinux (CentOS/RHEL) :

getenforce  # état SELinux

Solutions :

Option 1 : ajuster les permissions sur l’hôte

# Lecture/écriture pour tous (peu sécurisé — dev uniquement)
chmod 777 /host/data/path

# Plus sûr : changer le propriétaire
chown -R 999:999 /host/data/path  # UID de l'utilisateur dans le conteneur

Option 2 : mode privilégié (à utiliser avec prudence)

docker run --privileged=true my-app

Donne au conteneur des privilèges étendus sur l’hôte — risque de sécurité ; déconseillé en production.

Option 3 : spécifier l’utilisateur d’exécution

docker run --user 1000:1000 my-app  # UID/GID de l'hôte

Option 4 : SELinux

# Méthode 1 : label Z (modifie le label sur l'hôte)
docker run -v /host/path:/container/path:Z my-app

# Méthode 2 : label z (partagé)
docker run -v /host/path:/container/path:z my-app

# Méthode 3 : désactiver temporairement SELinux (non recommandé en prod)
setenforce 0

Scénario 5 : service dépendant non prêt

Signes typiques :

  • Exit Code 1
  • Échec de connexion base de données, timeout Redis, etc.
  • Connection refused, ECONNREFUSED, could not connect to server

Cas réel :

Déploiement microservices avec docker-compose : l’application dépend de MySQL. Les deux conteneurs démarrent presque en même temps, l’application échoue :

Error: connect ECONNREFUSED 172.18.0.2:3306

Le conteneur MySQL était « up », mais le service MySQL terminait encore son initialisation. L’application a tenté trop tôt, échec, puis sortie.

Méthode de dépannage :

Services dépendants :

docker ps  # les conteneurs dépendants tournent-ils ?

Connectivité réseau :

docker exec my-app ping database
docker exec my-app telnet database 3306
docker exec my-app nc -zv database 3306

Réseau Docker :

docker network ls
docker network inspect <network_name>

Solutions :

Option 1 : healthcheck et depends_on dans docker-compose

version: '3.8'
services:
  database:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  app:
    image: my-app
    depends_on:
      database:
        condition: service_healthy  # attendre que la base soit healthy

Option 2 : logique de retry dans l’application

// Exemple Node.js
async function connectWithRetry(maxRetries = 5) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      await db.connect();
      console.log('Database connected');
      return;
    } catch (err) {
      console.log(`Connection failed, retrying... (${i+1}/${maxRetries})`);
      await new Promise(resolve => setTimeout(resolve, 5000));
    }
  }
  throw new Error('Failed to connect to database');
}

Option 3 : script d’attente au démarrage

Par exemple wait-for-it.sh :

# Dans le Dockerfile
COPY wait-for-it.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/wait-for-it.sh

# Au démarrage
CMD ["wait-for-it.sh", "database:3306", "--", "node", "app.js"]

Option 4 : politique de redémarrage

docker run --restart=on-failure:3 my-app  # max 3 redémarrages

Dans docker-compose :

services:
  app:
    restart: on-failure

Ces approches se combinent : healthcheck + retry applicatif + restart policy.

Mesures préventives et bonnes pratiques

Tout ce qui précède concerne la réparation. Avec les bons réglages dès le départ, beaucoup de problèmes n’apparaissent jamais — ou se corrigent seuls.

Configurer un health check (HEALTHCHECK)

Le health check permet à Docker de vérifier périodiquement si le conteneur fonctionne réellement, pas seulement si le processus existe.

Dans le Dockerfile :

FROM nginx:alpine

# Toutes les 30 s, timeout 3 s, 3 échecs consécutifs → unhealthy
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

Pour un service Web :

HEALTHCHECK --interval=30s --timeout=5s --start-period=40s \
  CMD curl -f http://localhost:8080/health || exit 1

Pour les bases de données :

# MySQL
HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1

# PostgreSQL
HEALTHCHECK CMD pg_isready -U postgres || exit 1

# Redis
HEALTHCHECK CMD redis-cli ping || exit 1

Bénéfices :

  • Kubernetes/Swarm peuvent redémarrer ou rescheduler selon l’état de santé
  • depends_on dans docker-compose peut attendre un service vraiment prêt
  • La surveillance peut alerter sur unhealthy

Consulter l’état :

docker ps  # colonne STATUS avec health
docker inspect --format='{{.State.Health.Status}}' <container_id>

Définir une politique de redémarrage

Une politique de restart permet la reprise automatique sans intervention manuelle à 3 h du matin.

Quatre stratégies Docker :

no (par défaut) : pas de redémarrage automatique

docker run --restart=no my-app

Adapté aux tâches ponctuelles.

on-failure[:max-retries] : redémarrage uniquement en cas de sortie anormale

docker run --restart=on-failure:5 my-app  # max 5 tentatives

Redémarre seulement si le code de sortie est non nul.

always : toujours redémarrer

docker run --restart=always my-app

Pour les services longue durée (Web, API). Même après un docker stop manuel, le conteneur repart au redémarrage du daemon.

unless-stopped : redémarrer sauf arrêt manuel explicite

docker run --restart=unless-stopped my-app

Comme always, mais un docker stop manuel n’est pas annulé au redémarrage du daemon. C’est ma stratégie préférée en production.

Points importants :

  1. Règle des 10 secondes : le conteneur doit tourner au moins 10 secondes au premier démarrage pour que la politique s’applique — évite les boucles infinies sur une mauvaise config.
  2. Piège des redémarrages infinis : une erreur de config (ex. conflit de port) peut faire exploser les logs. Pensez à la rotation des logs.

Modifier la politique d’un conteneur existant :

docker update --restart=unless-stopped <container_id>

Dans docker-compose :

services:
  web:
    image: nginx
    restart: unless-stopped  # recommandé en production

  worker:
    image: my-worker
    restart: on-failure  # échecs possibles, sans retry infini

Gestion des logs : éviter de saturer le disque

Par défaut, Docker stocke tous les logs en fichiers JSON. Sur la durée, cela peut consommer des dizaines de Go. J’ai déjà vu un serveur de production tomber à cause des logs Docker.

Rotation des logs (recommandé) — éditer /etc/docker/daemon.json :

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",    // taille max d'un fichier de log
    "max-file": "3"       // nombre max de fichiers conservés
  }
}

Puis redémarrer Docker :

sudo systemctl restart docker

Chaque conteneur occupe au plus environ 30 Mo (10 Mo × 3) ; les anciens fichiers sont supprimés automatiquement.

Par conteneur :

docker run --log-opt max-size=10m --log-opt max-file=3 my-app

Dans docker-compose :

services:
  app:
    image: my-app
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Autres drivers :

  • syslog : vers les logs système
  • journald : journal systemd
  • fluentd : centralisation Fluentd
  • none : pas de logs (déconseillé)

Emplacement et taille des logs :

docker inspect --format='{{.LogPath}}' <container_id>
du -h $(docker inspect --format='{{.LogPath}}' <container_id>)

Surveillance et alertes : détecter tôt

Ne attendez pas la panne pour agir.

Base : docker stats

docker stats  # ressources de tous les conteneurs en temps réel
docker stats <container_id>  # un conteneur précis

CPU, mémoire, réseau, disque. Une mémoire qui grimpe sans cesse peut signaler une fuite.

Production : Prometheus + Grafana

# docker-compose.yml
services:
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"

  cadvisor:  # métriques conteneurs
    image: google/cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    ports:
      - "8080:8080"

Règles d’alerte : mémoire > 80 %, trop de redémarrages, etc.

Approche simple : script planifié

#!/bin/bash
# check-containers.sh

# Conteneurs en Exited
EXITED=$(docker ps -a -f "status=exited" --format "{{.Names}}")

if [ -n "$EXITED" ]; then
  echo "Warning: The following containers are exited:"
  echo "$EXITED"
  # envoi mail ou notification ici
fi

Crontab toutes les 5 minutes :

*/5 * * * * /path/to/check-containers.sh

Checklist de configuration production

Exemple de configuration solide :

version: '3.8'
services:
  web:
    image: my-web-app:latest

    # Politique de redémarrage
    restart: unless-stopped

    # Limites de ressources
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          memory: 512M

    # Health check
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

    # Logs
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

    # Variables d'environnement (secrets pour données sensibles)
    environment:
      - NODE_ENV=production

    # Ports
    ports:
      - "8080:8080"

    # Dépendances
    depends_on:
      database:
        condition: service_healthy

  database:
    image: postgres:14
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - db-data:/var/lib/postgresql/data
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

volumes:
  db-data:

Avec cela : redémarrage automatique, limites mémoire, logs maîtrisés, alertes possibles — beaucoup plus serein.

Conclusion

L’essentiel : un conteneur qui ne démarre pas n’est pas une catastrophe si vous avez une méthode.

Comprendre les codes de sortie : 137 → mémoire ; 1 → config ou dépendance. Ce sont des indices, pas du bruit.

Dépannage en quatre étapes :

  1. État du conteneur (docker ps -a)
  2. Logs (docker logs)
  3. Configuration (docker inspect)
  4. Validation interactive (docker run -it)

Plus de 90 % des cas se règlent à l’étape 2.

Cinq scénarios courants : configuration, mémoire, ports, permissions, dépendances.

Prévention : health checks, restart policy, rotation des logs, surveillance.

Checklist rapide à garder sous la main :

Checklist — échec de démarrage de conteneur Docker

□ Étape 1 : docker ps -a — état et code de sortie
□ Étape 2 : docker logs <container_id> — logs détaillés
□ Étape 3 : docker inspect <container_id> — configuration
□ Étape 4 : docker run -it <image> — validation interactive

Localisation rapide :
- Exit Code 1 + "No such file" → montages et configuration
- Exit Code 1 + "port already allocated" → conflit de ports
- Exit Code 1 + "Permission denied" → permissions et SELinux
- Exit Code 1 + "Connection refused" → services dépendants
- Exit Code 137 + OOMKilled=true → limite mémoire
- Exit Code 127 → chemin CMD/ENTRYPOINT

Prévention :
□ HEALTHCHECK configuré
□ Politique restart (unless-stopped recommandé)
□ Rotation des logs (max-size + max-file)
□ Limites de ressources (-m mémoire)
□ Surveillance (docker stats ou Prometheus)

Si cet article vous a aidé, gardez-le en favori pour le prochain incident. Si vous avez rencontré un cas particulier, partagez-le en commentaire — cela peut aider d’autres lecteurs.

Que vos conteneurs restent Up and Running, et plus d’alerte le vendredi soir pour des conteneurs tombés !

Flux complet de dépannage des échecs de démarrage de conteneurs Docker

Méthode systématique : sens des codes 137/1, dépannage en quatre étapes et solutions pour les cinq scénarios d'échec les plus courants

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Comprendre les codes de sortie et la gravité du problème

    Sens des codes de sortie :
    • Exit Code 0 : sortie normale, tâche terminée
    • Exit Code 1 : erreur applicative, échec de la commande de démarrage (le plus fréquent)
    • Exit Code 137 : tué par l'OOM Killer, mémoire insuffisante
    • Exit Code 127 : commande introuvable
    • Exit Code 139 : segmentation fault (programmes C/C++)

    Gravité du problème :
    • En production, les conteneurs de quatre services critiques sont tous passés en Exited
    • Les conteneurs quittent immédiatement au démarrage — une méthode systématique est nécessaire

    Localisation rapide des problèmes courants :
    • Exit Code 1 + 'No such file' → vérifier les chemins de montage et les fichiers de configuration
    • Exit Code 1 + 'port already allocated' → vérifier les conflits de ports
    • Exit Code 1 + 'Permission denied' → vérifier les permissions de fichiers et SELinux
    • Exit Code 1 + 'Connection refused' → vérifier si les services dépendants sont prêts
    • Exit Code 137 + OOMKilled=true → augmenter la limite mémoire
  2. 2

    Step 2: Dépannage en quatre étapes

    Dépannage en quatre étapes :

    Étape 1 : consulter l'état du conteneur et le code de sortie
    • docker ps -a pour l'état et le code de sortie
    • Surveiller les colonnes State et Exit Code

    Étape 2 : consulter les logs détaillés
    • docker logs <container_id> pour les logs complets
    • docker logs --tail 50 <container_id> pour les 50 dernières lignes
    • docker logs -f <container_id> pour le suivi en temps réel

    Étape 3 : vérifier la configuration
    • docker inspect <container_id> pour la configuration
    • Examiner Cmd, Entrypoint, Env, etc.

    Étape 4 : validation interactive
    • docker run -it <image> pour une validation interactive
    • Exécuter manuellement la commande de démarrage et observer les erreurs
  3. 3

    Step 3: Cinq scénarios d'échec courants et leurs solutions

    Cinq scénarios d'échec courants :

    Scénario 1 : commande de démarrage incorrecte
    • CMD/ENTRYPOINT mal configuré
    • Solution : corriger la commande de démarrage, vérifier chemins et arguments

    Scénario 2 : fichier de configuration incorrect
    • Chemin ou format erroné
    • Solution : corriger le fichier, valider chemin et format

    Scénario 3 : service dépendant non prêt
    • Base de données non démarrée
    • Solution : attendre que le service soit prêt (depends_on + healthcheck)

    Scénario 4 : mémoire insuffisante
    • Processus tué par l'OOM Killer
    • Solution : augmenter la limite mémoire (--memory) ou optimiser l'application

    Scénario 5 : conflit de ports
    • Port déjà utilisé
    • Solution : modifier le mapping de ports (-p 8081:80) ou arrêter le processus occupant le port

    Bonnes pratiques :
    • Configurer les health checks dans docker-compose
    • Utiliser depends_on + healthcheck pour les dépendances
    • Définir des limites de ressources raisonnables (mémoire, CPU)

FAQ

Pourquoi un conteneur Docker quitte-t-il immédiatement après le démarrage ?
Causes fréquentes d'une sortie immédiate :

Sens des codes de sortie :
• Exit Code 1 : erreur applicative, échec de la commande de démarrage (le plus fréquent)
• Exit Code 137 : tué par l'OOM Killer, mémoire insuffisante
• Exit Code 0 : sortie normale, tâche terminée

Localisation rapide :
• Exit Code 1 + 'No such file' → vérifier montages et configuration
• Exit Code 1 + 'port already allocated' → vérifier les conflits de ports
• Exit Code 1 + 'Permission denied' → vérifier permissions et SELinux
• Exit Code 1 + 'Connection refused' → vérifier les services dépendants
• Exit Code 137 + OOMKilled=true → augmenter la limite mémoire

Méthode : dépannage en quatre étapes (logs → code de sortie → commande de démarrage → limites de ressources)
Comment dépanner un échec de démarrage de conteneur Docker ?
Dépannage en quatre étapes :
1) Consulter les logs : docker logs container-name
2) Vérifier le code de sortie : docker ps -a
3) Contrôler la commande de démarrage : docker inspect container-name
4) Vérifier les limites de ressources : docker stats

Détail des étapes :
• Étape 1 : docker ps -a pour l'état et le code de sortie
• Étape 2 : docker logs <container_id> pour les logs détaillés
• Étape 3 : docker inspect <container_id> pour la configuration
• Étape 4 : docker run -it <image> pour une validation interactive
Quelle est la différence entre Exit Code 1 et Exit Code 137 ?
Sens des codes de sortie :
• Exit Code 1 : erreur applicative, échec de la commande de démarrage
• Exit Code 137 : tué par l'OOM Killer, mémoire insuffisante
• Exit Code 0 : sortie normale
• Autres codes : selon l'application concernée

Causes fréquentes de Exit Code 1 :
• Commande de démarrage incorrecte (CMD/ENTRYPOINT)
• Fichier de configuration erroné (chemin ou format)
• Service dépendant non prêt (base de données)
• Conflit de ports (port déjà utilisé)

Causes fréquentes de Exit Code 137 :
• Mémoire insuffisante (OOM Killer)
• Augmenter la limite mémoire (--memory)
Comment résoudre les problèmes courants d'échec de démarrage de conteneur ?
Cinq scénarios d'échec courants :
1) Commande de démarrage incorrecte (CMD/ENTRYPOINT)
2) Fichier de configuration erroné (chemin ou format)
3) Service dépendant non prêt (base de données)
4) Mémoire insuffisante (OOM Killer)
5) Conflit de ports (port déjà utilisé)

Solutions :
• Corriger la commande de démarrage
• Corriger le fichier de configuration
• Attendre les services dépendants (depends_on + healthcheck)
• Augmenter la limite mémoire (--memory)
• Modifier le mapping de ports (-p 8081:80)
• Configurer les health checks dans docker-compose

15 min de lecture · Publié le: 18 déc. 2025 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog