Skip to Content
CLIRéseau Docker

🌐 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 bridge

Piè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 nginx

Avantages : 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 inspect montre 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 nginx

none

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 3600

Ré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-reseau

DNS 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:80

Ré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-isole

docker-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_on gè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_healthy

Avec 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 nginx

expose (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 postgres

Dans 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ôte

Mapping 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/tcp

Ré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 :

  1. Collision de ports : deux containers host sur le même port entrent en conflit
  2. Pas de mapping : le port du container doit correspondre exactement au port de l’hôte
  3. Sécurité : le container voit toutes les interfaces de l’hôte, y compris loopback
  4. Dépendance à l’hôte : impossible de faire du load balancing entre hosts avec le même service
  5. Docker Desktop (Mac/Windows) : host est 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ôte

Cas 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: bridge

Points clés de cette stack :

  • api atteint db via DB_HOST=db (DNS compose)
  • gateway atteint api via http://api:8080
  • monitoring est isolé sur un réseau séparé
  • api expose 8081 sur l’hôte (accès direct pour debug)
  • gateway expose 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-name

Vé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/path

Pièges de débogage fréquents

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

  2. Container ne démarre pas : “Cannot connect to the daemon” : problème de permissions socket Docker, pas de réseau.

  3. Services accessibles en localhost mais pas depuis un autre container : le service écoute probablement sur 127.0.0.1 au lieu de 0.0.0.0.

  4. Timeout sur connexion externe : le container peut avoir des problèmes de résolution DNS externe. Vérifier /etc/resolv.conf.

  5. 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 --volumes

Références rapides

PiloteUsageIsolationRésolution DNS
bridgeContainers isolésMoyenneOUI (même réseau)
hostPerformance / proxiesAucuneNON (utilise l’hôte)
overlayMulti-hôte (Swarm)HauteOUI
noneIsolation totaleMaximaleNON

See also

  • Docker (cheatsheet) — commandes de base, volumes, images
  • Linux — gestion des processus et signaux
  • DevOps — monitoring et CI/CD associés à Docker