webentwicklung-frage-antwort-db.com.de

Zugriff auf den Host-Port über Docker-Container

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.]+'
142
Tri Nguyen

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.

121
larsks

Für Mac OS und Windows

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

MacOS mit früheren Versionen von Docker

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

161
Janne Annala

Verwenden Sie --net="Host" in Ihrem docker run-Befehl, dann zeigt localhost in Ihrem Docker-Container auf Ihren Docker-Host.

21
samthebest

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
7
vovan

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). 

6
Tomáš Fejfar

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

2
qoomon

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.

1
mlissner

Sie können auf zwei Arten auf den lokalen Webserver zugreifen, der auf Ihrem Host-Computer ausgeführt wird.

  1. Ansatz 1 mit öffentlicher IP

    Verwenden Sie die öffentliche IP-Adresse des Host-Computers, um auf den Webserver im Jenkins-Docker-Container zuzugreifen.

  2. 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
0
sreenivasar

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.

0
99Sono

Ich habe die verschiedenen Lösungen ausprobiert und finde die am wenigsten gehackte Lösung:

  1. Definieren Sie eine statische IP-Adresse für die Bridge-Gateway-IP.
  2. Fügen Sie die Gateway-IP als zusätzlichen Eintrag in der Hosts-Datei hinzu.

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.

0
bcoughlan