Introduction
Le réseautage Docker est une source fréquente de frustration dans les environnements conteneurisés. Un conteneur qui ne peut pas atteindre sa base de données, un service qui ne peut pas résoudre un autre service par son nom, ou un mappage de port qui refuse de fonctionner peut interrompre le développement et perturber la production. Cet article se concentre sur les erreurs de réseautage Docker courantes et fournit des correctifs pratiques avec des exemples concrets. Il s'adresse aux développeurs, aux consultants DevOps et aux équipes techniques de startups qui doivent passer rapidement d'un problème observé à un résultat vérifié.
Nous couvrirons les modes de défaillance les plus courants, notamment les mauvaises configurations de réseaux bridge, les problèmes de réseaux overlay dans Swarm, les échecs de résolution DNS, les problèmes de publication de ports et les incidents IPv6. Pour chacun, nous montrons comment diagnostiquer le problème à l'aide des commandes Docker standard, comprendre la cause première, appliquer le correctif minimal sûr et vérifier le résultat. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets et documenter les étapes de récupération.
Tout au long de l'article, nous insistons sur une approche systématique :
- Inventorier l'environnement : connaître la version de Docker, la topologie et l'état actuel.
- Diagnostics en lecture seule : utiliser
docker network inspect,docker logs,docker execet d'autres commandes pour recueillir des preuves. - Changement minimal : ajuster un élément de configuration ciblé à la fois.
- Vérifier : confirmer le correctif avec une commande spécifique et une sortie attendue.
À la fin, vous disposerez d'un ensemble de procédures de dépannage reproductibles et d'une liste de contrôle pour prévenir les problèmes de réseau récurrents.
Inventaire de la version et de l'environnement
Avant de plonger dans les correctifs, établissez une base de référence. Connaître votre version de Docker, le pilote de stockage, les plugins réseau et le runtime de conteneur vous aide à éviter d'appliquer des conseils destinés à une configuration différente. Exécutez les commandes suivantes et enregistrez la sortie :
# Version de Docker
$ docker version --format '{{.Server.Version}}'
24.0.7
# Informations Docker (concentrez-vous sur les sections pertinentes pour le réseau)
$ docker info --format '{{json .Plugins.Network}}'
["bridge","host","overlay","macvlan"]
# Lister les conteneurs en cours d'exécution avec leurs réseaux
$ docker ps --format 'table {{.Names}} {{.Networks}} {{.Ports}}'
NAMES NETWORKS PORTS
web bridge 0.0.0.0:8080->80/tcp
db myapp_default
Pour les projets Compose, utilisez docker compose ps et inspectez le réseau généré :
$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
myapp_web_1 "docker-entrypoint.s…" web running 0.0.0.0:8080->80/tcp
myapp_db_1 "docker-entrypoint.s…" db running 5432/tcp
$ docker network ls | grep myapp
NETWORK ID NAME DRIVER SCOPE
abc123def456 myapp_default bridge local
Si vous soupçonnez un problème de plugin réseau, listez tous les réseaux avec leurs pilotes et leur portée :
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
1234567890ab bridge bridge local
cdef12345678 host host local
90abcdef1234 none null local
Un test local de type production devrait inclure un test de redémarrage : arrêtez le conteneur, recréez-le et confirmez que l'application voit toujours le réseau et les fichiers attendus. Si la connectivité se rompt après un redémarrage, vous avez probablement une configuration qui dépend d'adresses IP de conteneur éphémères ou d'une définition de réseau manquante.
Erreur courante 1 : le conteneur ne peut pas atteindre Internet ou les hôtes externes
Symptôme
Un conteneur ne peut pas ping une IP externe (par exemple, 8.8.8.8) ou curl une URL publique. L'erreur peut être ping: bad address ou curl: (6) Could not resolve host, indiquant une défaillance DNS ou de routage.
Diagnostic
Commencez par vérifier les paramètres réseau du conteneur :
$ docker exec mycontainer ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
Si le conteneur n'a pas d'IP ou si l'interface est désactivée, quelque chose ne va pas avec la création du réseau. Vérifiez l'attachement réseau du conteneur :
$ docker inspect --format '{{json .NetworkSettings.Networks}}' mycontainer
{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"NetworkID":"1234567890ab","EndpointID":"","Gateway":"","IPAddress":"","IPPrefixLen":0,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"","DriverOpts":null}}
Une IPAddress vide suggère que le conteneur n'a pas rejoint correctement le réseau. Essayez de le connecter explicitement :
$ docker network connect bridge mycontainer
Si le conteneur n'a toujours pas de connectivité, inspectez les paramètres DNS du démon Docker. Le démon utilise le fichier /etc/resolv.conf de l'hôte par défaut, mais vous pouvez le remplacer :
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "1234567890ab",
"Created": "2024-01-01T00:00:00.000000000Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"...": {}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
Si "Internal": true, le réseau est isolé du trafic externe. Si la résolution DNS échoue, vérifiez le fichier /etc/resolv.conf du conteneur :
$ docker exec mycontainer cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0
Le serveur DNS intégré à 127.0.0.11 devrait être présent. Sinon, le conteneur a été démarré avec des options --dns ou --dns-search qui peuvent être incorrectes.
Correctif
- Si le conteneur est sur un réseau personnalisé avec
internal: true, recréez le réseau sans ce drapeau ou connectez le conteneur à un réseau externe. - Si le DNS est mal configuré, démarrez le conteneur avec des serveurs DNS explicites :
$ docker run -d --name mycontainer --dns 8.8.8.8 --dns 1.1.1.1 myimage
- Si le réseau bridge par défaut cause des problèmes, créez un réseau bridge défini par l'utilisateur, qui fournit une résolution DNS automatique entre les conteneurs :
$ docker network create mynet
$ docker run -d --name mycontainer --network mynet myimage
- Vérifiez la connectivité :
$ docker exec mycontainer ping -c 4 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=18.6 ms
...
Erreur courante 2 : les conteneurs ne peuvent pas communiquer entre eux sur un réseau bridge défini par l'utilisateur
Symptôme
Deux conteneurs sur le même réseau bridge défini par l'utilisateur ne peuvent pas se résoudre par leur nom ou se connecter via IP. Par exemple, un conteneur web ne peut pas atteindre db à db:5432.
Diagnostic
Tout d'abord, confirmez que les deux conteneurs sont sur le même réseau :
$ docker network inspect mynet
[
{
"Name": "mynet",
"Id": "...",
"Containers": {
"container1_id": {
"Name": "web",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"container2_id": {
"Name": "db",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
}
}
]
Si un conteneur est manquant, connectez-le :
$ docker network connect mynet web
Vérifiez si les conteneurs peuvent se pinger par IP :
$ docker exec web ping -c 4 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.123 ms
...
Si le ping IP fonctionne mais que la résolution de nom échoue, testez avec nslookup ou getent :
$ docker exec web nslookup db
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: db
Address: 172.18.0.3
Si nslookup échoue, le serveur DNS intégré peut avoir des problèmes, ou le fichier /etc/resolv.conf du conteneur ne pointe pas vers 127.0.0.11.
Une erreur courante est d'utiliser le réseau bridge par défaut, qui ne fournit pas de résolution DNS automatique. Sur le bridge par défaut, les conteneurs ne peuvent communiquer que via des adresses IP (à moins d'utiliser --link, qui est obsolète).
Correctif
- Créez un réseau bridge défini par l'utilisateur et attachez-y les deux conteneurs :
$ docker network create mynet
$ docker network connect mynet web
$ docker network connect mynet db
- Alternativement, recréez les conteneurs avec le réseau spécifié au démarrage :
$ docker run -d --name web --network mynet webimage
$ docker run -d --name db --network mynet dbimage
- Testez à nouveau la résolution de nom :
$ docker exec web ping -c 1 db
PING db (172.18.0.3) 56(84) bytes of data.
64 bytes from db.mynet (172.18.0.3): icmp_seq=1 ttl=64 time=0.089 ms
Erreur courante 3 : le mappage de port ne fonctionne pas ou le port est déjà utilisé
Symptôme
Un conteneur est démarré avec -p 8080:80, mais l'accès à localhost:8080 échoue, ou le conteneur ne démarre pas avec Bind for 0.0.0.0:8080 failed: port is already allocated.
Diagnostic
Vérifiez si le port est déjà utilisé sur l'hôte :
$ sudo ss -tulpn | grep :8080
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("docker-proxy",pid=1234,fd=4))
Un autre conteneur peut utiliser le même port. Listez les mappages de ports :
$ docker ps --format '{{.Names}} {{.Ports}}'
web1 0.0.0.0:8080->80/tcp
web2 0.0.0.0:8080->80/tcp # Ceci échouera au démarrage
Si vous utilisez un pare-feu, assurez-vous que le port est autorisé. Vérifiez également que le processus du conteneur écoute réellement sur le port du conteneur :
$ docker exec web1 netstat -tulpn | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master p
Correctif
- Utilisez un port hôte différent :
$ docker run -d --name web2 -p 8081:80 webimage
- Ou utilisez le mappage de port dynamique et interrogez le port attribué :
$ docker run -d --name web2 -P webimage
$ docker port web2
80/tcp -> 0.0.0.0:49153
- Si un port doit être libéré, identifiez et arrêtez le processus qui l'utilise, puis redémarrez le conteneur.
Erreur courante 4 : problèmes de réseau overlay dans Docker Swarm
Symptôme
Dans un cluster Swarm, les services sur différents nœuds ne peuvent pas communiquer via un réseau overlay. Des erreurs comme No route to host ou des échecs de résolution de nom se produisent.
Diagnostic
Tout d'abord, assurez-vous que le réseau overlay existe et est attaché aux services :
$ docker network ls | grep overlay
NETWORK ID NAME DRIVER SCOPE
xyz123abc456 myoverlay overlay swarm
$ docker service inspect --format '{{json .Spec.TaskTemplate.Networks}}' myservice
[{"Target":"xyz123abc456"}]
Vérifiez que tous les nœuds ont les ports nécessaires ouverts pour le réseautage overlay : TCP 2377 pour la gestion du cluster, TCP/UDP 7946 pour la communication entre nœuds et UDP 4789 pour les données VXLAN.
Sur chaque nœud, vérifiez que l'interface VXLAN existe :
$ ip link show type vxlan
10: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br0 state UNKNOWN mode DEFAULT group default
link/ether 02:42:... brd ff:ff:ff:ff:ff:ff
Si l'interface VXLAN est manquante ou si le MTU est incorrect, cela peut causer des fragmentations et des problèmes de connectivité.
Correctif
- Assurez-vous que les règles de pare-feu autorisent les ports requis.
- Si des problèmes de MTU sont suspectés, ajustez le MTU sur le démon Docker ou le réseau. Par exemple, si le réseau sous-jacent a un MTU de 1400, définissez le MTU Docker à 1400 :
$ sudo dockerd --mtu 1400
Ou définissez-le par réseau :
$ docker network create -d overlay --opt com.docker.network.driver.mtu=1400 myoverlay
- Redémarrez le démon Docker sur les nœuds affectés.
Erreur courante 5 : échecs de résolution DNS pour les domaines personnalisés
Symptôme
Un conteneur ne peut pas résoudre un domaine interne personnalisé, par exemple api.internal.example.com.
Diagnostic
Vérifiez la configuration DNS du conteneur :
$ docker exec mycontainer cat /etc/resolv.conf
search mydomain.local
nameserver 127.0.0.11
options ndots:0
Si le domaine personnalisé est servi par un serveur DNS externe, le conteneur peut ne pas le consulter. Testez avec nslookup en utilisant le serveur spécifique :
$ docker exec mycontainer nslookup api.internal.example.com 10.0.0.53
Si cela fonctionne mais que la résolution par défaut ne fonctionne pas, le DNS Docker peut ne pas transférer vers le bon serveur.
Correctif
Démarrez le conteneur avec les options --dns et --dns-search :
$ docker run -d --name mycontainer --dns 10.0.0.53 --dns 8.8.8.8 --dns-search mydomain.local myimage
Alternativement, configurez le démon Docker pour utiliser un serveur DNS personnalisé globalement en éditant /etc/docker/daemon.json :
{
"dns": ["10.0.0.53", "8.8.8.8"],
"dns-search": ["mydomain.local"]
}
Puis redémarrez Docker :
$ sudo systemctl restart docker
Erreur courante 6 : problèmes de configuration IPv6
Symptôme
Les conteneurs ne reçoivent pas d'adresses IPv6 ou ne peuvent pas communiquer via IPv6.
Diagnostic
Vérifiez si IPv6 est activé sur le réseau :
$ docker network inspect bridge | grep EnableIPv6
"EnableIPv6": false,
Par défaut, IPv6 est désactivé. Si vous avez besoin d'IPv6, vous devez l'activer dans la configuration du démon et créer des réseaux avec des sous-réseaux IPv6.
Correctif
- Éditez
/etc/docker/daemon.jsonpour activer IPv6 et définir un CIDR fixe :
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64"
}
- Redémarrez Docker :
$ sudo systemctl restart docker
- Créez un réseau avec support IPv6 :
$ docker network create --ipv6 --subnet=2001:db8:1::/64 myipv6net
- Exécutez un conteneur sur ce réseau et vérifiez son adresse IPv6 :
$ docker run -d --name ipv6test --network myipv6net alpine sleep 300
$ docker exec ipv6test ip -6 addr show eth0
2: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
inet6 2001:db8:1::242:ac11:2/64 scope global nodad
valid_lft forever preferred_lft forever
Pièges courants et comment les éviter
- Utiliser le réseau bridge par défaut pour la production. Le bridge par défaut manque de découverte de service automatique et d'isolation. Créez toujours des réseaux définis par l'utilisateur pour les applications.
- Pourquoi cela arrive : commodité ;
docker runsans--networkutilise par défaut le bridge. - Comment éviter : définissez les réseaux dans les fichiers Compose ou créez explicitement des réseaux personnalisés.
- Coder en dur les IP des conteneurs. Les IP des conteneurs peuvent changer après recréation. Fiez-vous plutôt aux noms DNS.
- Pourquoi cela arrive : les développeurs peuvent inspecter et copier les IP.
- Comment éviter : utilisez les noms de service ; si nécessaire, attribuez des IP statiques via
--ipsur un réseau défini par l'utilisateur.
- Ignorer les incompatibilités de MTU. Les réseaux overlay sur VPN ou certains fournisseurs cloud peuvent nécessiter un MTU plus bas.
- Pourquoi cela arrive : le MTU par défaut de 1500 peut ne pas fonctionner si le réseau sous-jacent a un MTU plus bas.
- Comment éviter : testez avec
ping -M do -s 1472 <hôte>pour découvrir le MTU maximum et configurez en conséquence.
- Ne pas nettoyer les réseaux inutilisés. Les réseaux inutilisés peuvent encombrer l'environnement et causer de la confusion.
- Pourquoi cela arrive : oublier de supprimer les réseaux après des expériences.
- Comment éviter : exécutez périodiquement
docker network prune.
- Négliger les règles de pare-feu. Pour Swarm ou les configurations multi-hôtes, des ports de pare-feu manquants causent des échecs mystérieux.
- Pourquoi cela arrive : supposer que tout le trafic est autorisé.
- Comment éviter : documentez les ports requis et vérifiez avec
nc -zv <hôte> <port>.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle avant et après avoir apporté des modifications réseau :
- [ ] Enregistrer l'état actuel :
docker network ls,docker ps,docker info. - [ ] Identifier l'erreur : collecter les messages d'erreur exacts des journaux et des commandes.
- [ ] Isoler le problème : tester la connectivité avec
ping,curl,nslookupettraceroute. - [ ] Vérifier la configuration réseau :
docker network inspect <réseau>. - [ ] Vérifier les paramètres DNS :
cat /etc/resolv.confà l'intérieur du conteneur. - [ ] Vérifier les mappages de ports :
docker port <conteneur>. - [ ] Vérifier les règles de pare-feu : assurez-vous que les ports requis sont ouverts.
- [ ] Apporter un seul changement à la fois et tester après chaque changement.
- [ ] Documenter le changement et le plan de retour en arrière.
- [ ] Vérifier le correctif : répéter la commande d'origine qui échouait et confirmer le succès.
- [ ] Mettre à jour la surveillance et les alertes si nécessaire.
Conclusion
Les erreurs de réseau Docker peuvent être intimidantes, mais une approche systématique simplifie le dépannage. En établissant une base de référence, en utilisant les bonnes commandes de diagnostic, en comprenant les schémas de défaillance courants et en appliquant des correctifs minimaux avec vérification, vous pouvez résoudre rapidement la plupart des problèmes de réseau. Préférez toujours les réseaux bridge définis par l'utilisateur pour la communication conteneur à conteneur, évitez de coder en dur les IP et faites attention aux paramètres DNS et MTU. Utilisez la liste de contrôle opérationnelle pour prévenir les problèmes futurs et garantir un environnement de conteneurs fiable. Avec la pratique, vous naviguerez dans le réseautage Docker en toute confiance.