Un conteneur est isolé par défaut

Par défaut, un conteneur est isolé du reste de votre ordinateur : ses processus, son réseau, ses ports internes n'existent que pour lui. Mini-Carnet, dans son conteneur, écoute bel et bien sur un port, celui défini par PORT dans server.js (3000 par défaut). Mais ce port reste, sans indication contraire, invisible depuis l'extérieur du conteneur, y compris depuis votre propre navigateur.

Deux mondes séparés : l'hôte et le conteneur

Il faut distinguer deux ports, qui portent parfois le même numéro mais désignent deux choses différentes : le port du conteneur, celui sur lequel l'application écoute réellement à l'intérieur de son isolement, et le port de l'hôte, celui de votre ordinateur, ouvert vers l'extérieur, sur lequel votre navigateur va effectivement se connecter.

L'option -p, pour « publish », crée un pont entre ces deux mondes. Sa syntaxe est -p port-de-lhote:port-du-conteneur.

Ici, les deux numéros sont identiques, ce qui peut laisser croire qu'un seul port suffirait. Ce n'est pas le cas : ce sont bien deux valeurs distinctes, qui peuvent parfaitement différer.

Un exemple où les deux ports diffèrent

Arrêtez d'abord le conteneur actuel, puis relancez-en un nouveau, en changeant uniquement le port de l'hôte :

Ouvrez maintenant http://localhost:8081, et non plus 3000. La page s'affiche exactement pareil : à l'intérieur du conteneur, Mini-Carnet écoute toujours sur le port 3000, il n'en sait rien d'autre. Seul le port de l'hôte, celui que vous tapez dans votre navigateur, a changé.

Petit exercice

Relancez maintenant le conteneur en exposant le service sur le port 8090 de votre ordinateur au lieu de 8081, toujours vers le port 3000 du conteneur. Vérifiez ensuite que http://localhost:8090 affiche bien Mini-Carnet. La commande à adapter : docker run -d -p 8090:3000 --name mon-carnet mini-carnet, après avoir arrêté et supprimé le conteneur précédent.

Pourquoi cette séparation est utile

Cette distinction devient particulièrement pratique dès que plusieurs conteneurs doivent tourner en même temps sur le même ordinateur. Deux conteneurs peuvent très bien écouter chacun sur le port 3000 en interne, sans le moindre conflit, tant qu'ils sont publiés vers des ports d'hôte différents, par exemple 3000 et 3001.

Erreur fréquente : port déjà utilisé

Si Docker refuse de démarrer un conteneur avec un message évoquant un port déjà utilisé (« port is already allocated »), c'est que le port de l'hôte demandé est déjà occupé, par un autre conteneur ou par un programme de votre ordinateur. La solution la plus simple : choisir un autre port d'hôte disponible. Vous retrouverez ce cas précis, détaillé, au guide 30.

Vérifiez que vous avez compris

Vous lancez un conteneur avec -p 5000:3000. À quelle adresse devez-vous ouvrir votre navigateur pour accéder à l'application ?

http://localhost:5000. Le premier nombre, 5000, est le port de l'hôte, celui que votre navigateur doit contacter depuis l'extérieur du conteneur. Le second, 3000, reste un détail interne : c'est le port sur lequel l'application écoute à l'intérieur du conteneur, sans intérêt direct pour votre navigateur.