## Intro

Les erreurs Docker peuvent sembler opaques, mais la plupart reviennent à un petit nombre de causes répétitives. Ce guide relie les erreurs les plus fréquentes à leurs causes racines, propose un flux de diagnostic pas à pas et présente des correctifs modernes, sûrs et vérifiables localement avant déploiement.

Pour qui :

- Développeurs qui livrent des services en conteneurs

- Ingénieurs DevOps qui standardisent la réponse aux incidents

- Équipes de startup qui construisent des pipelines de livraison fiables

Ce que vous obtiendrez :

- Un workflow reproductible pour diagnostiquer vite et sans risque

- Des correctifs pratiques pour les problèmes de build, d’exécution, de réseau, de volumes et de registre

- Un petit pilote local pour stabiliser les améliorations avant de les étendre

## Aperçu du workflow

Utilisez ce flux pour couper le bruit et éviter le rework :

- Reproduire exactement

- Capturez la commande complète et les versions :

- docker --version

- docker compose version

- docker info (masquez les secrets)

- docker buildx version

- docker context ls

- Relancez avec des journaux complets :

- docker build --progress=plain .

- docker run --rm -it IMAGE[:TAG] COMMAND

- docker compose up --build puis docker compose logs -f

- Lire tout le message d’erreur

- Beaucoup d’erreurs Docker affichent un court résumé, la vraie cause se trouvant quelques lignes plus haut. Faites défiler et capturez la première ligne en échec.

- Réduire le scénario

- Créez un Dockerfile de repro minimal et isolez l’étape fautive avec un seul COPY ou RUN .

- Remplacez votre app par une base connue et saine (ex. alpine , nginx:alpine ) pour différencier problème infra vs applicatif.

- Comparer la configuration

- Comparez tags, plateformes et montages qui fonctionnent vs échouent.

- Inspectez le Dockerfile étape par étape; vérifiez la sortie de docker compose config .

- Confirmez le contexte de build et tout override.

- Appliquer le plus petit correctif sûr

- Préférez les changements de configuration (chemins, permissions, plateforme) avant les modifications de code.

- Vérifier localement sur une base propre

- Optionnellement nettoyer les ressources inutilisées : docker system df puis docker system prune -f (attention : supprime les ressources non utilisées)

- Rebuilder : docker build --no-cache .

- Exécuter : docker run --rm IMAGE[:TAG]

## Erreurs de build courantes

### 1) COPY failed: file not found in build context

Symptômes :

- COPY failed: file not found in build context or excluded by .dockerignore

Pourquoi cela arrive :

- Le fichier est hors du contexte de build (le chemin passé à docker build ).

- .dockerignore exclut le fichier ou son répertoire parent.

Comment diagnostiquer :

- Confirmez le contexte : docker build -f app/Dockerfile ./app vs docker build -f app/Dockerfile .

- Listez les fichiers vus par Docker : tar -cz . | tar -tz | head (à exécuter dans le répertoire de contexte visé)

- Inspectez les motifs .dockerignore qui pourraient exclure des fichiers nécessaires.

Correctif :

- Construisez depuis le bon répertoire et ajustez les chemins.

- Mettez à jour .dockerignore pour conserver les fichiers requis.

Exemple :

# Faux : build depuis la racine du dépôt alors que le Dockerfile suppose le contexte ./app
docker build -t myapp -f app/Dockerfile .

# Correct : passer ./app comme contexte de build
docker build -t myapp -f app/Dockerfile ./app 

### 2) exec format error (incompatibilité d’architecture)

 Symptômes :

- standard_init_linux.go:... exec format error

- L’image fonctionne sur une machine mais pas sur une autre (ex. portable ARM vs serveur AMD64).

Pourquoi cela arrive :

- La plateforme de l’image ne correspond pas à l’hôte ou au nœud cible.

Comment diagnostiquer :

- Vérifiez l’archi de l’hôte : uname -m

- Vérifiez les plateformes de l’image : docker buildx imagetools inspect IMAGE:TAG

Correctif :

- Construisez ou tirez pour la bonne plateforme avec BuildKit/Buildx.

Exemples :

