Introduction
Lorsqu’un conteneur ne peut pas joindre un autre conteneur, le monde extérieur ou un nom DNS, la cause peut se cacher dans le modèle réseau en couches de Docker. Ce guide propose une approche pratique, axée sur les commandes, pour dépanner le réseau Docker. Il s’adresse aux développeurs, aux ingénieurs DevOps et aux équipes techniques de startups qui doivent passer de « ça ne marche pas » à une correction vérifiée sans conjectures.
Nous nous concentrons sur quatre zones de défaillance récurrentes : la résolution DNS, les ports publiés, la connectivité entre conteneurs et les mauvaises configurations réseau générales. Chaque section associe des commandes, des sorties attendues, des signaux d’échec et des étapes de récupération. L’objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d’impact, utiliser des espaces réservés plutôt que des secrets, vérifier les résultats et documenter les chemins de récupération.
Le réseau Docker n’est pas une chose unique. C’est un empilement de choix : réseaux pont (bridge), réseaux overlay, réseau hôte, DNS personnalisé, règles iptables et réseaux définis par l’utilisateur. Une approche méthodique vous évite de modifier des choses à l’aveugle. Nous commençons par un inventaire de l’environnement, puis nous parcourons des flux de diagnostic spécifiques.
Inventaire de la version et de l’environnement
Avant de dépanner, connaissez votre environnement. La version de Docker, le pilote de stockage, les plugins réseau et le runtime des conteneurs influencent tous le comportement du réseau. Une discordance entre les versions de Docker ou un module noyau manquant peut causer des problèmes qui ressemblent à des bogues applicatifs.
Exécutez d’abord ces commandes en lecture seule pour capturer l’état actuel :
docker version
Cela affiche les versions du client et du serveur. Si elles diffèrent fortement, certaines fonctionnalités peuvent ne pas fonctionner. Par exemple, les réseaux overlay nécessitent Docker Engine 1.12 ou ultérieur. Copiez la sortie dans vos notes.
docker info
Recherchez les lignes « Storage Driver », « Network » et « Kernel Version ». La ligne « Network » indique les pilotes réseau disponibles (par exemple, bridge, overlay, macvlan). Si un pilote est manquant, les conteneurs qui l’utilisent ne démarreront pas.
Ensuite, listez les conteneurs en cours d’exécution et leur état de santé :
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
La sortie peut ressembler à ceci :
NAMES STATUS PORTS
web Up 2 minutes 0.0.0.0:8080->80/tcp
db Up 2 minutes 3306/tcp
cache Exited (1) 10 seconds ago
Remarquez que cache est arrêté. Si un conteneur est arrêté, consultez ses journaux :
docker logs cache --tail 100
Si vous avez besoin des détails complets de configuration, utilisez inspect :
docker inspect web
Cela renvoie un objet JSON avec le réseau, les montages, les variables d’environnement et l’état de santé. Pour extraire uniquement les paramètres réseau :
docker inspect web --format '{{json .NetworkSettings}}' | jq
Pour les projets Docker Compose, ces commandes sont équivalentes et souvent plus simples :
docker compose ps
docker compose logs -f web
docker compose exec db sh
L’utilisation de docker compose exec vous permet de déboguer à l’intérieur d’un conteneur sans modifier l’image. Notez toutefois que le conteneur doit être en cours d’exécution.
Lorsque des données sont impliquées, confirmez l’emplacement des fichiers avant de modifier les conteneurs. Un volume nommé tel que app_data:/var/lib/app est géré par Docker et est généralement plus facile à réutiliser lors de reconstructions de conteneurs. Un montage bind tel que ./data:/var/lib/app mappe directement un répertoire hôte et est utile pour le développement local, mais il peut exposer des problèmes de permissions, de portabilité et de sauvegarde si le même chemin n’existe pas sur une autre machine.
Un petit test local de type production doit inclure un test de redémarrage : arrêtez le conteneur, recréez-le et confirmez que l’application voit toujours les fichiers attendus. Si les données disparaissent, le service écrivait probablement dans le système de fichiers du conteneur au lieu d’un volume ou d’un montage.
Chemin de configuration sécurisé
Une fois que vous comprenez l’état actuel, apportez des modifications avec prudence. La configuration réseau Docker est souvent globale ou par réseau. Une mauvaise modification peut perturber tous les conteneurs d’un hôte.
Isoler le réseau
Avant de modifier quoi que ce soit, identifiez le ou les réseaux concernés. Listez tous les réseaux :
docker network ls
Sortie typique :
NETWORK ID NAME DRIVER SCOPE
abc123def456 bridge bridge local
def456abc789 host host local
789def456abc none null local
123abc789def myapp bridge local
Les réseaux par défaut (bridge, host, none) sont toujours présents. Les réseaux personnalisés comme myapp sont généralement créés par l’utilisateur ou par Compose.
Inspectez le réseau pour voir les conteneurs attachés et les détails du sous-réseau :
docker network inspect myapp
Cela renvoie du JSON. Voici un exemple compacté montrant les champs importants :
[
{
"Name": "myapp",
"Id": "123abc789def...",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Containers": {
"web_container_id": {
"Name": "web",
"IPv4Address": "172.18.0.2/16"
}
}
}
]
Si le sous-réseau chevauche votre réseau hôte ou un autre réseau Docker, vous rencontrerez des problèmes de routage. Dans ce cas, créez un nouveau réseau avec un sous-réseau sans chevauchement :
docker network create --subnet 192.168.100.0/24 --gateway 192.168.100.1 myapp_fixed
Reconnectez ensuite les conteneurs au nouveau réseau. Pour Compose, modifiez la section networks de votre docker-compose.yml et exécutez docker compose up -d.
Modifier une chose à la fois
Supposons qu’un conteneur ne puisse pas résoudre un nom DNS. Vous pourriez être tenté de changer le serveur DNS, de modifier /etc/hosts et de redémarrer Docker en même temps. Suivez plutôt un chemin par étapes :
- Vérifiez si le conteneur peut joindre un réseau quelconque (ping d’une IP).
- Vérifiez s’il peut résoudre un nom (dig ou nslookup).
- Sinon, inspectez la configuration DNS à l’intérieur du conteneur.
- Modifiez uniquement le paramètre DNS (par exemple, dans le réseau ou la configuration du conteneur).
- Redémarrez le conteneur et testez à nouveau.
Chaque modification doit être réversible. Tenez un journal des commandes. Par exemple :
# Avant modification : le conteneur ne peut pas résoudre google.com
# Modification : ajouter l’option dns au conteneur
docker run --dns 8.8.8.8 --name test busybox nslookup google.com
# Après modification : la sortie attendue affiche l’adresse IP
Si la modification ne résout pas le problème, revenez en arrière et essayez l’hypothèse suivante.
Vérification et diagnostics
Cette section fournit des flux de diagnostic spécifiques pour les problèmes réseau Docker courants.
Problème 1 : le conteneur ne peut pas atteindre Internet
Symptômes : apt-get update échoue, curl vers des sites externes expire, mais d’autres conteneurs sur le même hôte peuvent fonctionner.
Étapes de diagnostic :
- Testez la connectivité depuis l’intérieur du conteneur vers une IP externe (en contournant le DNS) :
docker exec -it web ping 8.8.8.8
Sortie attendue si le réseau fonctionne :
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=117 time=10.5 ms
Si le ping échoue, le conteneur n’a pas de route vers Internet. Vérifiez le routage de l’hôte et les règles iptables.
- Testez la résolution DNS :
docker exec -it web nslookup google.com
Sortie attendue :
Server: 127.0.0.11
Address: 127.0.0.11#53
Non-authoritative answer:
Name: google.com
Address: 142.250.72.14
Si l’adresse IP est résolue, le DNS fonctionne. Si elle échoue avec un délai d’attente, le DNS est cassé.
- Inspectez la configuration DNS du conteneur :
docker exec -it web cat /etc/resolv.conf
Sur le réseau pont par défaut de Docker, vous verrez :
nameserver 127.0.0.11
options ndots:0
Le serveur DNS intégré à 127.0.0.11 transmet les requêtes aux serveurs DNS de l’hôte. Si vous avez un réseau personnalisé, vous pouvez définir un DNS différent :
docker network create --dns 1.1.1.1 mynet
Ou lors de l’exécution d’un conteneur :
docker run --dns 1.1.1.1 --name test busybox nslookup google.com
Récupération :
- Si l’hôte lui-même ne peut pas atteindre Internet, corrigez d’abord le réseau hôte.
- Si le DNS est mal configuré, ajustez les paramètres DNS sur le réseau ou le conteneur.
- Si des règles iptables bloquent, vérifiez
iptables -L -n -vet les règles NAT de Docker.
Problème 2 : le port publié n’est pas accessible depuis l’hôte
Symptômes : vous avez mappé un port avec -p 8080:80, mais curl localhost:8080 sur l’hôte échoue.
Étapes de diagnostic :
- Vérifiez que le conteneur est en cours d’exécution et que les ports sont mappés :
docker ps --format "{{.Names}}\t{{.Ports}}"
La sortie attendue affiche 0.0.0.0:8080->80/tcp. Si le mappage est absent, le conteneur n’a pas été démarré avec le drapeau -p.
- Vérifiez si le service à l’intérieur du conteneur écoute :
docker exec web netstat -tulpn | grep 80
Sortie attendue :
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
Si rien n’écoute sur le port 80, l’application à l’intérieur ne fonctionne pas correctement.
- Vérifiez les iptables de l’hôte :
sudo iptables -t nat -L -n | grep 8080
Vous devriez voir une règle DNAT transférant le port 8080 vers l’IP du conteneur et le port 80.
Récupération :
- Si le mappage de port est incorrect, recréez le conteneur avec le bon drapeau
-p. - Si le service n’écoute pas, corrigez l’application.
- Si les règles iptables manquent, redémarrez Docker ou ajoutez les règles manuellement.
Problème 3 : les conteneurs sur le même réseau ne peuvent pas communiquer
Symptômes : deux conteneurs sur un réseau défini par l’utilisateur ne peuvent pas se pinger par nom ou par IP.
Étapes de diagnostic :
- Confirmez que les deux conteneurs sont attachés au même réseau :
docker network inspect myapp --format '{{range .Containers}}{{.Name}} {{.IPv4Address}}{{"\n"}}{{end}}'
La sortie attendue liste les deux conteneurs avec leurs IP.
- Testez la connectivité par IP :
docker exec web ping 172.18.0.3
Si cela fonctionne, la connectivité IP est bonne ; le problème est la résolution de noms.
- Testez par nom de conteneur :
docker exec web ping db
Si la résolution de nom échoue, vérifiez le DNS intégré. Sur les réseaux définis par l’utilisateur, le DNS intégré de Docker doit résoudre automatiquement les noms de conteneurs en IP.
Récupération :
- Si le ping IP échoue, vérifiez si les conteneurs sont sur le même réseau ou s’il existe une règle iptables bloquant le trafic.
- Si la résolution de nom échoue, assurez-vous que les noms de conteneurs sont uniques et que le réseau est défini par l’utilisateur (pas le pont par défaut, qui ne fournit pas de DNS automatique).
Problème 4 : la résolution DNS échoue pour les domaines personnalisés
Symptômes : les conteneurs ne peuvent pas résoudre un domaine qui pointe vers un service à l’intérieur du réseau Docker (par exemple, api.internal).
Étapes de diagnostic :
- Vérifiez la configuration DNS :
docker exec web cat /etc/resolv.conf
Le DNS intégré à 127.0.0.11 ne résout que les noms de conteneurs sur les réseaux définis par l’utilisateur, pas les domaines personnalisés arbitraires.
- Définissez un serveur DNS personnalisé ou ajoutez des entrées d’hôte.
Pour un serveur DNS personnalisé :
docker network create --dns 192.168.1.10 mynet
Pour ajouter une entrée d’hôte :
docker run --add-host api.internal:192.168.1.20 --name test busybox cat /etc/hosts
Récupération :
- Utilisez
--dnspour un DNS à l’échelle du réseau. - Utilisez
--add-hostpour des mappages d’hôte statiques par conteneur. - Ou exécutez un serveur DNS local comme conteneur et pointez les autres conteneurs vers lui.
Modes de défaillance et récupération
Voici les modes de défaillance courants, leurs symptômes et les stratégies de récupération.
1. Épuisement des adresses IP
Symptôme : les nouveaux conteneurs ne démarrent pas avec une erreur du type failed to allocate IP address ou no available addresses on network.
Pourquoi cela arrive : le réseau pont par défaut utilise un sous-réseau /16 (172.17.0.0/16), ce qui permet 65 534 adresses, mais un réseau personnalisé peut avoir un sous-réseau plus petit. Si vous avez beaucoup de conteneurs ou si vous les recréez fréquemment, vous pouvez épuiser le pool.
Comment récupérer :
- Vérifiez le sous-réseau et les IP utilisées :
docker network inspect myapp --format '{{.IPAM.Config}}'
- Augmentez la taille du sous-réseau en créant un nouveau réseau avec un sous-réseau plus grand, puis reconnectez les conteneurs.
- Supprimez les conteneurs obsolètes qui détiennent des IP.
2. Délais d’attente de résolution DNS
Symptôme : la résolution de noms se bloque puis expire.
Pourquoi cela arrive : le serveur DNS intégré transmet les requêtes aux serveurs DNS de l’hôte. Si le DNS de l’hôte est lent ou injoignable, toute la résolution DNS des conteneurs sera lente. De plus, les paramètres ndots peuvent causer des recherches supplémentaires.
Comment récupérer :
- Vérifiez la configuration DNS de l’hôte :
cat /etc/resolv.confsur l’hôte. - Spécifiez un serveur DNS plus rapide pour les réseaux Docker :
docker network create --dns 1.1.1.1 --dns 8.8.8.8 mynet. - Pour les conteneurs, utilisez le drapeau
--dns.
3. Chevauchement de réseaux
Symptôme : les conteneurs peuvent atteindre certaines IP mais pas d’autres ; le routage est incohérent.
Pourquoi cela arrive : les sous-réseaux par défaut de Docker (172.17.0.0/16, 172.18.0.0/16, etc.) peuvent chevaucher les réseaux internes de votre organisation. Le trafic peut être routé incorrectement.
Comment récupérer :
- Identifiez le chevauchement en comparant les sous-réseaux Docker avec vos sous-réseaux internes.
- Créez un nouveau réseau Docker avec un sous-réseau sans chevauchement, par exemple
10.100.0.0/16. - Mettez à jour la configuration de votre application pour utiliser le nouveau réseau.
4. Le conteneur ne peut pas atteindre les services de l’hôte
Symptôme : un conteneur ne peut pas se connecter à un service exécuté sur l’hôte (par exemple, une base de données sur localhost).
Pourquoi cela arrive : sur le réseau pont par défaut, l’hôte est joignable à l’adresse IP de la passerelle (généralement 172.17.0.1), mais localhost à l’intérieur du conteneur fait référence au conteneur lui-même.
Comment récupérer :
- Utilisez le nom d’hôte spécial
host.docker.internal(sur Docker Desktop pour Mac/Windows) ou l’IP de la passerelle pour atteindre l’hôte. - Pour Linux, ajoutez
--add-host=host.docker.internal:host-gatewayà votre commandedocker run.
5. Pare-feu bloquant le trafic des conteneurs
Symptôme : les clients externes ne peuvent pas atteindre les ports publiés, même si docker ps montre le mappage de port.
Pourquoi cela arrive : le pare-feu de l’hôte (par exemple, UFW, firewalld) peut bloquer les connexions entrantes vers le port publié. Docker manipule directement iptables, ce qui peut entrer en conflit avec les règles du pare-feu.
Comment récupérer :
- Vérifiez l’état du pare-feu :
sudo ufw statusousudo firewall-cmd --list-all. - Ouvrez le port nécessaire :
sudo ufw allow 8080/tcp. - Ajustez l’intégration iptables de Docker si nécessaire (généralement non recommandé sauf si vous savez ce que vous faites).
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour les opérations réseau Docker quotidiennes. Chaque élément inclut le rôle responsable et la fréquence de révision.
| Élément | Commande ou action | Responsable | Fréquence |
|---|---|---|---|
| Vérifier la version de Docker et les pilotes réseau | docker version, docker info | Ingénieur DevOps | Mensuel |
| Lister les conteneurs en cours d’exécution et les mappages de ports | docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | Ingénieur de garde | Contrôle de santé quotidien |
| Vérifier la configuration réseau | docker network ls, docker network inspect <net> | Ingénieur DevOps | Lors de modifications réseau |
| Tester la connectivité entre conteneurs | docker exec <conteneur> ping <autre-conteneur> | Ingénieur de garde | Au besoin |
| Valider la résolution DNS | docker exec <conteneur> nslookup google.com | Ingénieur de garde | Au besoin |
| Réviser les règles de publication de ports | sudo iptables -t nat -L -n -v | Administrateur sécurité/réseau | Trimestriel |
| Tester la récupération après redémarrage | Arrêter et démarrer les conteneurs, vérifier la persistance des données | Ingénieur DevOps | Avant chaque version |
| Mettre à jour les règles du pare-feu | sudo ufw status, ouvrir les ports nécessaires | Administrateur réseau | Lors de modifications de ports |
| Nettoyer les réseaux et conteneurs inutilisés | docker network prune, docker container prune | Ingénieur DevOps | Mensuel |
Pour chaque décision majeure, comme le changement d’un sous-réseau réseau ou l’ajout d’un nouveau réseau, attribuez un responsable unique. Par exemple, l’ingénieur DevOps est propriétaire de la conception du réseau, et l’ingénieur de garde est propriétaire des corrections immédiates. Révisez la configuration réseau au moins trimestriellement ou après tout incident significatif.
Pièges courants et comment les éviter
Piège 1 : utiliser le pont par défaut pour la communication entre conteneurs
Problème : les conteneurs sur le réseau pont par défaut peuvent communiquer par IP mais pas par nom, car le pont par défaut ne fournit pas de résolution DNS automatique.
Pourquoi cela arrive : de nombreux tutoriels utilisent le pont par défaut pour simplifier, mais il lui manque le service DNS disponible sur les réseaux définis par l’utilisateur.
Comment éviter : créez toujours un réseau pont défini par l’utilisateur pour votre application :
docker network create myapp
Exécutez ensuite les conteneurs avec --network myapp. Dans Compose, définissez un réseau personnalisé.
Piège 2 : supposer que localhost à l’intérieur du conteneur fait référence à l’hôte
Problème : les développeurs essaient souvent de se connecter à un service hôte en utilisant localhost depuis l’intérieur d’un conteneur et échouent.
Pourquoi cela arrive : chaque conteneur a son propre espace de noms réseau, donc localhost est le conteneur lui-même.
Comment éviter : utilisez l’IP de la passerelle ou host.docker.internal comme décrit précédemment. Par exemple, dans Docker Desktop, connectez-vous à host.docker.internal:5432 pour un Postgres sur l’hôte.
Piège 3 : liaisons de ports mal configurées
Problème : liaison à la mauvaise interface ou utilisation des mauvais ports.
Pourquoi cela arrive : par défaut, Docker publie les ports sur toutes les interfaces (0.0.0.0). Si vous voulez restreindre l’accès, vous devez spécifier l’IP de l’hôte.
Comment éviter : liez explicitement à l’interface désirée :
docker run -p 127.0.0.1:8080:80 nginx
Cela restreint l’accès à localhost uniquement.
Piège 4 : ignorer les limitations des pilotes réseau
Problème : essayer d’utiliser des réseaux overlay sans le mode swarm ou un magasin clé-valeur.
Pourquoi cela arrive : les réseaux overlay sont conçus pour le réseau multi-hôtes et nécessitent le mode swarm ou un magasin clé-valeur externe (pour les anciennes versions de Docker).
Comment éviter : utilisez les réseaux overlay uniquement en mode swarm ou avec une configuration appropriée. Pour un hôte unique, utilisez les pilotes bridge ou macvlan.
Piège 5 : ne pas nettoyer les réseaux
Problème : les réseaux inutilisés accumulés mènent à la confusion et aux conflits d’IP.
Pourquoi cela arrive : les réseaux ne sont pas automatiquement supprimés lorsque les conteneurs sont supprimés.
Comment éviter : élaguez périodiquement les réseaux inutilisés :
docker network prune
Cela supprime tous les réseaux non utilisés par au moins un conteneur. Utilisez docker network ls pour réviser avant d’élaguer.
Conclusion
Le dépannage réseau Docker est un processus systématique d’observation, de modification ciblée et de vérification. En suivant les étapes d’inventaire et de diagnostic de ce guide, vous pouvez résoudre la plupart des problèmes sans conjectures. La clé est de comprendre le modèle réseau de Docker : les réseaux pont définis par l’utilisateur avec DNS intégré, la publication de ports via iptables et les différences entre les espaces de noms réseau des conteneurs et de l’hôte.
Comme prochaine étape, choisissez une vérification à faible risque dans la liste de contrôle, enregistrez l’état actuel, exécutez la vérification documentée, comparez le résultat avec le signal attendu et examinez les dépendances. Un flux de travail technique fiable rend les défaillances visibles, protège les valeurs sensibles, limite les modifications à la ressource prévue et définit la vérification de récupération avant qu’un incident ne force la décision.
N’oubliez pas d’attribuer une propriété claire pour les modifications réseau et de réviser régulièrement votre configuration réseau. Avec ces pratiques, vous pouvez garder vos environnements Docker stables et vos applications connectées.