À la une · Fiche technique

Comment bien gérer les réseaux Docker ?

Bridge, host, overlay, réseaux personnalisés, DNS interne et isolation : découvrez comment fonctionnent les réseaux Docker et comment faire communiquer (ou cloisonner) vos conteneurs proprement.

Intermédiaire
Un standard téléphonique vintage avec une opératrice qui branche des câbles, pixel art

On continue notre série Docker. Après avoir clarifié la différence entre Docker, Compose et Swarm, on s’attaque à un sujet qu’on a tendance à survoler, à savoir les réseaux Docker.

Dans le chapitre réseau du cours, on a vu comment exposer un port avec ports et expose. Mais derrière ce mécanisme se cache toute une mécanique. À chaque fois que vous lancez un conteneur, Docker le branche sur un réseau. Selon le réseau choisi, vos conteneurs vont pouvoir se parler ou pas.

Dans cette fiche, on va voir quels sont les différents types de réseaux, comment les créer et surtout comment faire communiquer proprement vos conteneurs entre eux.


Pourquoi Docker a besoin de réseaux ?

Un conteneur, c’est un environnement isolé. Par défaut, il ne sait rien du monde extérieur ni des autres conteneurs. Le réseau, c’est précisément ce qui va lui permettre de communiquer avec votre machine, avec Internet et avec ses voisins.


Il faut savoir que Docker gère tout ça automatiquement grâce à des drivers réseau. Un driver, c’est simplement le « type » de réseau utilisé. Vous pouvez lister les réseaux existants sur votre machine avec :

docker network ls

Vous verrez au moins trois réseaux créés par défaut :

NETWORK ID     NAME      DRIVER    SCOPE
xxxxxxxxxxxx   bridge    bridge    local
xxxxxxxxxxxx   host      host      local
xxxxxxxxxxxx   none      none      local

Ces trois-là correspondent aux trois drivers que vous croiserez le plus souvent. On va les passer en revue.


Les principaux drivers réseau

bridge - le réseau par défaut

C’est le driver utilisé automatiquement quand vous lancez un conteneur sans rien préciser. Docker crée un réseau privé interne sur votre machine et chaque conteneur y reçoit sa propre adresse IP. Pour communiquer avec l’extérieur, on passe par la redirection de ports (le fameux -p 8080:80).

C’est le mode adapté à la grande majorité des cas. Plusieurs conteneurs sur une même machine qui doivent dialoguer entre eux.

host - on partage le réseau de la machine

Avec le driver host, le conteneur n’est plus isolé. Il utilise directement la pile réseau de votre machine hôte. Plus besoin de rediriger les ports, le conteneur écoute directement sur ceux de l’hôte.

docker container run --network host nginx

C’est plus performant parce qu’il n’y a pas de couche de traduction réseau. Cela dit, vous perdez l’isolation et vous risquez les conflits de ports. À réserver à des cas précis.

none - pas de réseau du tout

Comme son nom l’indique, le conteneur n’a aucune connectivité réseau. Utile pour des tâches totalement isolées, pour des raisons de sécurité ou pour des batchs qui n’ont besoin de rien.

overlay - pour communiquer entre plusieurs machines

Le driver overlay permet à des conteneurs situés sur des machines différentes de communiquer comme s’ils étaient sur le même réseau local. C’est le driver utilisé par Docker Swarm pour faire dialoguer les services d’un cluster. Si le sujet vous intrigue, on en reparlera dans la fiche dédiée à Swarm.


Il existe aussi le driver macvlan, plus avancé, qui donne à un conteneur une vraie adresse MAC sur votre réseau physique. C’est un cas d’usage de niche, on ne s’y attarde pas ici. J’y reviendrais peut-être dans une prochaine fiche technique.

Tableau récapitulatif

Pour y voir clair en un coup d’œil :

DriverPortéeQuand l’utiliser
bridgeUne machineCas par défaut : plusieurs conteneurs qui dialoguent sur un même hôte
hostUne machinePerformance maximale, quand l’isolation réseau n’est pas nécessaire
noneUne machineConteneur totalement isolé, sans aucun accès réseau
overlayPlusieurs machinesCommunication entre services d’un cluster Swarm
macvlanRéseau physiqueDonner une vraie IP du réseau local à un conteneur (cas avancé)

