Skip to content
VDS · Docker et conteneurs

Réseaux Docker et redirection de ports

Comment les conteneurs se voient entre eux, en quoi la publication d'un port diffère d'un simple EXPOSE et pourquoi Docker contourne les règles d'ufw.

Mis à jour le 23 août 2026

La moitié des problèmes de conteneurs sont liés au réseau : un service n'atteint pas la base de données, un port est occupé, le panneau se retrouve soudain exposé à tout Internet. Voyons comment cela fonctionne.

Trois types de réseaux

  • bridge — le type par défaut. Les conteneurs reçoivent des adresses internes et communiquent entre eux ; ils sortent via le NAT de l'hôte.
  • host — le conteneur utilise directement le réseau de l'hôte ; la publication de ports n'est ni nécessaire ni fonctionnelle. Rapide, mais sans isolation : le port 80 du conteneur est le port 80 de l'hôte.
  • none — aucun réseau. Pour les tâches qui n'en ont pas besoin.

Un réseau personnalisé créé par vous ou par Compose diffère du bridge par défaut sur un point important : la résolution de noms y fonctionne. Le conteneur app peut joindre le conteneur db par le nom db.

docker network create backend
docker network ls
docker network inspect backend

Dans Compose, un tel réseau est créé automatiquement pour chaque projet.

Publication de ports

ports:
  - "127.0.0.1:8080:8080"   # accessible only from the machine itself
  - "80:80"                 # accessible to the whole internet

À gauche se trouve le port sur l'hôte, à droite le port à l'intérieur du conteneur. La directive EXPOSE dans une image ne publie rien : ce n'est qu'une indication du port sur lequel l'application écoute.

La règle est simple : ne publiez que ce qui doit être accessible depuis l'extérieur. La base de données, le panneau et l'API interne se placent sur 127.0.0.1, et un serveur web muni d'un certificat les expose vers l'extérieur.

Docker écrit lui-même les règles iptables et le fait avant les chaînes gérées par ufw. Un port publié avec -p 8080:8080 sera accessible depuis Internet même si ufw affiche « deny ». Ne comptez pas sur le pare-feu — liez le port à 127.0.0.1.

Communication entre conteneurs

services:
  app:
    networks: [frontend, backend]
  db:
    networks: [backend]
  proxy:
    networks: [frontend]
    ports:
      - "80:80"
      - "443:443"

networks:
  frontend:
  backend:

Ici, la base de données n'est accessible qu'à l'application, et seul le serveur web fait face à l'extérieur. C'est la configuration correcte pour n'importe quelle stack.

À l'intérieur d'un conteneur, référencez un voisin par son nom de service : postgres://db:5432/app. L'adresse localhost dans un conteneur désigne le conteneur lui-même, pas l'hôte — la deuxième erreur la plus fréquente après latest.

Pour joindre depuis un conteneur un service exécuté sur l'hôte lui-même, utilisez le nom host.docker.internal en ajoutant :

extra_hosts:
  - "host.docker.internal:host-gateway"

Diagnostic

docker compose exec app ping -c2 db
docker compose exec app getent hosts db
sudo ss -tulpn | grep LISTEN
docker port <container>

ss indiquera sur quelle interface un port écoute réellement : 0.0.0.0:8080 — ouvert vers l'extérieur, 127.0.0.1:8080 — non.

Erreurs courantes

  • « Port already in use ». Il est occupé par un autre conteneur ou un service de l'hôte. sudo ss -tulpn | grep :80 trouvera le coupable.
  • Les conteneurs de projets Compose différents ne se voient pas. Chaque projet a son propre réseau. Reliez-les explicitement via networks: { shared: { external: true } }.
  • L'application écoute sur 127.0.0.1 à l'intérieur du conteneur. La publication ne servira alors à rien : vous ne pourrez pas l'atteindre depuis l'extérieur du conteneur. Configurez l'application pour qu'elle écoute sur 0.0.0.0.
  • Bande passante. Jusqu'à 500 Mbps partagés par hôte. La distribution de fichiers la partage avec tout le reste.