← Retour aux tutoriels

Réseau Docker avancé : Bridge, Host, Macvlan et Overlay expliqués en profondeur

dockerdocker networkingbridgehost networkmacvlanoverlayswarmcontainerslinux networkingdevops

Réseau Docker avancé : Bridge, Host, Macvlan et Overlay expliqués en profondeur

Ce tutoriel propose une exploration approfondie des principaux modes réseau Docker (Bridge, Host, Macvlan, Overlay), avec des commandes réelles, des scénarios concrets, des méthodes de diagnostic, et des bonnes pratiques de conception. L’objectif est de comprendre comment Docker connecte les conteneurs, comment le trafic circule, et quels compromis (performance, isolation, simplicité, compatibilité) chaque mode implique.


Table des matières

  1. Pré-requis et environnement
  2. Rappels : namespaces, veth, iptables/nftables
  3. Outils de diagnostic indispensables
  4. Réseau Bridge (par défaut) — en profondeur
  5. Réseau Host — performances et pièges
  6. Réseau Macvlan — IP “physiques” sur le LAN
  7. Réseau Overlay — multi-hôtes et Swarm
  8. Choisir le bon mode : matrice de décision
  9. Dépannage : symptômes → causes → commandes
  10. Bonnes pratiques et sécurité

Pré-requis et environnement

Vérifier la version Docker :

docker version
docker info

Rappels : namespaces, veth, iptables/nftables

Docker s’appuie sur des primitives Linux :

Pour visualiser rapidement :

ip link show
ip addr show
ip route show

Outils de diagnostic indispensables

1) Inspecter un réseau Docker

docker network ls
docker network inspect bridge

2) Inspecter un conteneur (réseau, IP, endpoints)

docker inspect <container> --format '{{json .NetworkSettings.Networks}}' | jq

3) Entrer dans un conteneur et vérifier sa pile réseau

docker exec -it <container> sh
ip addr
ip route
cat /etc/resolv.conf

4) Sniffer le trafic

Sur l’hôte :

tcpdump -ni any port 80
tcpdump -ni docker0

Dans un conteneur (si tcpdump est présent) :

tcpdump -ni eth0

5) Voir les règles de NAT/filtrage

Selon votre système :

iptables -S
iptables -t nat -S
iptables -L -n -v
iptables -t nat -L -n -v

Ou en nftables :

nft list ruleset

Réseau Bridge (par défaut) — en profondeur

Le mode bridge est le plus courant : chaque conteneur a une IP privée sur un sous-réseau géré par Docker, et l’hôte fait la passerelle.

Comprendre docker0 et le NAT

Par défaut, Docker crée un bridge Linux docker0 (sauf configuration différente). Vérifiez :

ip addr show docker0
ip link show docker0

Vous verrez typiquement une IP comme 172.17.0.1/16.

Quand un conteneur démarre sur le réseau bridge par défaut :

Exemple : lancer un conteneur et inspecter son IP :

docker run -d --name web nginx:alpine
docker inspect web --format '{{.NetworkSettings.IPAddress}}'

Tester la connectivité :

docker exec -it web sh -c "ip addr; ip route; wget -qO- http://example.com | head"

NAT sortant (MASQUERADE)

Le conteneur sort vers Internet via l’IP de l’hôte. Les règles iptables typiques :

iptables -t nat -L -n -v | sed -n '1,200p'

Cherchez des règles MASQUERADE associées aux sous-réseaux Docker.

Conséquence : depuis l’extérieur, un conteneur n’est pas joignable sans publication de port (DNAT), car son IP est privée.


Bridge utilisateur et DNS embarqué

Le bridge par défaut a des limitations (notamment sur la résolution DNS par nom de conteneur selon versions/paramètres). En pratique, on préfère créer un bridge utilisateur : il apporte un DNS interne plus fiable et une meilleure isolation.

Créer un réseau bridge utilisateur :

docker network create --driver bridge app-net
docker network inspect app-net

Lancer deux conteneurs sur ce réseau et tester la résolution par nom :

docker run -d --name api --network app-net hashicorp/http-echo:1.0 -text="hello"
docker run -d --name client --network app-net alpine:3.20 sleep 1d

docker exec -it client sh -c "apk add --no-cache curl >/dev/null; curl -s http://api:5678"

Ici, api est résolu via le DNS Docker (souvent 127.0.0.11 dans /etc/resolv.conf du conteneur).

Vérifier :

docker exec -it client cat /etc/resolv.conf

Publication de ports : -p vs —network host

En bridge, vous exposez un service via -p :

docker run -d --name web2 --network bridge -p 8080:80 nginx:alpine
curl -I http://127.0.0.1:8080

Ce que fait Docker :

Voir les règles :

iptables -t nat -L DOCKER -n -v