Dans 90 % des cas en local comme sur un petit serveur, vous resterez sur du bridge. C’est pourquoi on va s’y attarder un peu plus.


Le réseau bridge par défaut n’est pas le meilleur

Voici LE point que beaucoup ignorent et qui fait toute la différence.

Le réseau bridge par défaut fonctionne mais il a une grosse limite. Les conteneurs ne peuvent s’y joindre que par adresse IP et pas par nom. Et comme les IP changent à chaque redémarrage, c’est ingérable.


La bonne pratique, c’est de créer votre propre réseau bridge (on parle de user-defined bridge). Sur un réseau personnalisé, Docker active un DNS interne. Ce qui fait que chaque conteneur est joignable par son nom.

# On crée notre réseau
docker network create mon-reseau

# On lance deux conteneurs dessus
docker container run -d --name api --network mon-reseau mon-api
docker container run -d --name db --network mon-reseau postgres

Le résultat ici est que depuis le conteneur api, je peux contacter la base de données simplement en utilisant db comme nom d’hôte. Pas d’IP à connaître, pas de config à maintenir. C’est propre, lisible et stable.


En plus du DNS, un réseau personnalisé apporte une meilleure isolation. Seuls les conteneurs que vous branchez explicitement dessus peuvent communiquer entre eux. Sur le réseau bridge par défaut, à l’inverse, tous les conteneurs se retrouvent mélangés sur le même réseau, ce qui est rarement ce que vous voulez. Bref, prenez l’habitude de toujours créer un réseau dédié à votre projet.


Les commandes réseau à connaître

Quelques commandes utiles pour piloter tout ça au quotidien :

# Lister les réseaux
docker network ls

# Créer un réseau
docker network create mon-reseau

# Inspecter un réseau (voir qui est connecté, l'IP, le driver…)
docker network inspect mon-reseau

# Connecter / déconnecter un conteneur à chaud
docker network connect mon-reseau mon-conteneur
docker network disconnect mon-reseau mon-conteneur

# Supprimer les réseaux inutilisés
docker network prune

La commande docker network inspect est particulièrement précieuse pour debugger. Elle vous montre exactement quels conteneurs sont branchés et avec quelles adresses.


Les réseaux en Docker Compose

Avec Docker Compose, tout ce travail est fait pour vous. Quand vous lancez un docker compose up, Compose crée automatiquement un réseau dédié à votre projet et y branche tous vos services.

C’est pour ça que, dans un docker-compose.yml, un service peut en joindre un autre par son nom directement :

services:
  api:
    image: mon-api
    # L'api peut joindre la base via le nom "db", tout simplement
  db:
    image: postgres

Ici, pas besoin de déclarer quoi que ce soit. Le DNS interne fonctionne tout seul parce que Compose utilise un réseau bridge personnalisé sous le capot.


Astuce bonus - Cloisonnez vos services avec plusieurs réseaux

Vous pouvez aller plus loin et créer plusieurs réseaux pour isoler vos services. C’est une excellente pratique de sécurité : votre base de données n’a aucune raison d’être joignable depuis l’extérieur.

services:
  frontend:
    image: mon-front
    networks:
      - public

  api:
    image: mon-api
    networks:
      - public
      - prive

  db:
    image: postgres
    networks:
      - prive

networks:
  public:
  prive:
    internal: true

Décryptage :

  • le frontend et l’api partagent le réseau public ;
  • l’api et la db partagent le réseau prive ;
  • le frontend ne peut pas joindre directement la db : ils ne sont sur aucun réseau commun ;
  • la directive internal: true coupe tout accès à Internet pour le réseau prive, ce qui isole encore davantage votre base.

Avec ce découpage, même si votre frontend était compromis, l’attaquant n’aurait pas un accès direct à la base. C’est le principe du moindre privilège, appliqué au réseau.


Et voilà ! Les réseaux Docker n’ont (presque) plus de secret pour vous. Retenez surtout deux choses ! Créez toujours un réseau personnalisé pour profiter du DNS interne et cloisonnez vos services dès que la sécurité l’exige.

Dans la prochaine fiche, on enchaînera justement sur un sujet voisin et sensible : la gestion des secrets en Docker. À très vite 😉.

D’ici là, je vous invite :

Ressources

Partager

Codez bien, Thomas