Ich habe einen Docker-Container mit Jenkins. Als Teil des Erstellungsprozesses muss ich auf einen Webserver zugreifen, der lokal auf der Hostmaschine ausgeführt wird. Gibt es eine Möglichkeit, den Host-Webserver (der für die Ausführung auf einem Port konfiguriert werden kann) für den Jenkins-Container verfügbar zu machen?
EDIT: Ich lade Docker nativ auf einem Linux-Rechner.
AKTUALISIEREN:
Um die IP-Adresse der Host-IP von der Host-Maschine zu erhalten, mache ich zusätzlich zu der Antwort von @larsks Folgendes:
ip addr show docker0 | grep -Po 'inet \K[\d.]+'
Wenn Sie Docker nativ unter Linux ausführen, können Sie über die IP-Adresse der docker0
-Schnittstelle auf Host-Dienste zugreifen. Dies ist Ihre Standardroute innerhalb des Containers.
Zum Beispiel auf meinem System:
$ ip addr show docker0
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::f4d2:49ff:fedd:28a0/64 scope link
valid_lft forever preferred_lft forever
Und in einem Container:
# ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 src 172.17.0.4
Es ist ziemlich einfach, diese IP-Adresse mit einem einfachen Shell-Skript zu extrahieren.
#!/bin/sh
hostip=$(ip route show | awk '/default/ {print $3}')
echo $hostip
Möglicherweise müssen Sie die iptables
-Regeln auf Ihrem Host ändern, um Verbindungen von Docker-Containern zu ermöglichen. So etwas macht den Trick:
# iptables -A INPUT -i docker0 -j ACCEPT
Dies würde den Zugriff auf alle Ports auf dem Host über Docker-Container ermöglichen. Beachten Sie, dass:
iptables-Regeln werden geordnet, und diese Regel kann oder kann nicht das Richtige .__ tun, je nachdem, welche anderen Regeln vor ihr stehen.
sie können nur auf Host-Dienste zugreifen, die entweder (a) auf INADDR_ANY
(aka 0.0.0.0) oder explizit auf der docker0
-Schnittstelle hören.
Docker v 18.03 und höher (seit 21. März 2018)
Verwenden Sie Ihre interne IP-Adresse oder stellen Sie eine Verbindung mit dem speziellen DNS-Namen Host.docker.internal
her, der in die vom Host verwendete interne IP-Adresse aufgelöst wird.
Linux-Unterstützung ausstehend https://github.com/docker/for-linux/issues/264
Docker für Mac v 17.12 bis v 18.02
Wie oben, aber stattdessen docker.for.mac.Host.internal
verwenden.
Docker für Mac v 17.06 bis v 17.11
Wie oben, aber stattdessen docker.for.mac.localhost
verwenden.
Docker für Mac 17.05 und darunter
Um vom Docker-Container aus auf den Host-Computer zuzugreifen, müssen Sie einen IP-Alias an Ihre Netzwerkschnittstelle anhängen. Sie können die 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 erwähnte IP-Adresse oder 0.0.0.0
abhört. Wenn er localhost 127.0.0.1
hört, akzeptiert er die Verbindung nicht.
Dann richten Sie Ihren Docker-Container einfach auf diese IP und Sie können auf die Host-Maschine zugreifen!
Zum Testen können Sie etwas wie curl -X GET 123.123.123.123:3000
im Container ausführen.
Der Alias wird bei jedem Neustart zurückgesetzt. Erstellen Sie gegebenenfalls ein Startskript.
Lösung und weitere Dokumentation hier: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Verwenden Sie --net="Host"
in Ihrem docker run
-Befehl, dann zeigt localhost
in Ihrem Docker-Container auf Ihren Docker-Host.
Lösung mit Docker-Compose: Für den Zugriff auf den Host-basierten Dienst können Sie network_mode
parameter https://docs.docker.com/compose/compose-file/#network_mode verwenden.
version: '3'
services:
jenkins:
network_mode: Host
Derzeit ist dies auf Mac und Windows die einfachste Möglichkeit, Host Host.docker.internal
zu verwenden, der in die IP-Adresse des Host-Computers aufgelöst wird. Leider funktioniert es noch nicht unter Linux (Stand April 2018).
Ich habe einen Docker-Container für genau das erstellt https://github.com/qoomon/docker-Host
Sie können dann einfach Containername DNs verwenden, um auf das Host-System zuzugreifen, z. curl http://dockerhost:9200
Wir haben festgestellt, dass eine einfachere Lösung für all diesen Netzwerkmüll darin besteht, nur den Domain-Socket für den Dienst zu verwenden. Wenn Sie trotzdem versuchen, eine Verbindung zum Host herzustellen, mounten Sie den Socket einfach als Volume, und schon sind Sie unterwegs. Für postgresql war dies so einfach wie:
docker run -v /var/run/postgresql:/var/run/postgresql
Dann richten wir einfach unsere Datenbankverbindung so ein, dass der Socket anstelle des Netzwerks verwendet wird. Buchstäblich so einfach.
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 Host-Computers, um auf den Webserver im Jenkins-Docker-Container 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.
NETWORK ID NAME DRIVER SCOPE
b3554ea51ca3 bridge bridge local
2f0d6d6fdd88 Host Host local
b9c2a4bc23b2 none null local
Starten Sie einen Container mit dem Host-Netzwerk Eg: docker run --net Host -it ubuntu
und führen Sie ifconfig
aus, um alle verfügbaren Netzwerk-IP-Adressen aufzulisten, die vom Docker-Container aus erreichbar sind.
ZB: Ich habe auf meinem lokalen Host-Rechner einen Nginx-Server gestartet und kann über den Ubuntu Docker-Container auf die URLs der Nginx-Website zugreifen.
docker run --net Host -it ubuntu
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a604f7af5e36 ubuntu "/bin/bash" 22 seconds ago Up 20 seconds ubuntu_server
Zugriff auf den Nginx-Webserver (auf dem lokalen Host-Computer) über den Ubuntu-Docker-Container mit privater Netzwerk-IP-Adresse.
[email protected]:/# curl 192.168.x.x -I
HTTP/1.1 200 OK
Server: nginx/1.15.10
Date: Tue, 09 Apr 2019 05:12:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Mar 2019 14:04:38 GMT
Connection: keep-alive
ETag: "5c9a3176-264"
Accept-Ranges: bytes
Wenn Sie zwei Docker-Images "bereits" erstellt haben und zwei Container für die Kommunikation miteinander einrichten möchten.
Dazu können Sie jeden Container bequem 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 ich befinden, und es ist Ihr
docker build -t "centos7/someApp" someApp/
Das bricht, wenn Sie es versuchen
curl http://172.17.0.1:localPort/fileIWouldLikeToDownload.tar.gz > dump.tar.gz
und du bleibst bei "curl/wget" hängen und kehrst keine "Route zum Host" zurück.
Der Grund ist die Sicherheit, die von Docker festgelegt wird, die standardmäßig die Kommunikation von einem Container zum Host oder zu anderen Containern, die auf Ihrem Host ausgeführt werden, verbietet .. Dies war für mich ziemlich überraschend, ich muss sagen, Sie würden das Echosystem erwarten von Docker-Rechnern, die auf einem lokalen Rechner ausgeführt werden, kann der einwandfreie Zugriff aufeinander ohne zu große Hürden erfolgen.
Die Erklärung dafür ist in der folgenden Dokumentation ausführlich beschrieben.
http://www.dedoimedo.com/computers/docker-networking.html
Es gibt zwei schnelle Problemumgehungen, die Ihnen helfen, sich in Bewegung zu setzen, indem Sie die Netzwerksicherheit verringern.
Die einfachste Alternative ist, die Firewall einfach auszuschalten - oder alles zuzulassen. Dies bedeutet, dass der erforderliche Befehl ausgeführt wird, der systemctl stop firewalld, iptables -F oder ein gleichwertiger Befehl sein kann.
Hoffen Sie, dass diese Informationen Ihnen helfen.
Ich habe die verschiedenen Lösungen ausprobiert und finde die am wenigsten gehackte Lösung:
Der einzige Nachteil ist, wenn Sie über mehrere Netzwerke oder Projekte verfügen, die dies tun, müssen Sie sicherstellen, dass der IP-Adressbereich nicht in Konflikt steht.
Hier ist ein Docker Compose-Beispiel:
version: '2.3'
services:
redis:
image: "redis"
extra_hosts:
- "dockerhost:172.20.0.1"
networks:
default:
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
Sie können dann innerhalb des Containers mit dem Hostnamen "dockerhost" auf die Ports des Hosts zugreifen.