Wie der Titel sagt. Ich muss in der Lage sein, die IP-Adresse der Docker-Hosts und der Portmaps vom Host an den Container abzurufen, und zwar innerhalb des Containers.
/sbin/ip route|awk '/default/ { print $3 }'
Wie @MichaelNeale festgestellt hat, ist es nicht sinnvoll, diese Methode in Dockerfile
zu verwenden (es sei denn, wir benötigen diese IP nur zur Erstellungszeit), da diese IP während der Erstellungszeit fest codiert wird.
Bei Docker für Mac können Sie ab Version 18.03 Host.docker.internal
als IP des Hosts verwenden.
Beachten Sie, wie in der Dokumentation : "Dies ist zu Entwicklungszwecken und funktioniert nicht in einer Produktionsumgebung außerhalb von Docker for Mac." Dies liegt daran, dass in Docker für Mac "keine Docker0-Schnittstelle auf dem Host angezeigt wird. Diese Schnittstelle befindet sich tatsächlich innerhalb der virtuellen Maschine."
Dies ist ein Update von docker.for.mac.localhost
, verfügbar seit Version 17.06, und docker.for.mac.Host.internal
, verfügbar seit Version 17.12, was möglicherweise noch funktioniert.
Zum Beispiel habe ich Umgebungsvariablen auf meinem Host gesetzt:
MONGO_SERVER=Host.docker.internal
In meiner docker-compose.yml
-Datei habe ich Folgendes:
version: '3'
services:
api:
build: ./api
volumes:
- ./api:/usr/src/app:ro
ports:
- "8000"
environment:
- MONGO_SERVER
command: /usr/local/bin/gunicorn -c /usr/src/app/gunicorn_config.py -w 1 -b :8000 wsgi
Update: Bei Docker für Mac können Sie ab Version 18.03 Host.docker.internal als IP des Hosts verwenden. Siehe allanberrys Antwort . Bei früheren Versionen von Docker für Mac kann die folgende Antwort dennoch nützlich sein:
Bei Docker für Mac ist die Brücke docker0
nicht vorhanden, sodass andere Antworten hier möglicherweise nicht funktionieren. Der gesamte ausgehende Datenverkehr wird jedoch über den übergeordneten Host geleitet. Wenn Sie also versuchen, eine Verbindung zu einer IP-Adresse herzustellen, die er als sich selbst erkennt (und der Docker-Container nicht denkt, dass er sich selbst ist), sollten Sie eine Verbindung herstellen können. Zum Beispiel, wenn Sie dies vom übergeordneten Computer ausführen:
ipconfig getifaddr en0
Dies sollte Ihnen die IP Ihres Mac in seinem aktuellen Netzwerk anzeigen und Ihr Docker-Container sollte auch in der Lage sein, eine Verbindung zu dieser Adresse herzustellen. Dies ist natürlich schmerzhaft, wenn sich diese IP-Adresse ändert. Sie können Ihrem Mac jedoch eine benutzerdefinierte Loopback-IP hinzufügen, die der Container nicht für sich selbst hält, indem Sie auf dem übergeordneten Computer Folgendes tun:
Sudo ifconfig lo0 alias 192.168.46.49
Sie können die Verbindung dann innerhalb des Docker-Containers mit Telnet testen. In meinem Fall wollte ich eine Verbindung zu einem Remote-Xdebug-Server herstellen:
telnet 192.168.46.49 9000
Wenn nun Datenverkehr in Ihren Mac kommt, der für 192.168.46.49 adressiert ist (und der gesamte Datenverkehr, der Ihren Container verlässt, über Ihren Mac geleitet wird), geht Ihr Mac davon aus, dass die IP-Adresse selbst ist. Wenn Sie mit der Verwendung dieser IP-Adresse fertig sind, können Sie den Loopback-Alias wie folgt entfernen:
Sudo ifconfig lo0 -alias 192.168.46.49
Seien Sie vorsichtig, wenn der Docker-Container keinen Datenverkehr an den übergeordneten Host sendet, wenn er der Meinung ist, dass das Ziel des Datenverkehrs sich selbst befindet. Überprüfen Sie daher die Loopback-Schnittstelle im Container, wenn Sie Probleme haben:
Sudo ip addr show lo
In meinem Fall zeigte dies inet 127.0.0.1/8
an, was bedeutet, dass ich keine IP-Adressen im 127.*
-Bereich verwenden konnte. Deshalb habe ich im obigen Beispiel 192.168.*
verwendet. Stellen Sie sicher, dass die von Ihnen verwendete IP-Adresse keinen Konflikt mit Ihrem eigenen Netzwerk verursacht.
Für diejenigen, die Docker in AWS ausführen, sind die Instanz-Metadaten für den Host weiterhin im Container verfügbar.
curl http://169.254.169.254/latest/meta-data/local-ipv4
Zum Beispiel:
$ docker run Alpine /bin/sh -c "apk update ; apk add curl ; curl -s http://169.254.169.254/latest/meta-data/local-ipv4 ; echo"
fetch http://dl-cdn.alpinelinux.org/Alpine/v3.3/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/Alpine/v3.3/community/x86_64/APKINDEX.tar.gz
v3.3.1-119-gb247c0a [http://dl-cdn.alpinelinux.org/Alpine/v3.3/main]
v3.3.1-59-g48b0368 [http://dl-cdn.alpinelinux.org/Alpine/v3.3/community]
OK: 5855 distinct packages available
(1/4) Installing openssl (1.0.2g-r0)
(2/4) Installing ca-certificates (20160104-r2)
(3/4) Installing libssh2 (1.6.0-r1)
(4/4) Installing curl (7.47.0-r0)
Executing busybox-1.24.1-r7.trigger
Executing ca-certificates-20160104-r2.trigger
OK: 7 MiB in 15 packages
172.31.27.238
$ ifconfig eth0 | grep -oP 'inet addr:\K\S+'
172.31.27.238
Die einzige Möglichkeit besteht darin, die Host-Informationen als Umgebung zu übergeben, wenn Sie einen Container erstellen
run --env <key>=<value>
Der --add-Host
könnte eine sauberere Lösung sein (aber ohne den Port-Teil kann nur der Host mit dieser Lösung behandelt werden). Führen Sie also in Ihrem docker run
-Befehl Folgendes aus:
docker run --add-Host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
Docker für Mac Ich möchte eine Verbindung von einem Container zu einem Dienst auf dem Host herstellen
Der Host hat eine sich ändernde IP-Adresse (oder keine, wenn Sie keinen Netzwerkzugriff haben). Ab dem 18.03. Empfehlen wir, eine Verbindung mit dem speziellen DNS-Namen Host.docker.internal herzustellen, der in die vom Host verwendete interne IP-Adresse aufgelöst wird.
Das Gateway ist auch als gateway.docker.internal . https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds erreichbar.
Wenn Sie die docker-Remote-API (z. B. über -H
tcp://0.0.0.0:4243
) aktiviert haben und den Hostnamen oder die IP-Adresse des Host-Computers kennen, kann dies mit einer Menge bash erfolgen.
In der bashrc
des Benutzers meines Containers:
export hostIP=$(ip r | awk '/default/{print $3}')
export containerID=$(awk -F/ '/docker/{print $NF;exit;}' /proc/self/cgroup)
export proxyPort=$(
curl -s http://$hostIP:4243/containers/$containerID/json |
node -pe 'JSON.parse(require("fs").readFileSync("/dev/stdin").toString()).NetworkSettings.Ports["DESIRED_PORT/tcp"][0].HostPort'
)
In der zweiten Zeile wird die Container-ID aus Ihrer lokalen /proc/self/cgroup
-Datei abgerufen.
Die dritte Zeile rollt zum Host-Computer (vorausgesetzt, Sie verwenden 4243 als Port des Dockers) und analysiert dann den zurückgegebenen JSON-Knoten mit dem DESIRED_PORT
.
Wenn Sie eine echte IP
-Adresse (keine Brücke IP
) auf Windows
haben möchten und Docker 18.03
(oder neuer) haben, gehen Sie folgendermaßen vor:
Führen Sie auf dem Host bash auf dem Container aus, auf dem der Image-Name nginx
ist (funktioniert mit Alpine Linux distribution
):
docker run -it nginx /bin/ash
Dann in den Container laufen lassen
/ # nslookup Host.docker.internal
Name: Host.docker.internal
Address 1: 192.168.65.2
192.168.65.2
ist die IP des Hosts - nicht die Bridge-IP wie in spinus
akzeptierte Antwort.
Ich verwende hier Host.docker.internal :
Der Host hat eine sich ändernde IP-Adresse (oder keine, wenn Sie keinen Netzwerkzugriff haben). Ab dem 18.03. Empfehlen wir, eine Verbindung mit dem speziellen DNS-Namen Host.docker.internal herzustellen, der in die vom Host verwendete interne IP-Adresse aufgelöst wird. Dies dient zu Entwicklungszwecken und funktioniert nicht in einer Produktionsumgebung außerhalb von Docker für Windows.
Hier ist eine weitere Option für diejenigen, die Docker in AWS ausführen. Diese Option vermeidet die Verwendung von apk zum Hinzufügen des curl-Pakets und spart die kostbaren 7 MB Speicherplatz. Verwenden Sie das eingebaute wget (Teil der monolithischen BusyBox-Binärdatei):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
In Linux können Sie laufen
Host_IP=`hostname -I | awk '{print $1}'`
In macOS ist Ihr Host-Computer nicht der Docker-Host. Docker installiert sein Host-Betriebssystem in VirtualBox.
Host_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
Die Standard-Best-Practice für die meisten Apps, die dies automatisch tun möchten, lautet: Sie tun es nicht. Stattdessen muss die Person, die den Container ausführt, einen externen Hostnamen/eine externe IP-Adresse als Konfiguration eingeben, z. als Umgebungsvariable oder Konfigurationsdatei. Wenn Sie dem Benutzer erlauben, dies zu injizieren, erhalten Sie das tragbarste Design.
Warum sollte das so schwierig sein? Da Container die Anwendung standardmäßig von der Host-Umgebung isolieren. Das Netzwerk ist standardmäßig nur für diesen Container mit einem Namespace versehen, und Details des Hosts sind vor dem Prozess geschützt, der im Container ausgeführt wird und möglicherweise nicht vollständig vertrauenswürdig ist.
Abhängig von Ihrer spezifischen Situation gibt es verschiedene Optionen:
Wenn Ihr Container mit Host-Netzwerk ausgeführt wird, können Sie die Routing-Tabelle auf dem Host direkt einsehen, um die Standardroute anzuzeigen, z.
ip r s 0/0 | awk '{print $3}
Ein Beispiel, das dies mit einem Host-Netzwerk in einem Container zeigt, sieht folgendermaßen aus:
docker run --rm --net Host busybox /bin/sh -c "ip r s 0/0 | awk '{print \$3}'"
Bei einigen Versionen von Docker Desktop wurde ein DNS-Eintrag eingefügt:
getent hosts Host.docker.internal | awk '{print $1}'
Wenn Sie in einer Cloud-Umgebung ausgeführt werden, können Sie den Metadatendienst vom Cloud-Anbieter überprüfen, z. die AWS ein:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Wenn Sie Ihre externe/Internet-Adresse möchten, können Sie einen Remote-Service wie folgt abfragen:
curl ifconfig.co
Jedes davon hat Einschränkungen und funktioniert nur in bestimmten Szenarien. Am portabelsten ist es immer noch, Ihren Container mit der als Konfiguration eingegebenen IP-Adresse auszuführen, z. Hier ist eine Option, die den früheren Befehl ip
auf dem Host ausführt und als Umgebungsvariable einfügt:
docker run --rm -e Host_IP=$(ip r s 0/0 | awk '{print $3}') busybox printenv Host_IP
Ich habe Ubuntu 16.03. Für mich
docker run --add-Host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
funktioniert NICHT (falsche ip generiert)
Meine Arbeitslösung war:
docker run --add-Host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Dies ist eine minimalistische Implementierung in Node.js für Benutzer, die den Host auf AWS EC2-Instanzen ausführen. EC2-Metadateninstanz
const cp = require('child_process');
const ec2 = function (callback) {
const URL = 'http://169.254.169.254/latest/meta-data/local-ipv4';
// we make it silent and timeout to 1 sec
const args = [URL, '-s', '--max-time', '1'];
const opts = {};
cp.execFile('curl', args, opts, (error, stdout) => {
if (error) return callback(new Error('ec2 ip error'));
else return callback(null, stdout);
})
.on('error', (error) => callback(new Error('ec2 ip error')));
}//ec2
und verwendet als
ec2(function(err, ip) {
if(err) console.log(err)
else console.log(ip);
})
So mache ich es. In diesem Fall fügt es einen Hosteintrag in/etc/hosts innerhalb des Docker-Image, das Taurus-Host zeigt, der lokalen IP-Adresse des Computers hinzu:
TAURUS_Host=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-Host "taurus-Host:${TAURUS_Host}" ...
Anschließend kann das Skript aus dem Docker-Container den Hostnamen taurus-Host verwenden, um zu meinem lokalen Computer zu gelangen, der den Docker-Container hostet.
Die von mir verwendete Lösung basiert auf einem "Server", der die externe Adresse des Docker-Hosts zurückgibt, wenn er eine http-Anfrage erhält.
Auf dem "Server":
1) Starten Sie jwilder/nginx-proxy
# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
2) Starten Sie den ipify-Container
# docker run -e VIRTUAL_Host=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0
Wenn nun ein Container eine http-Anforderung an den Server sendet, z.
# curl http://<external server name/address>:<external server port>
die IP-Adresse des Docker Host wird von ipify über den HTTP-Header "X-Forwarded-For" zurückgegeben.
Beispiel (ipify-Server hat den Namen "ipify.example.com" und läuft an Port 80, der Docker-Host hat eine IP 10.20.30.40):
# docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
# docker run -e VIRTUAL_Host=ipify.example.com --detach --name ipify osixia/ipify-api:0.1.0
Innerhalb des Containers können Sie jetzt anrufen:
# curl http://ipify.example.com
10.20.30.40
Vielleicht ist der Container, den ich erstellt habe, auch nützlich https://github.com/qoomon/docker-Host
Sie können einfach Containernamen-DNs verwenden, um auf das Host-System zuzugreifen, z. curl http: // dockerhost: 9200 , so dass keine IP-Adresse benötigt wird.
Wenn Sie einen Windows-Container in einem Service Fabric-Cluster ausführen, ist die IP-Adresse des Hosts über die Umgebungsvariable Fabric_NodeIPOrFQDN
verfügbar. Service Fabric-Umgebungsvariablen
Auf Ubuntu kann der Befehl hostname
mit den folgenden Optionen verwendet werden:
-i
, --ip-address
Adressen für den Hostnamen-I
, --all-ip-addresses
alle Adressen für den HostZum Beispiel:
$ hostname -i
172.17.0.2
Um die Variable zuzuweisen, kann der folgende Einzeiler verwendet werden:
IP=$(hostname -i)