Remarque importante : -p 8080:80 publie sur toutes les interfaces. Pour restreindre à localhost :

docker run -d --name web3 -p 127.0.0.1:8081:80 nginx:alpine
curl -I http://127.0.0.1:8081

Isolation inter-conteneurs et ICC

Docker peut contrôler si les conteneurs d’un même bridge peuvent communiquer. Historiquement, le paramètre ICC (Inter-Container Communication) pouvait être ajusté, mais aujourd’hui l’approche recommandée est :

Exemple : un reverse proxy sur deux réseaux (front et back) :

docker network create frontend-net
docker network create backend-net

docker run -d --name app --network backend-net hashicorp/http-echo:1.0 -text="app"
docker run -d --name rp --network frontend-net -p 8082:80 nginx:alpine

docker network connect backend-net rp
docker inspect rp --format '{{json .NetworkSettings.Networks}}' | jq

Le conteneur rp a maintenant deux interfaces (une par réseau Docker).


Exemples complets

Exemple A : micro-stack simple (client → api)

docker network create demo-net

docker run -d --name api --network demo-net hashicorp/http-echo:1.0 -listen=:8080 -text="API OK"
docker run -d --name client --network demo-net alpine:3.20 sleep 1d

docker exec -it client sh -c "apk add --no-cache curl >/dev/null; curl -s http://api:8080"

Exemple B : observer le veth côté hôte

Lister les interfaces avant/après :

ip link show | grep -E 'docker0|veth' || true
docker run -d --name t1 --network bridge alpine:3.20 sleep 1d
ip link show | grep -E 'docker0|veth' || true

Réseau Host — performances et pièges

En mode host, le conteneur partage la pile réseau de l’hôte (pas de namespace réseau isolé). Concrètement :

Lancer un service en host :

docker run -d --name web-host --network host nginx:alpine
ss -lntp | grep ':80' || true
curl -I http://127.0.0.1:80

Quand l’utiliser ?

Pièges

  1. Conflits de ports : si l’hôte utilise déjà :80, le conteneur échoue.
  2. Sécurité : exposition involontaire sur toutes les interfaces.
  3. Observabilité : distinguer processus hôte vs conteneur peut être moins évident (même si cgroups aident).

Réseau Macvlan — IP “physiques” sur le LAN

Le driver macvlan permet à un conteneur d’apparaître sur le réseau L2 comme une machine distincte, avec :

C’est utile pour :

Bridge vs 802.1Q trunk

Deux grands modes :

Exemple macvlan “bridge” (LAN 192.168.1.0/24)

Supposons :

Créer le réseau :

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  macvlan-net

Démarrer un conteneur avec IP fixe :

docker run -d --name mv1 --network macvlan-net --ip 192.168.1.210 nginx:alpine
docker exec -it mv1 ip addr

Tester depuis une autre machine du LAN :

curl -I http://192.168.1.210

Problème classique : le host ne voit pas le macvlan

Par design, l’interface macvlan isole souvent le trafic entre l’hôte et ses conteneurs macvlan : l’hôte ne peut pas joindre directement 192.168.1.210 (même si le LAN le peut).

Symptôme : depuis l’hôte, ping 192.168.1.210 échoue, mais depuis un autre PC du LAN ça marche.

Solution courante : créer une interface macvlan “shim” côté hôte sur le même parent, avec une IP dédiée dans le sous-réseau, puis router via elle.

Exemple :

ip link add macvlan-shim link eth0 type macvlan mode bridge
ip addr add 192.168.1.199/24 dev macvlan-shim
ip link set macvlan-shim up

ip route add 192.168.1.200/29 dev macvlan-shim || true

Ensuite, l’hôte peut joindre les IP macvlan (selon votre plan d’adressage). Adaptez la route à la plage réellement utilisée.


Exemples complets

Exemple C : service DNS/HTTP sur IP LAN

docker run -d --name mv-http --network macvlan-net --ip 192.168.1.211 nginx:alpine
curl -I http://192.168.1.211

Exemple D : macvlan en VLAN taggé (802.1Q)

Créer une sous-interface VLAN (ex: VLAN 20) :

ip link add link eth0 name eth0.20 type vlan id 20
ip link set eth0.20 up
ip addr show eth0.20

Créer le réseau macvlan sur eth0.20 :

docker network create -d macvlan \
  --subnet=10.20.0.0/24 \
  --gateway=10.20.0.1 \
  -o parent=eth0.20 \
  macvlan-v20

Lancer un conteneur :

docker run -d --name mv-v20 --network macvlan-v20 --ip 10.20.0.50 nginx:alpine

Réseau Overlay — multi-hôtes et Swarm

Le driver overlay est conçu pour relier des conteneurs sur plusieurs hôtes comme s’ils étaient sur le même réseau virtuel. Il est historiquement associé à Docker Swarm.

