IREX - Docker et la communication inter-processus : ports, noms et adresses IP
Tu t'es déjà demandé comment les conteneurs Dockers communiquent-ils entre eux ?
Docker et la communication inter-processus : ports, noms et adresses IP
Sommaire
- 1. Introduction
- 2. Les ports : exposer et sécuriser les services
- 3. Les noms de conteneurs : un DNS intégré
- 4. Les adresses IP : comprendre la couche réseau
- 5. Exemple détaillé : architecture 3 tiers
- 6. Bonnes pratiques et pièges courants
- 7. Erreurs fréquentes et comment les éviter
- 8. Conclusion et ouverture
- 9. Voir aussi
1. Introduction
Docker a révolutionné la façon dont les développeurs et les DevOps conçoivent, testent et déploient des applications. Mais si l’on se limite à un seul conteneur, on passe à côté de sa véritable puissance : celle de composer des environnements complets où plusieurs services collaborent. Dans ce contexte, la communication inter-processus devient un sujet incontournable.
J’ai personnellement découvert cette problématique lors d’un projet en stage : un backend devait échanger avec une base de données et fournir des données à un frontend. Chaque service fonctionnait parfaitement seul, mais dès qu’il fallait les connecter entre eux, tout se compliquait. C’est alors que j’ai compris l’importance de trois mécanismes fondamentaux : les ports, les noms de conteneurs et les adresses IP.
2. Les ports : exposer et sécuriser les services
Par défaut, un conteneur Docker est isolé. Les applications qu’il exécute écoutent sur des ports internes (80 pour un serveur web, 3306 pour MySQL, etc.). Pour rendre un service accessible depuis l’hôte ou l’extérieur, il faut l’exposer en mappant un port du conteneur à un port de la machine hôte.
docker run -p 8080:80 nginx
Ici, le port 80 interne est relié au port 8080 de l’hôte. Cela rend possible un accès via http://localhost:8080
.
Mais attention : exposer un port revient à ouvrir une porte. Dans un projet réel, on doit choisir avec soin ce que l’on expose.
Une base de données, par exemple, devrait rarement être accessible directement de l’extérieur.
Autres points pratiques :
- Vérifier le mapping réel :
docker ps
etdocker port <container>
. - Si l’application écoute uniquement sur
127.0.0.1
à l’intérieur du conteneur, elle ne sera pas accessible depuis l’hôte ; il faut qu’elle écoute sur0.0.0.0
. - Sur des environnements restreints, un pare-feu (ufw, iptables) ou SELinux peut bloquer l’accès — vérifie ces couches si le port semble publié mais injoignable.
3. Les noms de conteneurs : un DNS intégré
Une fois plusieurs conteneurs créés, il faut qu’ils puissent communiquer entre eux. C’est là que Docker simplifie la vie : dans un réseau Docker, chaque conteneur peut être joint par son nom.
docker network create monreseau
docker run -d --name web --network monreseau nginx
docker run -d --name app --network monreseau python-app
Dans cet exemple, app
peut appeler web
via http://web:80
. Docker fait office de DNS et traduit automatiquement le nom du conteneur en son adresse IP interne.
Cela évite le casse-tête des IP qui changent à chaque redémarrage, et permet une configuration beaucoup plus lisible et robuste.
4. Les adresses IP : comprendre la couche réseau
Sous le capot, Docker attribue une adresse IP à chaque conteneur dans le réseau défini. Par défaut, il utilise un réseau de type bridge avec une plage d’adresses privée.
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
On peut donc joindre un conteneur par son IP, mais c’est déconseillé : ces adresses sont éphémères. La bonne pratique est de s’appuyer sur les noms de conteneurs, et de garder l’IP comme un outil de diagnostic en cas de problème réseau.
5. Exemple détaillé : architecture 3 tiers
Imaginons une application composée de trois parties : un frontend en Nginx, une API backend en Python et une base de données PostgreSQL. Avec Docker Compose, leur communication devient explicite :
version: '3'
services:
frontend:
image: nginx
ports:
- "8080:80"
networks:
- appnet
backend:
build: ./backend
networks:
- appnet
db:
image: postgres
environment:
POSTGRES_PASSWORD: exemple
networks:
- appnet
networks:
appnet:
Dans cette configuration :
- Le frontend appelle le backend via
http://backend:5000
. - Le backend se connecte à la base via
db:5432
. - Seul le frontend expose un port vers l’extérieur ; les autres services communiquent en interne.
6. Bonnes pratiques et pièges courants
- Limiter l’exposition des ports : n’ouvrez à l’extérieur que ce qui est nécessaire.
- Nommer clairement vos services pour éviter toute confusion dans les configurations.
- Utiliser des réseaux dédiés pour isoler vos environnements (par ex. test, prod).
- Privilégier Docker Compose pour gérer plusieurs services plutôt que de lancer chaque conteneur à la main.
- Vérifier régulièrement la configuration réseau avec
docker network inspect
etdocker ps
. - S’assurer que les applications écoutent sur 0.0.0.0 si elles doivent accepter des connexions externes au conteneur.
L’un des pièges les plus fréquents est de penser que tout doit passer par des ports exposés. En réalité, la majorité des communications entre conteneurs se font en interne, sans jamais avoir besoin d’ouvrir un accès vers l’hôte.
7. Erreurs fréquentes et comment les éviter
Deux erreurs reviennent souvent dans les tickets et dans les conversations de salle : elles sont simples, mais elles coûtent du temps quand on les ignore. Je les ai moi-même rencontrées en stage — et je les ai résolues, parfois à la sueur du front.
Erreur fréquente A — Pas de réseau commun entre conteneurs
Symptôme : deux conteneurs semblent lancés, mais l’un ne peut pas joindre l’autre (ex. : l’API ne joint pas la base). Cause : les conteneurs ne sont pas rattachés au même réseau Docker. Par défaut, si on lance des conteneurs individuellement sans préciser de réseau, ils peuvent être isolés les uns des autres.
Diagnostic :
docker ps
pour lister les conteneurs en cours.docker network ls
pour voir les réseaux existants.docker inspect <container>
pour vérifier les réseaux auxquels le conteneur est connecté.docker network inspect <network>
pour lister les conteneurs attachés à un réseau.
Correction :
docker network create mon_reseau
docker run -d --network=mon_reseau --name db mysql:5.7
docker run -d --network=mon_reseau --name api mon_api
Avec Docker Compose, on définit le réseau dans le fichier et on laisse Compose attacher automatiquement les services au bon réseau. Après cela, la résolution par nom fonctionne (ex. api
vers db
).
Astuce pratique : si tout semble bien configuré mais que ça ne marche pas, exécutez un shell dans un conteneur et testez la résolution DNS / connectivité :
docker exec -it api sh
# from inside the container
ping db || curl -v http://db:5432
Erreur fréquente B — Port mappé manquant ou application liée à 127.0.0.1
Symptôme : le service tourne dans le conteneur mais n’est pas accessible depuis l’hôte (ou depuis d’autres conteneurs). Causes possibles :
- Le port n’a pas été publié (oubli du
-p
ou du mapping dans docker-compose). - L’application écoute uniquement sur
127.0.0.1
à l’intérieur du conteneur (par défaut certains serveurs de développement le font). - Un pare-feu ou une politique réseau bloque le port exposé.
Diagnostic :
docker ps
pour vérifier la colonne PORTS (mapping hôte→conteneur).docker port <container>
pour voir les ports exposés par le conteneur.docker logs <container>
pour vérifier sur quelle interface l’application indique qu’elle écoute.- Se connecter dans le conteneur et lister les sockets :
docker exec -it <container> ss -tulnp
ounetstat -tuln
.
Correction :
- Publier le port lors du lancement :
docker run -p 8080:5000 mon_api
ou configurerports
dansdocker-compose.yml
. - Faire en sorte que l’application écoute sur
0.0.0.0
(ex. Flask :app.run(host='0.0.0.0')
; ou préférer Gunicorn en production). - Vérifier le pare-feu de l’hôte (ufw/iptables) et les règles SELinux si présentes.
Cas pratique rencontré : j’ai une fois monté une API Flask dans un conteneur ; l’API était accessible en local sur la machine de développement, mais pas depuis le navigateur via localhost:5000
après le docker run. La cause : Flask écoutait par défaut sur 127.0.0.1
; la correction a été d’ajouter app.run(host='0.0.0.0')
et de relancer le conteneur avec -p 5000:5000
.
8. Conclusion et ouverture
Maîtriser la communication inter-processus avec Docker, c’est comprendre trois leviers : les ports, les noms et les adresses IP. En pratique, cela signifie organiser ses réseaux, limiter l’exposition, vérifier les bindings applicatifs et diagnostiquer efficacement quand ça casse.
Savoir repérer et corriger les erreurs décrites ici vous fera gagner du temps et démontrera une vraie compétence DevOps : connecter correctement des services conteneurisés n’est pas magique, c’est méthodique. Quand vos besoins dépassent quelques conteneurs, des solutions d’orchestration (Kubernetes, Docker Swarm) et des outils de service discovery deviennent nécessaires — mais les principes restent les mêmes.
No comments yet. Start a new discussion.