5. Les ports - Docker

Dans le cours précédent, nous avons pu lancer un conteneur à partir de l'image Python.
Regardons ensemble comment fonctionne le réseau dans Docker en essayant notamment d'exposer un ou plusieurs ports dans un conteneur.

Le réseau dans Docker

Une chose essentielle à savoir c'est que dès son installation, Docker vient créer une interface réseau virtuelle en mode bridge avec ce réseau par défaut 172.17.0.1/16 :

docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:f2:4b:b9:6b brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

Chaque nouveau conteneur aura donc pour adresse IP 172.17.0.2 puis 172.17.0.3 et ainsi de suite...

Les ports internes

Toujours avec notre conteneur Python, je souhaite démarrer un serveur HTTP à l'aide de du module Python http.server.
Nous allons lancer notre conteneur comme fait dans le cours précédent avec la commande suivante :

docker run -td --name mon-conteneur-python python

Il est possible d’inspecter beaucoup de ressources dans Docker afin d'y récupérer certaines informations.
Inspectons notre conteneur afin d'y récupérer son adresse IP :

docker inspect mon-conteneur-python
Retour :
{
  "Networks": {
    "bridge": {
      "IPAMConfig": null,
      "Links": null,
      "Aliases": null,
      "NetworkID": "ffea38e82c8a71910cc8d1165e9c2d499d8516798643ebdceca237bb4d0d4bab",
      "EndpointID": "0e866ed94a2002154b120cafc5dc036f85831e239bf0545f79c4f5d18b482bd1",
      "Gateway": "172.17.0.1",
      "IPAddress": "172.17.0.2",
      "IPPrefixLen": 16,
      "IPv6Gateway": "",
      "GlobalIPv6Address": "",
      "GlobalIPv6PrefixLen": 0,
      "MacAddress": "02:42:ac:11:00:02",
      "DriverOpts": null
    }
  }
}

Il est aussi possible de formater la sortie afin de filtrer uniquement que ce qui nous intéresse :

docker inspect --format={{.NetworkSettings.Networks.bridge.IPAddress}} mon-conteneur-python

Puis nous allons nous connecter au conteneur en lançant un Shell avec cette commande :

docker exec -ti mon-conteneur-python bash

Maintenant que nous sommes dans le conteneur, essayons d'exécuter la commande suivante qui permet de lancer un serveur HTTP Python qui écoute par défaut sur le port 8000 :

python3 -m http.server
Retour :
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Essayons d'accéder au serveur HTTP sur notre navigateur avec l'IP de notre conteneur :

🎉 Nous avons réussi à accéder au serveur HTTP de notre conteneur avec son adresse IP !

L'exposition de ports

Il existe un autre moyen d'accéder à notre conteneur, autrement que par son adresse IP : la redirection de ports.

En effet, il est possible de rediriger le port d'un conteneur sur notre machine hôte en précisant l'option -p de notre commande docker run.

Supprimons notre conteneur avec la commande :

docker rm -f mon-conteneur-python

Lançons à nouveau notre conteneur, cette fois-ci avec l'argument supplémentaire -p comme ceci :

docker run -td --name mon-conteneur-python -p 80:8000 python

L'argument -p 80:8000 signifie que nous redirigeons le port 8000 du conteneur (qui correspond au port du serveur HTTP Python) sur le port 80 de notre machine en local.
Vous l'avez compris, la partie à droite correspond au port du conteneur, et à gauche à la machine hôte.

Connectons-nous encore une fois avec la commande docker exec :

docker exec -ti mon-conteneur-python bash

Lançons de nouveau notre serveur HTTP Python avec cette commande :

python3 -m http.server

Cette fois-ci, accédons au serveur HTTP sur notre navigateur non pas avec l'IP mais du conteneur... mais en localhost !

Conclusion

Avec ce cours, vous savez maintenant :

  • Récupérer l'adresse IP d'un conteneur en l'inspectant
  • Accéder au port interne d'un conteneur
  • Rediriger le port d'un conteneur sur la machine hôte

Docker offre d'autres fonctionnalités en terme de réseau, notamment en créant des réseaux personnalisés, en changeant le driver pour ne plus être en bridge etc... Nous verrons cela dans un autre cours.

Dans la partie suivante, nous allons comprendre comment la persistances des données fonctionne avec les volumes Docker !