# Forcer la plateforme au build ou à l’exécution
docker buildx build --platform linux/amd64 -t myapp:amd64 .
docker run --rm --platform linux/amd64 myapp:amd64

# Construire une image multi-arch et pousser une liste de manifestes
docker buildx create --use --name multi
docker buildx build --platform linux/amd64,linux/arm64 -t registry.example.com/myorg/myapp:1.0 --push . 

### 3) no space left on device

 Symptômes :

- Les builds échouent lors de l’écriture des couches ou pendant l’installation de paquets.

Pourquoi cela arrive :

- Les images, couches et caches de build Docker ont saturé le disque.

Comment diagnostiquer :

- docker system df

- Sous Linux : df -h et du -sh /var/lib/docker/* (chemin variable selon l’installation)

Correctif :

# Libérer de l’espace (à utiliser avec précaution)
docker system prune -f
docker image prune -a -f
docker volume prune -f
# Spécifiquement pour le cache de build
docker builder prune -f 
 Conseils pratiques :

- Utilisez des builds multi-étapes pour éviter d’embarquer les outils de build dans l’image finale.

- Nettoyez les caches de paquets dans la même couche RUN (ex. apt-get clean && rm -rf /var/lib/apt/lists/* ).

- Utilisez les montages de cache BuildKit pour accélérer les installations sans gonfler les couches :

# Exemple pour pip
RUN --mount=type=cache,target=/root/.cache/pip \
 pip install --no-cache-dir -r requirements.txt 

### 4) RUN échoue à cause du shell ou des fins de ligne

 Symptômes :

- /bin/sh: 1: script.sh: not found

- exec user process caused: no such file or directory

Pourquoi cela arrive :

- Fins de ligne Windows CRLF, bit exécutable manquant, mauvais shebang, ou usage de bash alors que l’image ne contient que sh .

Correctif :

# Normaliser les fins de ligne au commit
git config core.autocrlf input

# Convertir les fichiers si nécessaire
dos2unix script.sh

# Assurer les permissions et un shebang valide
chmod +x script.sh
sed -n '1p' script.sh # doit commencer par #!/bin/sh ou #!/usr/bin/env bash 
 Si vous avez besoin des fonctionnalités Bash, définissez explicitement le shell dans le Dockerfile :

SHELL ["/bin/bash", "-o", "pipefail", "-c"] 

### 5) Confusion liée au cache de build

 Symptômes :

- Anciennes dépendances persistantes; les changements ne s’appliquent pas comme prévu.

Correctif et vérification :

# Afficher la sortie détaillée pour comprendre les décisions de cache
docker build --progress=plain .

# Forcer des couches fraîches quand nécessaire
docker build --no-cache --pull . 
 Bonne pratique : placez les étapes les plus stables (dépendances système) avant la copie du code applicatif pour maximiser la réutilisation du cache.

## Erreurs d’exécution et Compose

### 1) Port déjà alloué

Symptômes :

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

Comment diagnostiquer :

- docker ps --format 'table {{.ID}}\t{{.Image}}\t{{.Ports}}'

- lsof -i :80 (Linux/macOS) ou Get-NetTCPConnection -LocalPort 80 (PowerShell)

Correctif :

# Remapper le port hôte
docker run -p 8080:80 nginx:alpine 
 Exemple Compose :

services:
 web:
 image: nginx:alpine
 ports:
 - "8080:80" 

### 2) exec user process caused: no such file or directory

 Symptômes :

- Le conteneur se termine immédiatement au démarrage.

Pourquoi cela arrive :

- L’ENTRYPOINT/CMD pointe vers un fichier manquant ou avec des fins de ligne CRLF.

Comment diagnostiquer et corriger :

# Inspecter les fichiers à l’intérieur de l’image
docker run --rm -it --entrypoint sh myapp:tag -c 'ls -l /app && file /app/entrypoint.sh && cat -A /app/entrypoint.sh | head'
# Puis normaliser les fins de ligne et les permissions comme dans les correctifs de build 
 Assurez-vous que les chemins ENTRYPOINT/CMD sont absolus et que les fichiers existent dans l’étape finale des builds multi-étapes.

### 3) OCI runtime create failed: permission denied

Pourquoi cela arrive :

- Permissions de bind mount, limites de Docker rootless, ou labels SELinux sous Linux.

Correctifs :

# Aligner l’utilisateur du conteneur avec les fichiers de l’hôte
docker run -u $(id -u):$(id -g) -v "$PWD/data":/data myapp:tag

# Sur un hôte SELinux, étiqueter les bind mounts (:z partagé, :Z privé)
docker run -v "$PWD/data":/data:Z myapp:tag 
 Si vous avez besoin de root dans le conteneur avec Docker rootless, reconsidérez cette exigence ou basculez vers un environnement privilégié seulement si justifié.

### 4) Réseau introuvable dans Compose

Symptômes :

- network mynet declared as external, but could not be found

Correctif :

# Créer explicitement le réseau
docker network create mynet
# Ou laisser Compose le gérer en supprimant external: true 
 Vérifiez avec docker network ls et docker compose config .

### 5) Le conteneur n’arrive pas à joindre un service hôte via localhost

Symptômes :

- L’application dans le conteneur n’atteint pas un service de l’hôte via localhost .

Correctif :

- Utilisez host.docker.internal (macOS/Windows, et Linux Desktop récents) ou l’IP du pont Docker (souvent 172.17.0.1 sous Linux).

curl http://host.docker.internal:3000 

## Réseau et DNS

### 1) Temporary failure in name resolution

 Symptômes :

- Les résolutions DNS échouent à l’intérieur du conteneur.

Pourquoi cela arrive :

- DNS de l’hôte/resolveur atypique, proxy d’entreprise, ou sortie vers Internet bloquée.

Comment diagnostiquer et corriger :

# Tester le DNS dans un conteneur éphémère
docker run --rm busybox nslookup google.com || true

# Surcharger le DNS par conteneur (test rapide)
docker run --rm --dns 8.8.8.8 busybox nslookup google.com 
 DNS au niveau du daemon (puis redémarrer Docker) :

{
 "dns": ["8.8.8.8", "1.1.1.1"]
} 
 Derrière un proxy : définissez HTTP_PROXY , HTTPS_PROXY et NO_PROXY pour le build et l’exécution. Pour les builds :

docker build --build-arg HTTP_PROXY=http://proxy:3128 --build-arg HTTPS_PROXY=http://proxy:3128 . 

### 2) Cannot pull: lookup registry-1.docker.io: no such host

 Correctif :

- Appliquez les mêmes étapes DNS ci‑dessus.

- Vérifiez la connectivité de l’hôte : curl -I https://registry-1.docker.io .

- Envisagez un miroir de registre via "registry-mirrors" dans daemon.json si votre réseau est restrictif.

### 3) certificate signed by unknown authority (CA d’entreprise)

Symptômes :

- Les pulls/builds vers des registres internes échouent la vérification TLS.

Correctif dans l’image (confiance au runtime) :

COPY corp-ca.crt /usr/local/share/ca-certificates/
RUN update-ca-certificates 
 Pour le trust store du daemon Docker, installez votre CA selon le guide de votre OS puis redémarrez Docker.

## Volumes et permissions

### 1) Permission denied sur les bind mounts

Symptômes :

- L’application ne peut pas lire/écrire les fichiers montés.

Pourquoi cela arrive :

- Décalage UID/GID entre l’hôte et l’utilisateur du conteneur; labels SELinux sous Linux.

Comment diagnostiquer :

- Sur l’hôte : stat -c "%u:%g" data/

- Dans le conteneur : id , ls -l /data

Correctifs :

# Exécuter avec l’UID/GID correspondant
docker run -u $(id -u):$(id -g) -v "$PWD/data":/data myapp:tag

# Préférer les volumes nommés pour des écritures plus portables
docker volume create appdata
docker run -v appdata:/data myapp:tag 
 Exemple Compose (avec SELinux) :

volumes:
 data: {}
services:
 app:
 image: myapp:tag
 user: "${UID:-1000}:${GID:-1000}"
 volumes:
 - data:/data
 - "${PWD}/data:/data-host:Z" 

### 2) Partage de fichiers non activé (macOS/Windows)

 Symptômes :

- Le bind mount apparaît vide ou échoue.

Correctif :

- Activez le partage de fichiers pour le lecteur/dossier dans les réglages Docker Desktop. Sous Windows avec WSL 2, privilégiez un montage depuis le système de fichiers Linux (par ex. dans ~/project ) pour de meilleures performances.

## Images et registre

### 1) pull access denied, repository does not exist or may require authorization

Correctif :

# Vérifier le nom d’image et le tag
docker pull registry.example.com/team/app:1.2.3

# S’authentifier auprès du registre
docker login registry.example.com 

### 2) manifest unknown or not found

 Pourquoi cela arrive :

- Le tag n’existe pas ou le manifeste pour votre plateforme manque.

Correctif :

# Inspecter les plateformes disponibles
docker buildx imagetools inspect IMAGE:TAG

# Tirer pour une plateforme spécifique si disponible
docker pull --platform linux/amd64 IMAGE:TAG 

### 3) Rate limit exceeded (registres publics)

 Correctif :

- Authentifiez‑vous pour augmenter les limites.

- Utilisez un miroir privé ou un cache de registre.

- Regroupez et figez les images de base pour réduire le churn.

## Performances et ressources

### 1) OOMKilled ou pression mémoire

Symptômes :

- Le conteneur s’arrête; docker inspect indique "OOMKilled": true .

Comment diagnostiquer :

- docker stats pour observer l’usage mémoire en temps réel.

- Vérifiez les journaux applicatifs pour repérer des pics.

Correctif :

# Définir des limites à l’exécution
docker run --memory=512m --memory-swap=512m myapp:tag 
 Compose (s’applique aux implémentations Compose non‑Swarm) :

services:
 app:
 image: myapp:tag
 mem_limit: 512m
 cpus: 1.0 
 Ajustez l’empreinte mémoire de l’application et n’augmentez les limites qu’en cas de besoin.

### 2) Builds lents dus à des ratés de cache

Correctif :

- Réordonnez le Dockerfile : installez les dépendances OS avant de copier le code qui change souvent.

- Utilisez des builds multi‑étapes pour garder des images finales légères.

- Employez les montages de cache BuildKit pour les caches de langages/paquets (pip, npm, go, cargo).

- Figez les versions de dépendances pour rendre les hits de cache prévisibles.

Exemple (Python) :

FROM python:3.12-slim AS base
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
 pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"] 

## Plan pilote local

 Objectif

- Prouver que les erreurs courantes sont détectées et corrigées rapidement sur un seul service.

Périmètre

- Un Dockerfile (ex. service Nginx ou Python minimal).

- Un compose.yaml exposant un port HTTP et un répertoire de données inscriptible.

Étapes

- Créer un mini‑service

FROM nginx:alpine
COPY ./public /usr/share/nginx/html 

- Ajouter des vérifications d’échec courantes

- Supprimez un fichier de public et observez l’échec de COPY ; corrigez en ajustant le contexte et .dockerignore .

- Introduisez des CRLF dans un script shell ; corrigez avec des LF et chmod +x .

- Forcez un décalage de plateforme ; exécutez avec --platform pour vérifier le comportement.

- Montez en bind un répertoire de données ; testez les permissions via UID correspondants et :Z avec SELinux.

- Instrumenter un diagnostic rapide (Makefile optionnel)

 run:
 docker compose up --build
shell:
 docker run --rm -it --entrypoint sh myapp:dev
clean:
 docker system prune -f 

- Documenter les correctifs exacts

- Tenez un court troubleshooting.md avec le texte d’erreur, la cause et la commande utilisée pour corriger.

- Étendre progressivement

- Ajoutez un second service (ex. API) et un réseau défini par l’utilisateur.

- Ajoutez des pulls depuis un registre privé pour valider l’authentification et la gestion des tags.

## Conclusion

 La plupart des problèmes Docker se répètent d’un projet à l’autre : erreurs de chemin et de contexte, décalages de plateformes, particularités DNS/proxy et permissions sur les montages. Avec un workflow simple, les pratiques modernes BuildKit/Buildx et les correctifs ci‑dessus, vous pouvez diagnostiquer et résoudre rapidement et en sécurité. Démarrez avec le pilote local, capturez ce qui fonctionne et appliquez les mêmes schémas à Docker Compose, Kubernetes et vos pipelines CI.