VXLAN, chiffrement, gossip/contrôle

En overlay, Docker encapsule souvent le trafic dans VXLAN (UDP, typiquement port 4789). Il existe aussi un plan de contrôle (ports 2377/tcp pour Swarm, 7946/tcp+udp pour la découverte/état).

Ports à connaître (Swarm) :

Créer un cluster Swarm (sur le manager) :

docker swarm init --advertise-addr <IP_MANAGER>

Sur un worker, joindre :

docker swarm join --token <TOKEN> <IP_MANAGER>:2377

Vérifier :

docker node ls

Créer un réseau overlay :

docker network create -d overlay --attachable ovl-net
docker network ls
docker network inspect ovl-net

Services Swarm, VIP vs DNSRR

En Swarm, un service peut être exposé via :

Créer un service sur overlay :

docker service create --name whoami --network ovl-net --replicas 3 traefik/whoami
docker service ls
docker service ps whoami

Résolution DNS depuis un conteneur attaché :

docker run -it --rm --network ovl-net alpine:3.20 sh -c \
  "apk add --no-cache bind-tools curl >/dev/null; \
   dig +short whoami; \
   for i in 1 2 3 4; do curl -s whoami | head -n 1; done"

Selon le mode par défaut, dig peut renvoyer un VIP (une seule IP) ou plusieurs IP si DNSRR est configuré.

Configurer DNSRR :

docker service update --endpoint-mode dnsrr whoami

Exemples complets multi-nœuds

Exemple E : réseau overlay + service + test inter-nœuds

  1. Sur le manager :
docker network create -d overlay --attachable prod-net
docker service create --name echo --network prod-net --replicas 2 hashicorp/http-echo:1.0 -listen=:5678 -text="OVERLAY OK"
  1. Sur n’importe quel nœud (manager ou worker), lancer un conteneur client attaché :
docker run -it --rm --network prod-net alpine:3.20 sh -c \
  "apk add --no-cache curl >/dev/null; curl -s http://echo:5678"
  1. Diagnostiquer la distribution :
docker service ps echo
docker service logs echo

Exemple F : overlay chiffré

Docker permet de chiffrer le trafic overlay (surcoût CPU possible) :

docker network create -d overlay --opt encrypted --attachable secure-net
docker service create --name sec-echo --network secure-net --replicas 2 hashicorp/http-echo:1.0 -listen=:5678 -text="SECURE"

Choisir le bon mode : matrice de décision

BesoinMode recommandéPourquoi
Simplicité, dev local, microservices sur un seul hôteBridge (user-defined)DNS interne, isolation, facile à segmenter
Performance maximale, accès direct à la pile réseau hôteHostPas de NAT/bridge, latence minimale
Conteneur joignable directement sur le LAN avec IP dédiéeMacvlanIP/MAC “physiques”, intégration réseau
Multi-hôtes, orchestration, services distribuésOverlay (Swarm)Réseau virtuel inter-nœuds, découverte, LB

Dépannage : symptômes → causes → commandes

1) “Le conteneur a Internet, mais on ne peut pas y accéder depuis l’extérieur”

2) “Les conteneurs ne se résolvent pas par nom”

3) “En macvlan, le LAN voit le conteneur mais pas l’hôte”

4) “Overlay ne marche pas entre nœuds”


Bonnes pratiques et sécurité

1) Préférer les bridges user-defined

Ils offrent :

docker network create --driver bridge frontend
docker network create --driver bridge backend

2) Segmenter par “zones”

3) Restreindre l’exposition des ports

Publier sur 127.0.0.1 si l’accès externe n’est pas requis :

docker run -p 127.0.0.1:5432:5432 postgres:16

4) Utiliser DOCKER-USER pour les politiques firewall

Docker insère ses règles, mais la chaîne DOCKER-USER est prévue pour vos règles avant traitement Docker.

Exemple (bloquer l’accès à un port publié depuis l’extérieur, autoriser uniquement un subnet) :

iptables -I DOCKER-USER -i eth0 -p tcp --dport 8080 -s 203.0.113.0/24 -j ACCEPT
iptables -I DOCKER-USER -i eth0 -p tcp --dport 8080 -j DROP

5) Attention au Macvlan en environnement entreprise

6) Overlay : surveiller MTU et performance

VXLAN ajoute de l’en-tête (overhead). Si vous observez des timeouts ou des paquets fragmentés :

Exemple :

ping -M do -s 1472 <ip>   # 1472 + 28 = 1500 (ICMP+IP)

Conclusion

Si vous me donnez votre contexte (un seul serveur vs cluster, besoin d’IP LAN, contraintes firewall, VLAN, performance), je peux proposer une architecture réseau Docker complète avec un plan d’adressage, des règles de filtrage et une procédure de validation.