📘 Publication de ports réseau d’un conteneur
1. Problématique
Nous avons vu qu’un conteneur avait pour caractéristique d’isoler un logiciel dans un environnement minimal adapté Cependant, comme vu dans le chapitre précédent, il arrive couramment qu'un processus logiciel nécessite de communiquer avec un autre processus, pour échanger des messages et/ou accomplir une tâche.
Or, la conteneurisation peut nous amener à mettre en place un conteneur par logiciel déployé, ce qui signifie que chaque processus logiciel déployé ainsi se retrouve dans un micro-environnement isolé de tous les autres processus avec lesquels il pourrait souhaiter communiquer.
Comment permettre à un processus exécuté dans un conteneur de communiquer avec d’autres processus situés à l’extérieur du conteneur ? Dans ce (bref) chapitre nous allons étudier un premier méchanisme permettant de permettre certaines communications : la publication de ports réseaux, pour relier un conteneur au réseau local (ou Internet) de l’environnement d’accueil où il s’exécute.
| Nous verrons dans un futur chapitre comment mettre en réseau plusieurs conteneurs entre eux, afin de permettre à leurs processus de communiquer. |
2. Principe
Dans un environnement donné, lorsqu’un processus logiciel dit serveur souhaite pouvoir être contacté par d’autres processus logiciels, il est nécessaire que ce processus serveur écoute sur un port réseau choisi d’une interface réseau de son environnement. Une fois cette écoute en place sur le port choisi, d’autres processus dits clients peuvent se connecter sur ce port et démarrer une communication avec le processus serveur.
Cependant, lorsque le processus serveur est exécuté au sein d’un conteneur, à savoir un mini-environnement lui-même à l’intérieur d’un environnement d’accueil, un problème se pose : si le processus serveur écoute sur un port réseau, ce sera via une interface réseau de son conteneur, et non une interface réseau de son environnement d’accueil. Ainsi, malheureusement, un processus client situé sur le réseau local de l’environnement d’accueil ne sera pas en mesure de rentrer en communication avec ce processus serveur, car le processus client ne pourra que contacter une interface réseau de l’environnement d’accueil du processus serveur.
Pour rappel, Simplestblog est un logiciel qui s’exécute sous la forme d’un serveur web qui s’attend à recevoir des connexions de la part de_clients web communément appelés des navigateurs webs.
Supposons que :
-
Simplestblog s’exécute au sein d’un conteneur lui-même hébergé dans un environnement d’accueil.
-
Une personne utilise un poste de travail dénommé environnement utilisateur afin d’exécuter le navigateur web Firefox, et cherche à se connecter au serveur web Simplestblog.
-
Chacun de ces environnements est connecté à un réseau local ethernet via leur interfaces réseau ethernet respectives.
On aurait alors la situation suivante :
| Pour des raisons de lisibilité, dans ce schéma et dans les prochains schémas de ce chapitre, nous simplifions la représentation car nous ne représentons pas explicitement les couches "Matériel" et "Système d’exploitation" des différents environnements. Nous omettons également la représentation des dépendances de chaque logiciel. |
Problème : si le serveur web conteneurisé se met à écouter sur un port réseau, ce sera forcément un port de l’interface réseau virtuelle du conteneur dans lequel il s’exécute, et non un port réseau de l’interface réseau ethernet de l’environnement d’accueil. Or, comme l’interface réseau virtuelle du conteneur n’est pas connectée au réseau local ethernet, il sera impossible pour le client web de se connecter au port d’écoute.
Pour remédier à cela, il est possible pour un conteneur de réaliser une publication de port réseau.
Une publication de port consiste à relier un port réseau X d’une interface réseau du conteneur, à un port réseau d’une interface réseau de l’environnement d’accueil.
Une fois cette liaison établie, toute connexion depuis l’extérieur sur le port Y sera systématiquement transmise au port X du conteneur.
L’illustration ci-dessus présente trois conteneurs dans le même environnement d’accueil.
Le conteneur A exécute un logiciel qui écoute sur les ports 5000 et 21 au travers de l’interface réseau virtuelle du conteneur.
On décide de publier le port 5000 en le reliant au port 80 de l’environnement d’accueil, et on publie également le port 21 en le reliant au port 21 de l’environnement d’accueil.
On publie également le port 465 du conteneur B sur le même port de l’environnement d’accueil.
Enfin, on publie les ports 465 et 22 et du conteneur C sur les ports 565 et 2222 de l’environnement d’accueil
Ainsi, de manière transparente :
-
Si on accède au port
80de l’environnement d’accueil, on se retrouvera connecté au port5000du conteneur A. -
Si on accède au port
21de l’environnement d’accueil, on se retrouvera connecté au port21du conteneur A. -
Si on accède au port
465de l’environnement d’accueil, on sera connecté au port465du conteneur B. -
Si on accède au port
565de l’environnement d’accueil, on sera connecté au port465du conteneur C. -
Si on accède au port
2222de l’environnement d’accueil, on sera connecté au port22du conteneur C.
| On remarque qu’un même numéro de port peut être utilisé à la fois chez un conteneur et chez l’environnement d’accueil, et même par plusieurs conteneurs simultanément. |
On repart de la situation précédente avec Simplestblog conteneurisé, mais cette fois-ci on décide de briser l’isolation du conteneur à l’aide d’une publication de port.
Plus précidément, on choisit de publier le port 5000 du conteneur (sur lequel le processus Simplestblog écoute) vers le port 4000 de l’environnement d’accueil.
On obtient donc :
Ainsi, tout navigateur qui se connecte sur le port 4000 de l’environnement d’accueil sera de manière transparente connectée au port 5000 du conteneur, et donc au processus Simplestblog qui écoute sur ce port.
3. Mise en œuvre avec Podman
La publication d’un port du conteneur vers l’environnement d’accueil se fait lors de la création d’un conteneur (par exemple lors d’un appel à podman container run) à l’aide de l’option suivante :
-
--publish(version courte :-p) : publie un port du conteneur vers l’environnement d’accueil, avec une syntaxe<port environnement d’accueil>:<port conteneur>
|
Par défaut, la publication de ports se fait sur toutes les interfaces réseau de l’environnement d’accueil, ce qui est symbolisé par l’adresse Pour ce cours, on pourra se contenter de garder le comportement par défaut, autrement dit la publication sur l’adresse |
Pour afficher la liste des publications de ports d’un conteneur, on également faire :
$ podman container port <nom du conteneur>
On souhaite déployer un petit serveur web nginx mais cette fois-ci en connectant ce serveur web à l’extérieur pour qu’on puisse s’y connecter à l’aide d’un navigateur. Par défaut, nginx est un logiciel qui écoute sur le port 80. On doit donc effectuer une publication du port 80 du conteneur vers un port de l’environnement d’accueil − pour cet exemple, on choisit le port 8200.
On exécute donc la commande suivante :
$ podman container run --name mon_serveur_web \
--detach \
--publish 8200:80 \
docker.io/nginx:latest
On vérifie que le port est bien publié comme souhaité :
$ podman container port mon_serveur_web
80/tcp -> 0.0.0.0:8200
0.0.0.0 signifie que la publication se fait sur toutes les interfaces réseau de l’environnement d’accueil.
|
À l’aide d’un navigateur web comme Firefox, on peut ensuite se connecter sur le port 8200 de l’environnement d’accueil, ce qui de manière transparent nous connecte au port 80 du conteneur mon_serveur_web, ce qui nous emmène sur le serveur web nginx qui présente la page par défaut suivante :