ERROR 2002 (HY000): Can't connect to MySQL server on 'db' (111) — sauf que cette fois, la connexion aboutissait bien, mais pas vers la base attendue. Le conteneur nommé db du projet A venait de répondre à une requête émise par le projet B, hébergé sur le même serveur.
Ce genre d’incident ne se produit pas par malveillance ni par erreur de configuration flagrante. Il vient d’une caractéristique tout à fait normale de Docker : par défaut, tous les conteneurs lancés sans réseau explicite rejoignent le réseau bridge par défaut de la machine hôte, et peuvent s’y résoudre mutuellement par leur nom si celui-ci correspond. Sur un serveur qui héberge plusieurs projets, ce comportement devient un risque réel plutôt qu’une curiosité théorique.
Le scénario qui a déclenché l’alerte
Deux projets WordPress conteneurisés, appartenant à deux clients distincts, tournaient sur le même serveur physique. Chaque projet définissait son service de base de données sous le nom générique db dans son fichier docker-compose.yml, une convention parfaitement raisonnable prise indépendamment par deux personnes différentes de l’équipe. Le premier projet utilisait Docker Compose sans réseau nommé explicitement ; Compose crée alors un réseau par défaut portant le nom du dossier du projet, ce qui aurait dû suffire à isoler les deux environnements.
Le problème est apparu après une modification du fichier docker-compose.yml du second projet, où un champ network_mode avait été ajouté pour résoudre un souci de latence, en pointant vers le réseau bridge par défaut de Docker plutôt que vers un réseau dédié. Le service db de ce second projet est alors devenu joignable, par son nom, depuis n’importe quel conteneur également connecté au réseau bridge — y compris certains conteneurs du premier projet dont la configuration réseau était restée, elle aussi, imprécise.
Pourquoi la résolution de noms a fonctionné
Docker fournit une résolution DNS automatique entre conteneurs partageant le même réseau défini par l’utilisateur. Sur le réseau bridge par défaut, cette résolution par nom n’existe historiquement pas de la même façon, mais certains ajustements réseau — équilibreur de charge partagé, conteneur relais, alias déclaré manuellement — peuvent recréer les conditions d’une confusion. Dans ce cas précis, un conteneur de supervision partagé entre les deux projets avait été connecté aux deux réseaux à la fois pour simplifier sa configuration, créant de fait un pont entre deux environnements qui devaient rester cloisonnés.

Le diagnostic, étape par étape
La commande docker network ls a d’abord permis de lister l’ensemble des réseaux présents sur le serveur, en révélant plus de réseaux nommés par défaut que de projets réellement isolés. La commande docker network inspect <nom_du_réseau> a ensuite montré, pour chaque réseau, la liste exacte des conteneurs connectés :
docker network inspect bridge --format '{{range .Containers}}{{.Name}} {{end}}'
Ce relevé a confirmé la présence du conteneur de supervision partagé sur le réseau bridge, aux côtés de conteneurs appartenant aux deux projets clients. La cause n’était donc pas une faille dans Docker, mais une configuration réseau construite projet par projet, sans vue d’ensemble sur le serveur qui les hébergeait tous.
La méthode d’isolement retenue
La correction a consisté à définir, pour chaque projet, un réseau Docker nommé explicitement dans son fichier docker-compose.yml :
networks:
reseau_projet_a:
driver: bridge
name: reseau_projet_a
Chaque service du projet référence ensuite ce réseau nommé plutôt que de dépendre d’un réseau implicite. Le conteneur de supervision partagé a été reconfiguré pour exposer ses métriques via un port publié sur l’hôte plutôt que par une connexion directe aux réseaux internes de chaque projet, supprimant le besoin d’appartenir à plusieurs réseaux à la fois.
- Un réseau nommé et dédié par projet, jamais de dépendance au réseau
bridgepar défaut - Aucun conteneur transverse connecté à plusieurs réseaux de projets clients simultanément
- Une vérification régulière avec
docker network lsetdocker network inspectsur les serveurs mutualisés
Généraliser le contrôle sur un serveur partagé
Sur un serveur qui héberge plusieurs projets clients, ce contrôle mérite d’être systématisé plutôt que redécouvert à chaque incident. Un script de vérification périodique, lancé par une tâche planifiée, peut lister les réseaux existants et signaler tout conteneur connecté à plus d’un réseau nommé de projet, en excluant les cas légitimes comme les passerelles réseau explicitement documentées.
Ce qu’il faut retenir
L’isolement réseau entre projets hébergés côte à côte ne relève pas d’un renforcement optionnel de sécurité : c’est une conséquence directe et prévisible du modèle réseau de Docker dès qu’un serveur mutualise plusieurs environnements. Nommer explicitement chaque réseau, et refuser tout conteneur qui appartiendrait à plusieurs réseaux de projets distincts sans justification documentée, élimine ce risque à la racine plutôt que de compter sur la chance pour qu’aucun nom de service ne se recoupe jamais.