Conteneur et réseau

Dans l'exercice précédent, nous avons démarré une instance PostgreSQL dans un conteneur. Cependant cette base de données ne pouvait être utilisée que en local dans le conteneur.

C'est assez limitant, d'autant plus que la philosophie de Docker veut que l'on segmente les différents services dans des conteneurs séparés : un serveur Web dans un conteneur, une base de données dans un autre, etc.

Docker place les différents conteneurs dans des réseaux privés virtuels isolés, sur la machine hôte. Par exemple si l'on regarde l'adresse IP d'un conteneur :

1
docker run -it debian bash
2
root@26d068da63e7:/# apt update && apt install -y iproute2 && ip a
3
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
4
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5
    inet 127.0.0.1/8 scope host lo
6
      valid_lft forever preferred_lft forever
7
33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
8
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
9
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
10
      valid_lft forever preferred_lft forever

On constate que le conteneur a une interface sur un réseau 172.17.0.0/16. Ce réseau est un réseau par défaut que Docker a créé. C'est un réseau de type bridge, c'est à dire que le conteneur a accès à internet via la machine hôte, et la machine hôte peut accéder au conteneur en passant par le réseau virtuel de Docker.

Connecter le conteneur à un port de l'hôte

Cependant il est possible de connecter un (ou plusieurs) port spécifique du conteneur à un port de la machine hôte : le processus dans le conteneur aura ainsi directement accès à la couche réseau de la machine hôte pour le port en question. Pour cela on utilise l'option -p PORT_HOTE:PORT_CONTENEUR au démarrage du conteneur.

Par exemple, on lance un conteneur Nginx avec :

1
docker run -d --name nginx-1 -p 8080:80 nginx

Lorsque l'on ouvre son navigateur et que l'on navigue sur la machine hôte, sur le port 8080, on constate la page par défaut de Nginx. Le port 8080 de la machine hôte redirige automatiquement vers le port 80 du conteneur (sur lequel écoute le serveur Nginx).

En cherchant dans la documentation de Docker et sur internet, trouvez une commande permettant d'afficher en direct les logs d'accès sur votre serveur Nginx.

Connecter des conteneurs dans un même réseau

Cependant, il n'est pas forcément recommandé de publier tout les ports de tout les services de notre machine. Par exemple il est judicieux de ne pas exposer une base de données directement sur internet lorsque ce n'est pas nécessaire, mais plutôt de la placer dans un réseau privé auquel les clients (typiquement les serveurs web) auront accès. Docker permet cela grâce à la possibilité de créer des réseaux Docker et d'y connecter des conteneurs.

Pour commencer, on peut créer notre premier réseau avec docker network create myfirstnet. Il sera ensuite possible de placer des conteneurs dans ce réseau, avec l'option --net myfirstnet, qui pourront communiquer entre eux. D'ailleurs Docker permet à des conteneurs d'un même réseau de communiquer entre eux en se basant sur leurs noms (à l'aide d'un DNS dynamique).

Par exemple nous pouvons lancer 2 conteneurs différents:

1
docker run -it --name container1 --net myfirstnet debian bash
2
docker run -it --name container2 --net myfirstnet debian bash

Dans le premier conteneur on peut contacter le second, sur son IP privée, grâce à son nom DNS container2

1
$ docker run -it --name container1 --net myfirstnet debian bash
2
root@26d068da63e7:/# apt update && apt install -y iputils-ping
3
root@26d068da63e7:/# ping container2
4
PING container2 (172.18.0.3) 56(84) bytes of data.
5
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=1 ttl=64 time=0.160 ms
6
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=2 ttl=64 time=0.107 ms
7
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=3 ttl=64 time=0.109 ms
8
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=4 ttl=64 time=0.108 ms
9
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=5 ttl=64 time=0.068 ms
10
11
--- container2 ping statistics ---
12
5 packets transmitted, 5 received, 0% packet loss, time 4090ms
13
rtt min/avg/max/mdev = 0.068/0.110/0.160/0.030 ms