# Deux projets clients, deux réseaux Docker isolés sur le même serveur

> Sans réseaux Docker distincts, un service mal nommé peut accidentellement joindre la base de données d'un autre client. Diagnostic d'un cas réel et méthode d'isolement définitive.

- Auteur : WordPress Développement
- Publié le : 2022-11-18
- Mis à jour le : 2022-11-18
- Catégorie : Outils &amp; workflow
- URL : https://www.wpmoderne.fr/outils/deux-reseaux-docker-isoles-projets-clients/

## L’essentiel

- Un réseau Docker par défaut peut exposer plusieurs projets entre eux
- Un nom de service ambigu suffit à créer une résolution DNS inattendue
- Un réseau dédié par projet supprime le risque à la racine

`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.

> L'essentiel à retenir : Un réseau Docker par défaut peut exposer plusieurs projets entre eux ; Un nom de service ambigu suffit à créer une résolution DNS inattendue ; Un réseau dédié par projet supprime le risque à la racine

## 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 `bridge` par défaut
- Aucun conteneur transverse connecté à plusieurs réseaux de projets clients simultanément
- Une vérification régulière avec `docker network ls` et `docker network inspect` sur 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.
