🌐 Réseau Docker
Guide technique sur les modèles réseau de Docker, la communication inter-conteneurs, l’exposition des ports et le dépannage réseau.
Ce guide complète la section Networks du cheatsheet Docker. Il couvre les sujets suivants :
- Modèles réseau (bridge, host, overlay, none)
- Réseaux custom et DNS interne
- Communication inter-conteneurs via docker-compose
- Exposition de ports (
ports,expose, mapping aléatoire) - Réseau host : cas d’usage et pièges
- Cas concret : stack microservices
- Dépannage réseau
Modèles réseau
Docker propose quatre pilotes réseau intégrés :
bridge (par défaut)
Le réseau bridge est le pilote par défaut pour les containers isolés. Chaque container reçoit une adresse IP interne dans un sous-réseau DHCP automatique. Les containers sur le même bridge se communiquent via le DNS Docker.
# Vérifier le bridge par défaut
docker network ls
# Réseau bridge créé automatiquement à l'installation
docker network inspect bridgePiège : les containers sur des bridges différents ne se communiquent pas
sauf si l’un des deux est explicitement connecté à l’autre via
docker network connect.
host
Le container partage le réseau de l’hôte. Pas de NAT, pas de passerelle Docker, pas d’isolation réseau.
# Lancer un container en mode host
docker run -d --network host nginxAvantages : performances maximales, pas de mapping de ports. Pièges :
- Collision de ports possible avec d’autres services de l’hôte
- Aucune isolation : le container voit tous les interfaces de l’hôte
docker inspectmontre l’IP de l’hôte, pas une IP de container
overlay (Swarm / Docker Desktop)
Permet la communication entre containers sur plusieurs hôtes. Nécessite Docker Swarm ou Docker Desktop avec routable overlay.
# Créer un overlay en mode Swarm
docker network create -d overlay --attachable mon-overlay
# Utiliser avec un service Swarm
docker service create --network mon-overlay --name api nginxnone
Aucune interface réseau. Utile pour des travaux isolés (builds, tests) ou quand le réseau est ajouté manuellement.
docker run -d --network none alpine sleep 3600Réseaux custom
Créer un réseau custom permet de définir le sous-réseau, le gateway, et d’activer ou non le DNS interne.
# Créer un réseau avec sous-réseau et gateway personnalisés
docker network create \
--driver bridge \
--subnet 172.28.0.0/16 \
--gateway 172.28.0.1 \
--opt com.docker.network.bridge.name=br-custom \
mon-reseau
# Vérifier la configuration
docker network inspect mon-reseauDNS interne et alias
Par défaut, Docker résout automatiquement les noms de containers par leur ID court (premières lettres du container ID). Avec les réseaux custom, les containers peuvent être désignés par leur nom de container.
# Container avec alias personnalisés
docker run -d --network mon-reseau \
--name api \
--network-alias api-service \
--network-alias backend \
nginx
# Un autre container peut atteindre l'API via n'importe lequel de ces noms
docker run -it --network mon-reseau alpine wget -qO- http://api:80
docker run -it --network mon-reseau alpine wget -qO- http://api-service:80
docker run -it --network mon-reseau alpine wget -qO- http://backend:80Réseau isolé (no internal networking)
Pour les réseaux où les containers ne doivent pas communiquer entre
eux (ex : services publics qui ne parlent qu’au host), utiliser l’option
--internal :
# Réseau isolé : les containers ne peuvent sortir que vers l'hôte
docker network create --internal mon-isoledocker-compose et communication inter-conteneurs
C’est le scénario le plus courant en développement. Docker Compose crée automatiquement un réseau bridge et un DNS de service pour chaque service déclaré.
Principe de base
Le nom du service dans le docker-compose.yml est résoluble depuis
tous les autres services du même fichier.
services:
api:
image: myapp:latest
ports:
- "8080:8080"
environment:
- DB_HOST=db
- DB_PORT=5432
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Ici, api atteint db via DB_HOST=db. Pas besoin de connaître l’IP.
Le DNS de compose utilise le nom du service comme nom d’hôte.
Règles de résolution
- Le nom du service est résoluble depuis tous les autres services du même fichier compose, quel que soit l’ordre de démarrage
- Le nom de service = nom d’hôte = DNS dans le réseau créé par compose
depends_ongère l’ordre de démarrage mais ne garantit pas la disponibilité de la dépendance (le service peut démarrer avant que le port ne soit prêt)
Indicateurs de santé (healthcheck) pour les dépendances
Pour éviter que le service A ne démarre avant que B ne soit prêt :
services:
db:
image: postgres:15-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
api:
image: myapp:latest
depends_on:
db:
condition: service_healthyAvec condition: service_healthy, compose attend que le healthcheck
de db soit vert avant de démarrer api.
Variables d’environnement de connexion dans les microservices
Bonnes pratiques pour les stacks Spring Boot / Micronaut :
services:
api:
image: myapi:latest
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydb
- SPRING_DATASOURCE_USERNAME=app
- SPRING_DATASOURCE_PASSWORD=secret
- SPRING_CLOUD_GATEWAY_URI=http://gateway:8080
depends_on:
db:
condition: service_healthy
gateway:
image: spring-cloud-gateway:latest
ports:
- "8080:8080"
environment:
- SERVER_PORT=8080
db:
image: postgres:15-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
timeout: 5s
retries: 10
environment:
- POSTGRES_USER=app
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Exposition des ports
Trois mécanismes pour exposer les ports :
ports (hôte → container)
Expose un port du container sur l’hôte. C’est le mécanisme standard pour les services accessibles depuis l’extérieur.
# Mapping spécifique
docker run -d -p 8080:80 nginx
# Mapping avec IP de liaison
docker run -d -p 127.0.0.1:8080:80 nginx
# Mapping avec protocole TCP/UDP
docker run -d -p 8080:80/tcp nginx
# Binding sur toutes les interfaces
docker run -d -p 0.0.0.0:8080:80 nginxexpose (container → container, réseau custom)
expose déclare un port comme accessible depuis d’autres containers
sur le même réseau, sans l’ouvrir sur l’hôte.
# Déclarer un port sans l'exposer à l'hôte
docker run -d --expose 8080 --name api nginx
docker run -d --expose 5432 --name db postgresDans docker-compose, expose sert uniquement à documenter les ports
utilisés par les services du réseau interne :
services:
api:
image: myapp:latest
expose:
- "8080"
ports:
- "8080:8080"
db:
image: postgres:15-alpine
expose:
- "5432"
# Pas de ports : 5432 n'est pas accessible depuis l'hôteMapping aléatoire
Utile pour les tests parallèles ou les environnements éphémères :
# Docker attribue un port aléatoire de l'hôte vers le container
docker run -d -p 80 nginx
# Résultat : hôte:xxxxx -> container:80
docker ps
# Exemple : 0.0.0.0:32768->80/tcpRéseau host : quand l’utiliser
Le réseau host est valide dans ces cas :
- Performance critique (proxies, load balancers)
- Pas besoin d’isolation réseau
- Besoin d’accéder directement aux interfaces réseau de l’hôte (sniffing, monitoring)
- Éviter les problèmes de NAT pour des services UDP ou avec des ports élevés
Pièges courants :
- Collision de ports : deux containers host sur le même port entrent en conflit
- Pas de mapping : le port du container doit correspondre exactement au port de l’hôte
- Sécurité : le container voit toutes les interfaces de l’hôte, y compris loopback
- Dépendance à l’hôte : impossible de faire du load balancing entre hosts avec le même service
- Docker Desktop (Mac/Windows) :
hostest limité, les ports restent mappés via VM
# Exemple : cache Redis en host network pour performance
docker run -d --network host redis:7-alpine
# Redis accessible sur localhost:6379
# Pas de mapping : le port 6379 doit être libre sur l'hôteCas concret : stack microservices
Voici une stack complète API + Spring Cloud Gateway + PostgreSQL.
Docker Compose
services:
gateway:
image: spring-cloud-gateway:latest
ports:
- "8080:8080"
environment:
- SERVER_PORT=8080
networks:
- backend
depends_on:
api:
condition: service_healthy
api:
build: ./api
ports:
- "8081:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydb
- SPRING_DATASOURCE_USERNAME=app
- SPRING_DATASOURCE_PASSWORD=secret
- GATEWAY_URL=http://gateway:8080
- SPRING_CLOUD_GATEWAY_DISCOVERY_CLIENT_ENABLED=true
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/actuator/health || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- backend
depends_on:
db:
condition: service_healthy
db:
image: postgres:15-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
timeout: 5s
retries: 10
environment:
- POSTGRES_USER=app
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- backend
# Network isolé pour les outils de monitoring
monitoring:
image: prom/prometheus:latest
ports:
- "9090:9090"
networks:
- monitoring
# monitoring ne peut pas atteindre api ou db (pas de réseau partagé)
volumes:
pgdata:
networks:
backend:
driver: bridge
monitoring:
driver: bridgePoints clés de cette stack :
apiatteintdbviaDB_HOST=db(DNS compose)gatewayatteintapiviahttp://api:8080monitoringest isolé sur un réseau séparéapiexpose 8081 sur l’hôte (accès direct pour debug)gatewayexpose 8080 sur l’hôte (point d’entrée unique)- Les healthchecks garantissent l’ordre de démarrage
Dépannage réseau
Outils de diagnostic
# Lister tous les réseaux et leurs containers
docker network ls
# Inspecter un réseau en détail (IP, Gateway, Containers connectés)
docker network inspect nom-reseau
# Inspecter un réseau et filtrer les adresses IP
docker network inspect --format='{{range .Containers}}{{.Name}}: {{.IPv4Address}}{{"\n"}}{{end}}' nom-reseau
# Vérifier la connectivité entre deux containers
docker exec -it container-a ping container-b
# Depuis un container, faire un nslookup du DNS Docker
docker exec -it container-a nslookup service-name
docker exec -it container-a getent hosts service-nameVérifier la résolution DNS
# Créer un conteneur alpine avec DNS pour tests
docker run -it --network mon-reseau alpine ash
# À l'intérieur du container :
nslookup service-name
# ou
cat /etc/resolv.conf
# DNS Docker : 127.0.0.11
# Tester la connectivité HTTP
wget -qO- http://service-name:port/pathPièges de débogage fréquents
-
DNS non résolu : vérifier que les containers sont sur le même réseau. Les containers connectés à
bridge(par défaut) ne peuvent pas se résoudre entre eux sans connexion manuelle. -
Container ne démarre pas : “Cannot connect to the daemon” : problème de permissions socket Docker, pas de réseau.
-
Services accessibles en localhost mais pas depuis un autre container : le service écoute probablement sur
127.0.0.1au lieu de0.0.0.0. -
Timeout sur connexion externe : le container peut avoir des problèmes de résolution DNS externe. Vérifier
/etc/resolv.conf. -
Port mapping ne fonctionne pas : vérifier que le service écoute sur le bon port dans le container (
docker exec container netstat -tlnp).
Nettoyage réseau
# Supprimer les réseaux orphelins (non attachés à un container)
docker network prune
# Supprimer TOUT : réseaux, volumes, images non utilisées
docker system prune -a --volumesRéférences rapides
| Pilote | Usage | Isolation | Résolution DNS |
|---|---|---|---|
bridge | Containers isolés | Moyenne | OUI (même réseau) |
host | Performance / proxies | Aucune | NON (utilise l’hôte) |
overlay | Multi-hôte (Swarm) | Haute | OUI |
none | Isolation totale | Maximale | NON |
See also
- Docker (cheatsheet) — commandes de base, volumes, images
- Linux — gestion des processus et signaux
- DevOps — monitoring et CI/CD associés à Docker