Wie verbinde ich mich innerhalb eines Docker-Containers mit dem localhost des Rechners?
Ich habe also ein Nginx, das in einem Docker-Container läuft, ich habe ein MySql, das auf localhost läuft, ich möchte mich mit dem MySql von meinem Nginx aus verbinden. Die MySql läuft auf localhost und nicht einen Port für die Außenwelt, so seine gebunden auf localhost, nicht auf die IP-Adresse der Maschine gebunden.
Gibt es eine Möglichkeit, eine Verbindung zu diesem MySql oder ein anderes Programm auf localhost aus diesem Docker-Container?
Diese Frage unterscheidet sich von "Wie erhalte ich die IP-Adresse des Docker-Hosts von innerhalb eines Docker-Containers" aufgrund der Tatsache, dass die IP-Adresse des Docker-Hosts die öffentliche IP oder die private IP im Netzwerk sein könnte, die von innerhalb des Docker-Containers erreichbar sein kann oder nicht (ich meine die öffentliche IP, wenn sie bei AWS oder so gehostet wird). Selbst wenn Sie die IP-Adresse des Docker-Hosts haben, bedeutet dies nicht, dass Sie eine Verbindung zum Docker-Host von innerhalb des Containers mit dieser IP-Adresse herstellen können, da Ihr Docker-Netzwerk Overlay, Host, Bridge, Macvlan, none usw. sein kann, was die Erreichbarkeit dieser IP-Adresse einschränkt.
Bearbeiten: Wenn Sie [Docker-for-mac] (https://docs.docker.com/docker-for-mac/networking/#there-is-no-docker0-bridge-on-macos#i-want-to-connect-from-a-container-to-a-service-on-the-host) oder [Docker-for-Windows] (https://docs.docker.com/docker-for-windows/networking/#there-is-no-docker0-bridge-on-windows#i-want-to-connect-from-a-container-to-a-service-on-the-host) 18.03+ verwenden, verbinden Sie sich einfach mit Ihrem mysql-Dienst, indem Sie den Host
host.docker.internal
verwenden.Ab Docker 18.09.3 funktioniert dies nicht auf Docker-for-Linux. Ein Fix wurde am 8. März 2019 eingereicht und wird hoffentlich in die Code-Basis integriert werden. Bis dahin besteht eine Abhilfe darin, einen Container wie in qoomons Antwort beschrieben zu verwenden.
TLDR
Verwenden Sie
--network="host"
in Ihremdocker run
Befehl, dann zeigt127.0.0.1
in Ihrem Docker Container auf Ihren Docker Host.Hinweis: Dieser Modus funktioniert nur mit Docker für Linux, gemäß der Dokumentation.
Hinweis zu Docker-Container-Netzwerkmodi
Docker bietet [verschiedene Netzwerkmodi] (https://docs.docker.com/engine/reference/run/#network-settings), wenn Container ausgeführt werden. Je nachdem, welchen Modus Sie wählen, würden Sie sich mit Ihrer MySQL-Datenbank, die auf dem Docker-Host läuft, unterschiedlich verbinden.
docker run --network="bridge" (Standard)
Docker erstellt standardmäßig eine Bridge mit dem Namen
docker0
. Sowohl der Docker-Host als auch die Docker-Container haben eine IP-Adresse auf dieser Bridge.Wenn Sie auf dem Docker-Host "sudo ip addr show docker0" eingeben, erhalten Sie eine Ausgabe, die wie folgt aussieht:
Hier hat mein Docker-Host also die IP-Adresse "172.17.42.1" auf der Netzwerkschnittstelle "docker0".
Starten Sie nun einen neuen Container und rufen Sie eine Shell auf:
docker run --rm -it ubuntu:trusty bash
und geben Sie innerhalb des Containersip addr show eth0
ein, um herauszufinden, wie seine Hauptnetzwerkschnittstelle eingerichtet ist:Hier hat mein Container die IP-Adresse
172.17.1.192
. Schauen Sie sich nun die Routing-Tabelle an:Die IP-Adresse des Docker-Hosts
172.17.42.1
ist also als Standard-Route eingestellt und von Ihrem Container aus erreichbar.docker run --network="host"
Alternativ können Sie einen Docker-Container mit [Netzwerkeinstellungen auf
host
gesetzt] (http://docs.docker.com/engine/reference/run/#network-host) ausführen. Ein solcher Container teilt sich den Netzwerkstack mit dem Docker-Host und aus Sicht des Containers bezieht sichlocalhost
(oder127.0.0.1
) auf den Docker-Host.Seien Sie sich bewusst, dass jeder Port, der in Ihrem Docker-Container geöffnet wird, auch auf dem Docker-Host geöffnet wird. Und das, ohne dass die Option
-p
oder-P
docker run
erforderlich ist.IP-Konfiguration auf meinem Docker-Host:
und von einem Docker-Container im Host-Modus:
Wie Sie sehen können, teilen sich sowohl der Docker-Host als auch der Docker-Container genau dieselbe Netzwerkschnittstelle und haben somit dieselbe IP-Adresse.
Verbindung zu MySQL von Containern aus
Bridge-Modus
Um von Containern im Bridge-Modus auf MySQL, das auf dem Docker-Host läuft, zuzugreifen, müssen Sie sicherstellen, dass der MySQL-Dienst auf der IP-Adresse
172.17.42.1
auf Verbindungen wartet.Stellen Sie dazu sicher, dass Sie entweder
bind-address = 172.17.42.1
oderbind-address = 0.0.0.0
in Ihrer MySQL-Konfigurationsdatei (my.cnf) haben.Wenn Sie eine Umgebungsvariable mit der IP-Adresse des Gateways setzen müssen, können Sie den folgenden Code in einem Container ausführen:
verwenden Sie dann in Ihrer Anwendung die Umgebungsvariable
DOCKER_HOST_IP
, um die Verbindung zu MySQL zu öffnen.Hinweis: Wenn Sie
bind-address = 0.0.0.0
verwenden, wird Ihr MySQL-Server an allen Netzwerkschnittstellen auf Verbindungen lauschen. Das bedeutet, dass Ihr MySQL-Server vom Internet aus erreicht werden kann; stellen Sie sicher, dass Sie Firewall-Regeln entsprechend einrichten.Anmerkung 2: Wenn Sie
bind-address = 172.17.42.1
verwenden, wird Ihr MySQL-Server nicht auf Verbindungen zu127.0.0.1
lauschen. Prozesse, die auf dem Docker-Host laufen und sich mit MySQL verbinden wollen, müssen die IP-Adresse "172.17.42.1" verwenden.Host-Modus
Um von Containern im Host-Modus auf MySQL zuzugreifen, die auf dem Docker-Host laufen, können Sie
bind-address = 127.0.0.1
in Ihrer MySQL-Konfiguration beibehalten, und alles, was Sie tun müssen, ist, sich von Ihren Containern aus mit127.0.0.1
zu verbinden:Anmerkung: Verwenden Sie
mysql -h 127.0.0.1
und nichtmysql -h localhost
; andernfalls würde der MySQL-Client versuchen, sich über einen Unix-Socket zu verbinden.Dies funktionierte bei mir auf einem NGINX/PHP-FPM-Stapel, ohne dass ich irgendeinen Code oder ein Netzwerk berührte, bei dem die Anwendung nur erwartet, dass sie sich mit "localhost" verbinden kann
Mount
mysqld.sock
vom Host in den Container.Finden Sie den Ort der Datei mysql.sock auf dem Host, auf dem mysql läuft:
netstat -ln | awk '/mysql(.*)?\.sock/ { print $9 }'
Hängen Sie diese Datei dort ein, wo sie im Docker erwartet wird:
docker run -v /hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock
Mögliche Speicherorte von mysqld.sock:
Ich bin mit der Antwort von Thomasleveil nicht einverstanden.
Wenn Sie mysql an 172.17.42.1 binden, verhindern Sie, dass andere Programme, die die Datenbank auf dem Host verwenden, sie erreichen können. Dies wird nur funktionieren, wenn alle Ihre Datenbankbenutzer gedockt sind.
Wenn Sie mysql an 0.0.0.0 binden, öffnen Sie die Datenbank für die Außenwelt, was nicht nur eine sehr schlechte Sache ist, sondern auch dem widerspricht, was der Autor der ursprünglichen Frage erreichen möchte. Er sagt ausdrücklich: "MySql läuft auf localhost und gibt keinen Port für die Außenwelt frei, also ist es an localhost gebunden.
Um auf den Kommentar von ivant zu antworten
Das ist nicht möglich. Die mysql/mariadb-Dokumentation sagt ausdrücklich, dass es nicht möglich ist, an mehrere Schnittstellen zu binden. Sie können nur an 0, 1 oder an alle Schnittstellen binden.
Abschließend kann ich sagen, dass ich KEINE Möglichkeit gefunden habe, die (nur localhost) Datenbank auf dem Host von einem Docker-Container aus zu erreichen. Das scheint auf jeden Fall ein sehr gängiges Muster zu sein, aber ich weiß nicht, wie man es macht.