Docker : comment utiliser un service de l'hôte depuis un conteneur ?

il y a 4 mois

Attention : cet article ne couvre que Docker sous Linux. Je n'ai pas testé sous Windows. Sous MacOS l'inteface docker0 n'étant pas accessible, cette astuce ne fonctionnera pas.

Imaginons que vous vouliez utiliser un service présent sur un serveur hôte depuis un conteneur docker. Ce n'est pas forcément très propre mais croyez-moi, si vous êtes amené à utiliser Docker ça va forcément vous arriver. On peut prendre le cas où une application embarquée dans un ou plusieurs conteneurs nécessiterait l'accès au service SMTP ou à une base de données présent sur l'hôte.

Cas simple : le service écoute sur la bonne interface

Si le service en question écoute sur toutes les interfaces ou sur l'interface "docker0" (pour rappel, cette interface est créée automatiquement lors du démarrage de dockerd) c'est le cas idéal et surtout le plus simple à mettre en oeuvre.

En effet, il suffit alors dans le conteneur de faire référence à l'IP de l'hôte sur le réseau docker0 (chez moi 172.17.0.1).

Faisons un essai en tentant d'utiliser le port SSH (22) de l'hôte depuis un conteneur :

$ # démarrage du service docker
$ sudo systemctl start docker
$ # récupération de l'IP de l'hôte sur l'interface docker0
$ ifconfig | grep -A 1 docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
$ # ouverture du shell d'un conteneur
$ docker run -it alpine sh
$ telnet 172.17.0.1 22
SSH-2.0-OpenSSH_7.4
$ # le service est accessible !

Cas plus complexe : le service n'écoute pas sur la bonne interface

La méthode précédente ne fonctionnera pas si par exemple vous désirez acceder à un service qui n'écoute que sur l'interface loopback (IP 127.0.0.1 sur l'hôte).

Pas de panique ! On va utiliser une petite ruse rendue possible par une commande bien sympatique : redir (d'autres outils peuvent être utilisés comme iptables mais celui-ci est mon préféré car il est particulièrement simple à mettre en oeuvre). Redir va nous permettre de rediriger des connexions TCP/IP vers une autre IP.

Tout d'abord, commençons par l'installer.

RHEL :

Après avoir ajouté le dépôt "nux-misc" (instructions), installer le paquet :

$ sudo yum install --enablerepo=nux-misc -y redir

Debian :

$ sudo apt-get update && sudo apt-get install redir

Maintenant, utilisons la commande redir de manière à rediriger les connexions TCP/IP à destination de l'IP de l'hôte sur le réseau docker0 vers 127.0.0.1 (loopback de l'hôte) :

$ sudo redir --laddr <ip hôte sur docker0> --caddr <ip où le service est accessible> --lport <port du service> --cport <port du service>

Si par exemple on veut utiliser un service MySQL uniquement accessible sur l'IP 127.0.0.1 de l'hôte depuis un conteneur on écrira :

$ sudo redir --laddr 172.17.0.1 --caddr 127.0.0.1 --lport 3306 --cport 3306

Faisons maintenant le test depuis un conteneur :

$ # ouverture du shell d'un conteneur
$ docker run -it alpine sh
$ telnet 172.17.0.1 3306
J
5.7.205'.V
          j^.R.	<L]JYmysql_native_password
$ # le service est accessible !

En conclusion on peut dire que redir est une commande simple d'utilisation pour le commun des mortels (contrairement à iptables !) qui peut rendre bien des services pour un environnement de développement ou lors de la configuration rapide d'un conteneur.