Depuis l'intérieur d'un conteneur Docker, comment puis-je me connecter à l'hôte local de la machine ?
J'ai donc un Nginx fonctionnant dans un conteneur docker, j'ai un MySql fonctionnant sur localhost, je veux me connecter au MySql depuis mon Nginx. Le MySql fonctionne sur localhost et n'expose pas de port au monde extérieur, il est donc lié à localhost et non à l'adresse IP de la machine.
Existe-t-il un moyen de se connecter à ce MySql ou à tout autre programme sur localhost depuis ce conteneur docker ?
Cette question est différente de "Comment obtenir l'adresse IP de l'hôte du docker depuis l'intérieur d'un conteneur de docker" ; car l'adresse IP de l'hôte du docker peut être l'IP publique ou l'IP privée du réseau qui peut ou non être accessible depuis le conteneur de docker (je veux dire l'IP publique si elle est hébergée chez AWS ou autre). Même si vous avez l'adresse IP de l'hôte Docker, cela ne signifie pas que vous pouvez vous connecter à l'hôte Docker depuis le conteneur avec cette adresse IP, car votre réseau Docker peut être superposé, hôte, pont, macvlan, aucun, etc., ce qui limite l'accessibilité de cette adresse IP.
Edit: Si vous utilisez Docker-for-mac ou Docker-for-Windows 18.03+, connectez-vous simplement à votre service mysql en utilisant l'hôte
host.docker.internal
.A partir de Docker 18.09.3, cela ne fonctionne pas sur Docker-for-Linux. Un fix a été soumis le 8 mars 2019 et sera, nous l'espérons, intégré à la base de code. En attendant, une solution de contournement consiste à utiliser un conteneur comme décrit dans la réponse de qoomon'1.
TLDR
Utilisez
--network="host"
dans votre commandedocker run
, alors127.0.0.1
dans votre conteneur docker pointera vers votre hôte docker.Remarque : Ce mode ne fonctionne que sur Docker pour Linux, [selon la documentation][2].
Note sur les modes de mise en réseau des conteneurs Docker
Docker propose [différents modes de mise en réseau] (https://docs.docker.com/engine/reference/run/#network-settings) pour l'exécution des conteneurs. En fonction du mode choisi, vous vous connecterez différemment à votre base de données MySQL exécutée sur l'hôte Docker.
docker run --network="bridge" ; (par défaut)
Docker crée un pont nommé
docker0
par défaut. L'hôte docker et les conteneurs docker ont tous deux une adresse IP sur ce pont.Sur l'hôte Docker, tapez
sudo ip addr show docker0
, vous obtiendrez une sortie ressemblant à ceci :Donc ici mon hôte Docker a l'adresse IP
172.17.42.1
sur l'interface réseaudocker0
.Maintenant, démarrez un nouveau conteneur et obtenez un shell sur celui-ci :
docker run --rm -it ubuntu:trusty bash
et dans le conteneur tapezip addr show eth0
pour découvrir comment son interface réseau principale est configurée :Ici, mon conteneur a l'adresse IP
172.17.1.192
. Maintenant regardez la table de routage :Donc l'adresse IP de l'hôte docker
172.17.42.1
est définie comme route par défaut et est accessible depuis votre conteneur.docker run --network="host" ;
Vous pouvez également exécuter un conteneur docker avec [les paramètres réseau définis sur
host
] (http://docs.docker.com/engine/reference/run/#network-host). Un tel conteneur partagera la pile réseau avec l'hôte de docker et du point de vue du conteneur,localhost
(ou127.0.0.1
) fera référence à l'hôte de docker.Soyez conscient que tout port ouvert dans votre conteneur docker sera ouvert sur l'hôte docker. Et ceci sans avoir besoin de l'option [
-p
ou-P
docker run
] (https://docs.docker.com/engine/reference/run/#expose-incoming-ports).Configuration IP sur mon hôte Docker :
et depuis un conteneur docker en mode hôte :
Comme vous pouvez le constater, l'hôte docker et le conteneur docker partagent exactement la même interface réseau et ont donc la même adresse IP.
Connexion à MySQL à partir de conteneurs
mode pont
Pour accéder à MySQL fonctionnant sur l'hôte docker à partir de conteneurs en mode bridge, vous devez vous assurer que le service MySQL écoute les connexions sur l'adresse IP
172.17.42.1
.Pour ce faire, assurez-vous que vous avez soit
bind-address = 172.17.42.1
, soitbind-address = 0.0.0.0
dans votre fichier de configuration MySQL (my.cnf).Si vous avez besoin de définir une variable d'environnement avec l'adresse IP de la passerelle, vous pouvez exécuter le code suivant dans un conteneur :
puis dans votre application, utilisez la variable d'environnement
DOCKER_HOST_IP
pour ouvrir la connexion à MySQL.Note: si vous utilisez
bind-address = 0.0.0.0
votre serveur MySQL écoutera les connexions sur toutes les interfaces réseau. Cela signifie que votre serveur MySQL peut être atteint depuis l'Internet ; assurez-vous de configurer les règles du pare-feu en conséquence.Note 2: si vous utilisez
bind-address = 172.17.42.1
votre serveur MySQL n'écoutera pas les connexions faites sur127.0.0.1
. Les processus exécutés sur l'hôte Docker qui voudraient se connecter à MySQL devraient utiliser l'adresse IP172.17.42.1
.mode hôte
Pour accéder à MySQL fonctionnant sur l'hôte docker à partir de conteneurs en mode hôte, vous pouvez conserver
bind-address = 127.0.0.1
dans votre configuration MySQL et tout ce que vous avez à faire est de vous connecter à127.0.0.1
depuis vos conteneurs :note: Utilisez
mysql -h 127.0.0.1
et nonmysql -h localhost
; sinon le client MySQL essaiera de se connecter en utilisant un socket unix.[2] : https://docs.docker.com/network/host/
Cela a fonctionné pour moi sur une pile NGINX/PHP-FPM sans toucher au code ou au réseau où l'application s'attend simplement à pouvoir se connecter à
localhost
.Montez
mysqld.sock
de l'hôte à l'intérieur du conteneur.Trouvez l'emplacement du fichier mysql.sock sur l'hôte exécutant mysql : `netstat -ln | awk '/mysql(.*)?.sock/ { print $9 }'``
Montez ce fichier à l'endroit où il est attendu dans le docker :
docker run -v /hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock
Emplacements possibles de mysqld.sock :
Je ne suis pas d'accord avec la réponse de Thomasleveil.
Le fait de lier mysql à 172.17.42.1 empêchera les autres programmes utilisant la base de données sur l'hôte de l'atteindre. Cela ne fonctionnera que si tous les utilisateurs de votre base de données sont dockerisés.
Lier mysql à 0.0.0.0 ouvrira la base de données au monde extérieur, ce qui est non seulement une très mauvaise chose à faire, mais aussi contraire à ce que l'auteur de la question originale veut faire. Il dit explicitement : "Le MySql fonctionne sur localhost et n'expose pas de port au monde extérieur, il est donc lié à localhost" ;
Pour répondre au commentaire d'ivant
Cela n'est pas possible. La documentation mysql/mariadb indique explicitement qu'il n'est pas possible de se lier à plusieurs interfaces. Vous ne pouvez vous lier qu'à 0, 1 ou toutes les interfaces.
En conclusion, je n'ai PAS trouvé de moyen d'atteindre la base de données (uniquement localhost) sur l'hôte à partir d'un conteneur docker. Cela semble être un modèle très très courant, mais je ne sais pas comment le faire.