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 :
docker run -it debian bash
root@26d068da63e7:/# apt update && apt install -y iproute2 && ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
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 :
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:
docker run -it --name container1 --net myfirstnet debian bash
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
$ docker run -it --name container1 --net myfirstnet debian bash
root@26d068da63e7:/# apt update && apt install -y iputils-ping
root@26d068da63e7:/# ping container2
PING container2 (172.18.0.3) 56(84) bytes of data.
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=1 ttl=64 time=0.160 ms
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=2 ttl=64 time=0.107 ms
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=3 ttl=64 time=0.109 ms
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=4 ttl=64 time=0.108 ms
64 bytes from container2.myfirstnet (172.18.0.3): icmp_seq=5 ttl=64 time=0.068 ms
--- container2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4090ms
rtt min/avg/max/mdev = 0.068/0.110/0.160/0.030 ms