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

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 :
- Dépassement de la limite mémoire — l’OOM Killer du noyau Linux tue le processus
docker killoukill -9exé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 :
docker inspect --format '{{.Mounts}}'pour les montageslsdans le conteneur pour confirmer la présence des fichiers- 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 --helpdans le conteneur
Scénario 2 : mémoire insuffisante (OOM Killed)
Signes typiques :
- Exit Code 137
docker inspect --format '{{.State.OOMKilled}}'retournetrue- 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-reservationcomme 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 :
- 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.
- 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 :
- État du conteneur (
docker ps -a) - Logs (
docker logs) - Configuration (
docker inspect) - 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
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
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
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 ?
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 ?
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 ?
• 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 ?
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
Guide pratique Docker
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Débogage des conteneurs Docker : utiliser exec pour entrer dans un conteneur
Guide pratique de docker exec pour entrer dans un conteneur : différences exec/attach, installation d'outils, gestion des permissions utilisateur et exemples de commandes pour diagnostiquer rapidement les problèmes.
Partie 36 sur 38
Suivant
Dev Sandbox auto-hébergé avec Docker et Go : des preview URL sans Kubernetes
Guide pratique pour créer des Dev Sandboxes auto-hébergés avec Docker, Go et Traefik : preview URL, limites de ressources, sécurité et exploitation.
Partie 38 sur 38



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire