Ich habe einen Docker-Container mit Jenkins. Als Teil des Erstellungsprozesses muss ich auf einen Webserver zugreifen, der lokal auf dem Hostcomputer ausgeführt wird. Gibt es eine Möglichkeit, den Host-Webserver (der für die Ausführung an einem Port konfiguriert werden kann) für den Jenkins-Container verfügbar zu machen?
EDIT: Ich verwende Docker nativ auf einem Linux-Computer.
AKTUALISIEREN:
Zusätzlich zur Antwort von @larsks unten, um die IP-Adresse der Host-IP vom Host-Computer zu erhalten, gehe ich wie folgt vor:
ip addr show docker0 | grep -Po 'inet \K[\d.]+'
docker
docker-container
Tri Nguyen
quelle
quelle
curl: (7) Failed to connect to 172.17.1.78 port 7000: No route to host
Antworten:
Wenn Sie Docker nativ unter Linux ausführen, können Sie über die IP-Adresse der
docker0
Schnittstelle auf Hostdienste zugreifen . Innerhalb des Containers ist dies Ihre Standardroute.Zum Beispiel auf meinem System:
Und in einem Container:
Es ist ziemlich einfach, diese IP-Adresse mit einem einfachen Shell-Skript zu extrahieren:
Möglicherweise müssen Sie die
iptables
Regeln auf Ihrem Host ändern , um Verbindungen von Docker-Containern zuzulassen. So etwas reicht aus:Dies würde den Zugriff auf alle Ports auf dem Host von Docker-Containern aus ermöglichen. Beachten Sie, dass:
iptables-Regeln sind geordnet, und diese Regel kann das Richtige tun oder auch nicht, je nachdem, welche anderen Regeln davor stehen.
Sie können nur auf Hostdienste zugreifen, die entweder (a) abhören
INADDR_ANY
(auch bekannt als 0.0.0.0) oder diedocker0
Schnittstelle explizit abhören .quelle
docker.for.mac.localhost
anstelle vonlocalhost
oder127.0.0.1
. Hier ist doc .Für MacOS und Windows
Docker v 18.03 und höher (seit dem 21. März 2018)
Verwenden Sie Ihre interne IP-Adresse oder stellen Sie eine Verbindung mit dem speziellen DNS-Namen her,
host.docker.internal
der in die vom Host verwendete interne IP-Adresse aufgelöst wird.Linux-Unterstützung ausstehend https://github.com/docker/for-linux/issues/264
MacOS mit früheren Versionen von Docker
Docker für Mac v 17.12 bis v 18.02
Wie oben, aber
docker.for.mac.host.internal
stattdessen verwenden.Docker für Mac v 17.06 bis v 17.11
Wie oben, aber
docker.for.mac.localhost
stattdessen verwenden.Docker für Mac 17.05 und niedriger
Um vom Docker-Container aus auf den Host-Computer zuzugreifen, müssen Sie einen IP-Alias an Ihre Netzwerkschnittstelle anhängen. Sie können jede gewünschte IP-Adresse binden. Stellen Sie jedoch sicher, dass Sie sie nicht für andere Zwecke verwenden.
sudo ifconfig lo0 alias 123.123.123.123/24
Stellen Sie dann sicher, dass Ihr Server die oben genannte IP abhört oder
0.0.0.0
. Wenn localhost abgehört127.0.0.1
wird, wird die Verbindung nicht akzeptiert.Dann zeigen Sie einfach Ihren Docker-Container auf diese IP und Sie können auf den Host-Computer zugreifen!
Zum Testen können Sie so etwas wie
curl -X GET 123.123.123.123:3000
im Container ausführen .Der Alias wird bei jedem Neustart zurückgesetzt. Erstellen Sie daher bei Bedarf ein Startskript.
Lösung und weitere Dokumentation hier: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
quelle
docker.for.mac.localhost
herzustellen, der in die vom Host verwendete interne IP-Adresse aufgelöst wird! ... ich habe es getestet und es funktioniert tatsächlich! :)ip route show | awk '/default/ {print $3}'
eine IP gebe unddocker.for.mac.localhost
eine andere.host.docker.internal
docs.docker.com/docker-for-mac/networking/…host.docker.internal
im Docker-Container und die Konfiguration127.0.0.1 host.docker.internal
in der Hosts- Datei.Verwenden Sie
--net="host"
in Ihremdocker run
Befehl, dann zeigtlocalhost
in Ihrem Docker-Container auf Ihren Docker-Host.quelle
network_mode: "host"
Lösung mit Docker-Compose: Für den Zugriff auf den hostbasierten Dienst können Sie den
network_mode
Parameter https://docs.docker.com/compose/compose-file/#network_mode verwendenEDIT 2020-04-27: Empfohlen nur zur Verwendung in lokalen Entwicklungsumgebungen.
quelle
Derzeit ist der einfachste Weg, dies unter Mac und Windows zu tun, die Verwendung des Hosts
host.docker.internal
, der in die IP-Adresse des Hostcomputers aufgelöst wird. Leider funktioniert es noch nicht unter Linux (Stand April 2018).quelle
Ich habe einen Docker-Container erstellt, um genau das zu tun: https://github.com/qoomon/docker-host
Sie können dann einfach den Containernamen dns verwenden, um auf das Hostsystem zuzugreifen, z
curl http://dockerhost:9200
quelle
Wir haben festgestellt, dass eine einfachere Lösung für all diesen Netzwerk-Junk darin besteht, nur den Domain-Socket für den Dienst zu verwenden. Wenn Sie trotzdem versuchen, eine Verbindung zum Host herzustellen, stellen Sie den Socket einfach als Volume bereit, und schon können Sie loslegen. Für postgresql war dies so einfach wie:
Dann richten wir einfach unsere Datenbankverbindung ein, um den Socket anstelle des Netzwerks zu verwenden. Im wahrsten Sinne des Wortes so einfach.
quelle
Ich habe die verschiedenen Lösungen untersucht und finde, dass dies die am wenigsten hackige Lösung ist:
extra_hosts
Direktive ein.Der einzige Nachteil ist, dass Sie bei mehreren Netzwerken oder Projekten sicherstellen müssen, dass deren IP-Adressbereich nicht in Konflikt steht.
Hier ist ein Docker Compose-Beispiel:
Sie können dann über den Hostnamen "dockerhost" aus dem Container heraus auf Ports auf dem Host zugreifen.
quelle
Bei Linux-Systemen können Sie ab der Hauptversion
20.04
jetzt auch über mit dem Host kommunizierenhost.docker.internal
. Dies funktioniert nicht automatisch , Sie müssen jedoch das folgende Ausführungsflag angeben:Sehen
quelle
Sie können auf zwei Arten auf den lokalen Webserver zugreifen, der auf Ihrem Host-Computer ausgeführt wird.
Ansatz 1 mit öffentlicher IP
Verwenden Sie die öffentliche IP-Adresse des Hostcomputers, um auf den Webserver im Docker-Container von Jenkins zuzugreifen.
Ansatz 2 mit dem Host-Netzwerk
Verwenden Sie "--net host", um den Jenkins-Docker-Container zum Netzwerkstapel des Hosts hinzuzufügen. Container, die auf dem Host-Stack bereitgestellt werden, haben vollständigen Zugriff auf die Host-Schnittstelle. Sie können im Docker-Container mit einer privaten IP-Adresse des Host-Computers auf den lokalen Webserver zugreifen.
Starten Sie einen Container mit dem Host-Netzwerk
Eg: docker run --net host -it ubuntu
und führen Sie ihn aus,ifconfig
um alle verfügbaren Netzwerk-IP-Adressen aufzulisten, die über den Docker-Container erreichbar sind.Beispiel: Ich habe einen Nginx-Server auf meinem lokalen Host-Computer gestartet und kann über den Ubuntu-Docker-Container auf die URLs der Nginx-Website zugreifen.
docker run --net host -it ubuntu
Zugriff auf den Nginx-Webserver (der auf dem lokalen Host-Computer ausgeführt wird) über den Ubuntu-Docker-Container mit der IP-Adresse des privaten Netzwerks.
quelle
Für die
docker-compose
Verwendung von Bridge-Netzwerken zum Erstellen eines privaten Netzwerks zwischen Containerndocker0
funktioniert die akzeptierte Lösung nicht, da die Ausgangsschnittstelle aus den Containern nicht,docker0
sondern eine zufällig generierte Schnittstellen-ID ist, z.Leider ist diese zufällige ID nicht vorhersehbar und ändert sich jedes Mal, wenn compose das Netzwerk neu erstellen muss (z. B. bei einem Neustart des Hosts). Meine Lösung hierfür besteht darin, das private Netzwerk in einem bekannten Subnetz zu erstellen und so zu konfigurieren
iptables
, dass dieser Bereich akzeptiert wird:Datei-Snippet verfassen:
Sie können das Subnetz ändern, wenn Ihre Umgebung dies erfordert. Ich habe willkürlich ausgewählt,
192.168.32.0/20
indem ich verwendet habe, umdocker network inspect
zu sehen, was standardmäßig erstellt wurde.iptables
Auf dem Host so konfigurieren , dass das private Subnetz als Quelle zugelassen wird:Dies ist die einfachste mögliche
iptables
Regel. Möglicherweise möchten Sie weitere Einschränkungen hinzufügen, z. B. nach Zielport. Vergessen Sie nicht, Ihre iptables-Regeln beizubehalten, wenn Sie froh sind, dass sie funktionieren.Dieser Ansatz hat den Vorteil, dass er wiederholbar und daher automatisierbar ist. Ich benutze ansible das
template
Modul meine compose Datei mit Variablensubstitution zu implementieren und dann die Verwendungiptables
undshell
Module zu konfigurieren und die Firewall - Regeln bestehen, respectively.quelle
iptables -A INPUT -i docker0 -j ACCEPT
, aber das hat mir nicht geholfen, während dieiptables -I INPUT 1 -s 192.168.32.0/20 -j ACCEPT
hier vorgeschlagenen mein Problem gelöst haben.Dies ist eine alte Frage und hatte viele Antworten, aber keine davon passt gut genug zu meinem Kontext. In meinem Fall sind die Container sehr schlank und enthalten keine der Netzwerk-Tools, die zum Extrahieren der IP-Adresse des Hosts aus dem Container erforderlich sind.
Die Verwendung des
--net="host"
Ansatzes ist auch ein sehr grober Ansatz, der nicht anwendbar ist, wenn eine gut isolierte Netzwerkkonfiguration mit mehreren Containern gewünscht wird.Mein Ansatz besteht also darin, die Hostadresse auf der Hostseite zu extrahieren und sie dann mit dem folgenden
--add-host
Parameter an den Container zu übergeben :Oder speichern Sie die IP-Adresse des Hosts in einer Umgebungsvariablen und verwenden Sie die Variable später:
Anschließend
docker-host
wird das zur Hosts-Datei des Containers hinzugefügt, und Sie können es in Ihren Datenbankverbindungszeichenfolgen oder API-URLs verwenden.quelle
Wenn Sie zwei Docker-Images "bereits" erstellt haben und zwei Container für die Kommunikation untereinander platzieren möchten.
Dazu können Sie bequem jeden Container mit seinem eigenen Namen ausführen und das Flag --link verwenden, um die Kommunikation zwischen ihnen zu ermöglichen. Sie erhalten dies jedoch nicht während des Docker-Builds.
Wenn Sie sich in einem Szenario wie mir befinden und es Ihnen gehört
Das bricht, wenn Sie es versuchen
und Sie bleiben bei "curl / wget" hängen und geben keine "Route zum Host" zurück.
Der Grund ist die vom Docker eingerichtete Sicherheit, die standardmäßig die Kommunikation von einem Container zum Host oder zu anderen auf Ihrem Host ausgeführten Containern verbietet. Das war ziemlich überraschend für mich, ich muss sagen, Sie würden erwarten, dass das Echosystem von Docker-Maschinen, die auf einem lokalen Computer laufen, ohne allzu große Hürden fehlerfrei aufeinander zugreifen kann.
Die Erklärung hierfür wird in der folgenden Dokumentation ausführlich beschrieben.
http://www.dedoimedo.com/computers/docker-networking.html
Es werden zwei schnelle Problemumgehungen angegeben, die Ihnen helfen, sich zu bewegen, indem Sie die Netzwerksicherheit verringern.
Hoffe, diese Informationen helfen Ihnen.
quelle
--link
ist jetzt veraltetFür mich (Windows 10, Docker Engine v19.03.8) war es eine Mischung aus https://stackoverflow.com/a/43541732/7924573 und https://stackoverflow.com/a/50866007/7924573 .
z. B.: LOGGER_URL = " http: //host.docker.internal: 8085 / log "
version: '3.7' services: server: build: . ports: - "5000:5000" network_mode: bridge
oder alternativ: Verwenden--net="bridge"
Sie, wenn Sie Docker-Compose nicht verwenden (ähnlich wie https://stackoverflow.com/a/48806927/7924573 ).Wie in früheren Antworten ausgeführt: Dies sollte nur in einer lokalen Entwicklungsumgebung verwendet werden .
Weitere Informationen finden Sie unter: https://docs.docker.com/compose/compose-file/#network_mode und https://docs.docker.com/docker-for-windows/networking/#use-cases-and-workarounds
quelle