Wie der Titel schon sagt. Ich muss in der Lage sein, die IP-Adresse der Docker-Hosts und der Portmaps vom Host zum Container abzurufen und dies innerhalb des Containers zu tun.
Wie der Titel schon sagt. Ich muss in der Lage sein, die IP-Adresse der Docker-Hosts und der Portmaps vom Host zum Container abzurufen und dies innerhalb des Containers zu tun.
Antworten:
/sbin/ip route|awk '/default/ { print $3 }'
Wie @MichaelNeale bemerkt hat, macht es keinen Sinn, diese Methode zu verwenden Dockerfile
(außer wenn wir diese IP nur während der Erstellungszeit benötigen), da diese IP während der Erstellungszeit fest codiert wird.
Ab Version 18.03 können Sie host.docker.internal
die IP des Hosts verwenden.
Funktioniert in Docker für Mac , Docker für Windows und möglicherweise auch auf anderen Plattformen.
Dies ist ein Mac-spezifisches Update docker.for.mac.localhost
, das seit Version 17.06 docker.for.mac.host.internal
verfügbar ist und seit Version 17.12 verfügbar ist und möglicherweise auch noch auf dieser Plattform funktioniert.
Beachten Sie, dass dies wie in der Mac- und Windows- Dokumentation nur zu Entwicklungszwecken dient.
Auf meinem Host sind beispielsweise Umgebungsvariablen festgelegt:
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
docker.for.mac..
ist nutzlos , da in den meisten Fällen Sie keine Linux- oder Mac-Umgebung in Ihrem Unternehmen haben. Es ist gemischt, Sie haben Entwickler, die Linux, Mac und Windows verwenden. Diese Domain macht keinen Sinn, da es sich in 99% um eine gemischte Host-Betriebssystemumgebung handelt. Ich entwickle keinen Container unter macOS und stelle ihn auf einem macOS-Server bereit. Ich stelle es unter Linux bereit. Das macht jeder. Worum geht es also überhaupt docker.for.mac..
?
docker.for.mac.host.internal
spielt keine Rolle, ob Sie Docker mit oder ohne verwenden docker-compose
. Ich möchte einen festen Host in Konfigurationsdateien verwenden. Zum Beispiel IDK, docker.host.internal
das immer auf die Host-IP-Adresse verweist. Unabhängig davon, welches Hostsystem ich verwende. Das ist der springende Punkt bei der Verwendung von Docker: Ich möchte autonom sein. Ich verstehe, dass es unter macOS noch schwieriger ist, weil Sie eine weitere Schicht zwischen dem Hostsystem und dem Container haben. Aber meiner Meinung nach docker.for.mac.host.internal
ist es nutzlos, wenn man es nur für macOS verwenden kann.
host.docker.internal
funktioniert auch unter Docker für Windows , zumindest zum Zeitpunkt des Schreibens dieses Kommentars.
Update: Unter Docker für Mac können Sie ab Version 18.03 host.docker.internal als IP des Hosts verwenden. Siehe Allanberrys Antwort . Für frühere Versionen von Docker für Mac kann die folgende Antwort weiterhin hilfreich sein:
Unter Docker für Mac ist die docker0
Bridge nicht vorhanden, daher funktionieren andere Antworten hier möglicherweise nicht. Der gesamte ausgehende Datenverkehr wird jedoch über Ihren übergeordneten Host geleitet. Solange Sie versuchen, eine Verbindung zu einer IP herzustellen, die er als sich selbst erkennt (und der Docker-Container glaubt nicht, dass er sich selbst ist), sollten Sie in der Lage sein, eine Verbindung herzustellen. Wenn Sie dies beispielsweise auf dem übergeordneten Computer ausführen, führen Sie Folgendes aus:
ipconfig getifaddr en0
Dies sollte Ihnen die IP Ihres Mac in seinem aktuellen Netzwerk anzeigen und Ihr Docker-Container sollte auch eine Verbindung zu dieser Adresse herstellen können. Dies ist natürlich ein Problem, wenn sich diese IP-Adresse jemals ä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 ausführen:
sudo ifconfig lo0 alias 192.168.46.49
Anschließend können Sie die Verbindung im Docker-Container mit Telnet testen. In meinem Fall wollte ich eine Verbindung zu einem entfernten xdebug-Server herstellen:
telnet 192.168.46.49 9000
Wenn nun Datenverkehr auf Ihren Mac gelangt, der für 192.168.46.49 adressiert ist (und der gesamte Datenverkehr, der Ihren Container verlässt, über Ihren Mac fließt), geht Ihr Mac davon aus, dass die IP selbst ist. Wenn Sie diese IP nicht mehr verwenden, können Sie den Loopback-Alias wie folgt entfernen:
sudo ifconfig lo0 -alias 192.168.46.49
Eine Sache, die Sie beachten sollten, ist, dass der Docker-Container keinen Datenverkehr an den übergeordneten Host sendet, wenn er glaubt, dass das Ziel des Datenverkehrs selbst ist. Überprüfen Sie daher die Loopback-Schnittstelle im Container, wenn Sie Probleme haben:
sudo ip addr show lo
In meinem Fall zeigte inet 127.0.0.1/8
dies, dass ich keine IPs im 127.*
Bereich verwenden konnte. Deshalb habe ich 192.168.*
im obigen Beispiel verwendet. Stellen Sie sicher, dass die von Ihnen verwendete IP-Adresse nicht mit einem Konflikt in Ihrem eigenen Netzwerk in Konflikt steht.
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
ifconfig eth0 | grep -oP 'inet \K\S+'
Die einzige Möglichkeit besteht darin, die Hostinformationen als Umgebung zu übergeben, wenn Sie einen Container erstellen
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(unter Verwendung der akzeptierten Antwort von unix.stackexchange.com/questions/87468/… )
Das --add-host
könnte eine sauberere Lösung (aber ohne den Anschlussteil nur die Host kann mit dieser Lösung behandelt werden) sein. Machen Sie also in Ihrem docker run
Befehl etwas wie:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
Die Standard-Best Practice für die meisten Apps, die dies automatisch tun möchten, lautet: Sie tun dies nicht . Stattdessen muss die Person, die den Container ausführt, einen externen Hostnamen / eine externe IP-Adresse als Konfiguration einfügen, z. B. 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 Hostumgebung isolieren. Das Netzwerk ist standardmäßig nur auf diesen Container beschränkt, und die Details des Hosts sind vor dem Prozess geschützt, der im Container ausgeführt wird und dem möglicherweise nicht vollständig vertraut wird.
Abhängig von Ihrer spezifischen Situation gibt es verschiedene Optionen:
Wenn Ihr Container mit einem Host-Netzwerk ausgeführt wird, können Sie in der Routing-Tabelle auf dem Host direkt die Standardroute anzeigen. Aus dieser Frage ergibt sich für mich zB:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
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 route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
Bei einigen Versionen von Docker Desktop wurde ein DNS-Eintrag in die eingebettete VM eingefügt:
getent hosts host.docker.internal | awk '{print $1}'
Wenn Sie in einer Cloud-Umgebung ausgeführt werden, können Sie den Metadatendienst des Cloud-Anbieters überprüfen, z. B. den AWS-Dienst:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Wenn Sie Ihre externe / Internetadresse möchten, können Sie einen Remote-Dienst wie folgt abfragen:
curl ifconfig.co
Jedes dieser Verfahren weist Einschränkungen auf und funktioniert nur in bestimmten Szenarien. Die portabelste Option besteht weiterhin darin, Ihren Container mit der als Konfiguration eingefügten IP-Adresse auszuführen. Beispiel: Hier ist eine Option, mit der der frühere ip
Befehl auf dem Host ausgeführt und als Umgebungsvariable eingefügt wird:
export HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
docker run --rm -e HOST_IP busybox printenv HOST_IP
curl ifconfig.co
Befehl .. Danke :)
Wenn Sie eine echte IP
Adresse (keine Brücke IP
) möchten Windows
und Docker 18.03
(oder einen neueren) haben, gehen Sie wie folgt vor:
Führen Sie bash auf dem Container vom Host aus, auf dem sich der Bildname befindet nginx
(funktioniert Alpine Linux distribution
):
docker run -it nginx /bin/ash
Dann in den Behälter 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 der spinus
akzeptierten Antwort.
Ich benutze 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 zum speziellen DNS-Namen host.docker.internal herzustellen, der in die vom Host verwendete interne IP-Adresse aufgelöst wird. Dies dient Entwicklungszwecken und funktioniert nicht in einer Produktionsumgebung außerhalb von Docker für Windows.
Alpine Linux
? Wenn nicht, überprüfen Sie das Äquivalent für Ihre spezifischen linux distribution
.
linux containers
und verwende es nicht. windows containers
Sie können dies tun, indem Sie mit der rechten Maustaste auf klicken docker icon
und auswählen Switch to Linux containers
. Ich denke, das könnte wichtig sein, wenn Sie ein Bild herunterladen. Wenn Sie windows container
überprüft haben, ob nginx
Sie ein altes Bild löschen und erneut herunterladen, erhalten Sie einen anderen Container. Wenn es bei Ihnen immer noch nicht funktioniert, können Sie versuchen, es nslookup
in der zu installieren ash
.
host.docker.internal
) aus dem Container
docker run -it --rm alpine nslookup host.docker.internal
... druckt die IP-Adresse des Hosts ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
Unter Mac und Windows können Sie den speziellen DNS-Namen verwenden 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 zum speziellen DNS-Namen host.docker.internal herzustellen, der in die vom Host verwendete interne IP-Adresse aufgelöst wird. Dies dient Entwicklungszwecken und funktioniert nicht in einer Produktionsumgebung außerhalb von Docker Desktop für Mac.
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 zum 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 erreichbar. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Wenn Sie die Docker-Remote-API aktiviert haben ( z. B. über) und den Hostnamen oder die IP-Adresse des Hostcomputers kennen, kann dies mit viel Bash durchgeführt werden.-H
tcp://0.0.0.0:4243
Innerhalb des Benutzers meines Containers bashrc
:
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 wird auf den Hostcomputer übertragen (vorausgesetzt, Sie verwenden 4243 als Docker-Port) und verwendet dann den Knoten, um den zurückgegebenen JSON für den zu analysieren DESIRED_PORT
.
HostPort
können hier nützliche Informationen sein, leider HostIp
könnte das sein0.0.0.0
Ich habe Ubuntu 16.03. Für mich
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
tut NICHT (falsche IP wurde generiert)
Meine Arbeitslösung war:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
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 wertvolle 7 MB Platz. Verwenden Sie das integrierte wget (Teil der monolithischen BusyBox-Binärdatei):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, im Fall von Docker für Linux (Standarddistribution) lautet die IP-Adresse des Hosts immer 172.17.0.1
.
Der einfachste Weg, es zu bekommen, ist über ifconfig
(Schnittstelle docker0) vom Host:
ifconfig
Aus einem Docker heraus den folgenden Befehl von einem Docker: ip -4 route show default | cut -d" " -f3
Sie können es schnell in einem Docker mit der folgenden Befehlszeile ausführen:
# 1. Run an ubuntu docker
# 2. Updates dependencies (quietly)
# 3. Install ip package (quietly)
# 4. Shows (nicely) the ip of the host
# 5. Removes the docker (thanks to `--rm` arg)
docker run -it --rm ubuntu:19.10 bash -c "apt-get update && apt-get install iproute2 -y && ip -4 route show default | cut -d' ' -f3"
Ich hoffe, es hilft.
Unter Linux können Sie ausführen
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'/.$//'`
hostname -I
warnt davor, "keine Annahmen über die Reihenfolge der Ausgabe zu treffen".
Dies ist eine minimalistische Implementierung in Node.js für diejenigen , die den Host auf AWS EC2-Instanzen unter Verwendung der oben genannten EC2-Metadateninstanz ausführen
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);
})
Wenn Sie einen Windows-Container in einem Service Fabric-Cluster ausführen, ist die IP-Adresse des Hosts über die Umgebungsvariable verfügbar Fabric_NodeIPOrFQDN
. Service Fabric-Umgebungsvariablen
Hier ist, wie ich es mache. In diesem Fall wird ein Hosts-Eintrag in / etc / hosts im Docker-Image hinzugefügt, der den Stier-Host auf die IP meines lokalen Computers verweist ::
TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...
Anschließend kann das Skript im Docker-Container den Hostnamen taurus-host verwenden, um zu meinem lokalen Computer zu gelangen, auf dem sich der Docker-Container befindet.
Vielleicht ist der von mir erstellte Container auch nützlich: https://github.com/qoomon/docker-host
Sie können einfach den Containernamen dns verwenden, um auf das Hostsystem zuzugreifen, z. B. curl http: // dockerhost: 9200 , sodass Sie keine IP-Adresse benötigen.
Die von mir verwendete Lösung basiert auf einem "Server", der die externe Adresse des Docker-Hosts zurückgibt, wenn er eine http-Anfrage empfängt.
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-Anfrage an den Server sendet, z
# curl http://<external server name/address>:<external server port>
Die IP-Adresse des Docker-Hosts wird von ipify über den http-Header "X-Forwarded-For" zurückgegeben.
Beispiel (ipify-Server hat den Namen "ipify.example.com" und läuft auf Port 80, Docker-Host hat 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
Versuche dies
Docker run --rm -i --net = Host alpine ifconfig
Unter Ubuntu kann der hostname
Befehl 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 der Variablen zuzuweisen, kann der folgende Einzeiler verwendet werden:
IP=$(hostname -i)
Mit https://docs.docker.com/machine/install-machine/
a) $ docker-machine ip
b) Rufen Sie die IP-Adresse eines oder mehrerer Computer ab.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2