Jak mówi tytuł. Muszę być w stanie pobrać adres IP hostów dokera i map portów z hosta do kontenera i zrobić to wewnątrz kontenera.
Jak mówi tytuł. Muszę być w stanie pobrać adres IP hostów dokera i map portów z hosta do kontenera i zrobić to wewnątrz kontenera.
Odpowiedzi:
/sbin/ip route|awk '/default/ { print $3 }'
Jak zauważył @MichaelNeale, nie ma sensu używać tej metody Dockerfile
(z wyjątkiem sytuacji, gdy potrzebujemy tego adresu IP tylko w czasie kompilacji), ponieważ ten adres IP zostanie zakodowany na stałe podczas kompilacji.
Od wersji 18.03 można używać host.docker.internal
jako adresu IP hosta.
Działa w Docker na Mac , Docker na Windows i być może także na innych platformach.
Jest to aktualizacja specyficzna dla komputerów Mac docker.for.mac.localhost
, dostępna od wersji 17.06 i docker.for.mac.host.internal
dostępna od wersji 17.12, która może nadal działać na tej platformie.
Uwaga: tak jak w dokumentacji Mac i Windows , służy to wyłącznie do celów programistycznych.
Na przykład mam ustawione zmienne środowiskowe na moim hoście:
MONGO_SERVER=host.docker.internal
W moim docker-compose.yml
pliku mam to:
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..
Jest to więc bezużyteczne, ponieważ w większości przypadków w Twojej firmie nie ma środowiska opartego tylko na systemie Linux lub Mac. Jest mieszany, masz programistów używających Linuksa, Maca i Windowsa. Ta domena nie ma sensu, ponieważ w 99% jest mieszanym środowiskiem systemu operacyjnego Host. Nie rozwijam kontenera pod macOS i nie wdrażam go na serwerze macOS. Wdrażam go w systemie Linux. Tak robią wszyscy. Więc o co w tym wszystkim chodzi docker.for.mac..
?
docker.for.mac.host.internal
nie ma znaczenia, czy używasz Dockera z, czy bez docker-compose
. Chcę użyć stałego hosta w plikach konfiguracyjnych. Na przykład IDK, docker.host.internal
który zawsze wskazuje adres IP hosta. Niezależnie od używanego systemu hosta. O to w ogóle chodzi o używanie Dockera: chcę być autonomiczny. Rozumiem, że na MacOS jest to jeszcze trudniejsze, ponieważ masz inną warstwę między systemem hosta a kontenerem. Ale w każdym razie moim zdaniem docker.for.mac.host.internal
jest bezużyteczny, jeśli można go używać tylko w systemie macOS.
host.docker.internal
działa również w Docker dla Windows , przynajmniej w momencie pisania tego komentarza.
Aktualizacja: W Docker dla komputerów Mac od wersji 18.03 można użyć host.docker.internal jako adresu IP hosta. Zobacz odpowiedź allanberry . W przypadku wcześniejszych wersji Docker na komputery Mac przydatne mogą być następujące odpowiedzi:
W Docker dla komputerów Mac docker0
most nie istnieje, więc inne odpowiedzi tutaj mogą nie działać. Cały ruch wychodzący jest jednak kierowany przez hosta nadrzędnego, więc dopóki próbujesz połączyć się z adresem IP, który rozpoznaje jako sam (a kontener dokerów nie myśli, że jest sam), powinieneś być w stanie się połączyć. Na przykład, jeśli uruchomisz to z komputera nadrzędnego:
ipconfig getifaddr en0
Powinno to pokazać adres IP komputera Mac w bieżącej sieci, a kontener dokerów powinien mieć możliwość połączenia się z tym adresem. Jest to oczywiście bolesne, jeśli ten adres IP kiedykolwiek się zmienia, ale możesz dodać niestandardowy IP sprzężenia zwrotnego do komputera Mac, którego kontener nie uważa za sam, wykonując coś takiego na komputerze nadrzędnym:
sudo ifconfig lo0 alias 192.168.46.49
Następnie możesz przetestować połączenie z poziomu kontenera dokowanego za pomocą usługi telnet. W moim przypadku chciałem połączyć się ze zdalnym serwerem xdebug:
telnet 192.168.46.49 9000
Teraz, gdy ruch przychodzi na komputer Mac adresowany na 192.168.46.49 (a cały ruch opuszczający kontener przechodzi przez komputer Mac), komputer Mac przyjmuje, że adres IP jest sam. Po zakończeniu używania tego adresu IP możesz usunąć alias sprzężenia zwrotnego w następujący sposób:
sudo ifconfig lo0 -alias 192.168.46.49
Jedną z rzeczy, na które należy uważać, jest to, że kontener dokerów nie wysyła ruchu do hosta nadrzędnego, jeśli uważa, że sam cel jest miejscem docelowym. Jeśli masz problemy, sprawdź interfejs sprzężenia zwrotnego wewnątrz kontenera:
sudo ip addr show lo
W moim przypadku pokazało to, inet 127.0.0.1/8
co oznacza, że nie mogłem użyć żadnych adresów IP w tym 127.*
zakresie. Dlatego użyłem 192.168.*
w powyższym przykładzie. Upewnij się, że używany adres IP nie powoduje konfliktu z czymś w Twojej sieci.
Dla osób korzystających z Dockera w AWS metadane instancji dla hosta są nadal dostępne z wnętrza kontenera.
curl http://169.254.169.254/latest/meta-data/local-ipv4
Na przykład:
$ 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+'
Jedynym sposobem jest przekazanie informacji o hoście jako środowiska podczas tworzenia kontenera
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(używając zaakceptowanej odpowiedzi z unix.stackexchange.com/questions/87468/... )
--add-host
Może być rozwiązaniem bardziej czystsze (ale bez części portu, jedynie host może być obsługiwane z tego rozwiązania). Więc, na twój docker run
rozkaz, zrób coś takiego:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
Standardową najlepszą praktyką dla większości aplikacji, które chcą to zrobić automatycznie, jest: nie . Zamiast tego osoba uruchamiająca kontener wstrzykuje zewnętrzną nazwę hosta / adres IP jako konfigurację, np. Jako zmienną środowiskową lub plik konfiguracyjny. Zezwolenie użytkownikowi na wstrzyknięcie tego daje najbardziej przenośny projekt.
Dlaczego miałoby to być takie trudne? Ponieważ kontenery z założenia będą izolować aplikację od środowiska hosta. Sieć jest domyślnie umieszczana w przestrzeni nazw tylko tego kontenera, a szczegóły hosta są chronione przed procesem uruchomionym w kontenerze, który może nie być w pełni zaufany.
Istnieją różne opcje w zależności od konkretnej sytuacji:
Jeśli twój kontener działa z siecią hosta, możesz spojrzeć bezpośrednio na tabelę routingu na hoście, aby zobaczyć domyślną trasę. Z tego pytania działają dla mnie np .:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Przykład pokazujący to z siecią hosta w kontenerze wygląda następująco:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
W przypadku niektórych wersji Docker Desktop wstrzyknęły wpis DNS do wbudowanej maszyny wirtualnej:
getent hosts host.docker.internal | awk '{print $1}'
Jeśli pracujesz w środowisku chmurowym, możesz sprawdzić usługę metadanych od dostawcy chmury, np. AWS:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Jeśli chcesz mieć swój adres zewnętrzny / internetowy, możesz wysłać zapytanie do zdalnej usługi, takiej jak:
curl ifconfig.co
Każdy z nich ma ograniczenia i działa tylko w określonych scenariuszach. Najbardziej przenośną opcją jest nadal uruchamianie kontenera z adresem IP wprowadzonym jako konfiguracja, np. Oto opcja uruchomienia wcześniejszego ip
polecenia na hoście i wstrzyknięcia go jako zmiennej środowiskowej:
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
polecenie .. Dzięki :)
Jeśli chcesz mieć prawdziwy IP
adres (nie most IP
) Windows
i masz dokera18.03
(lub nowsze), wykonaj następujące czynności:
Uruchom bash na kontenerze z hosta, na którym znajduje się nazwa obrazu nginx
(działa na Alpine Linux distribution
):
docker run -it nginx /bin/ash
Następnie wbiegnij do pojemnika
/ # nslookup host.docker.internal
Name: host.docker.internal
Address 1: 192.168.65.2
192.168.65.2
to adres IP hosta - nie adres IP mostka, jak w spinus
zaakceptowanej odpowiedzi.
Używam tutaj host.docker.internal :
Host ma zmieniający się adres IP (lub żaden, jeśli nie masz dostępu do sieci). Od 18.03 r. Naszym zaleceniem jest łączenie się ze specjalną nazwą DNS host.docker.internal, która działa na wewnętrzny adres IP używany przez host. Ma to na celu rozwój i nie będzie działać w środowisku produkcyjnym poza Docker dla Windows.
Alpine Linux
? Jeśli nie, sprawdź odpowiednik dla swojego konkretnego linux distribution
.
linux containers
i nie używam windows containers
. Możesz to zrobić, klikając prawym przyciskiem myszy docker icon
i wybierając Switch to Linux containers
. Myślę, że może to być ważne podczas pobierania obrazu. Jeśli windows container
sprawdziłeś, czy usunięcie starego nginx
obrazu i pobranie go ponownie, dostaniesz inny pojemnik. Jeśli nadal nie będzie działać, możesz spróbować zainstalować nslookup
w ash
.
host.docker.internal
) z wnętrza kontenera
docker run -it --rm alpine nslookup host.docker.internal
... drukuje adres IP hosta ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
Na komputerach Mac i Windows można użyć specjalnej nazwy DNS host.docker.internal
.
Host ma zmieniający się adres IP (lub żaden, jeśli nie masz dostępu do sieci). Od 18.03 r. Naszym zaleceniem jest łączenie się ze specjalną nazwą DNS host.docker.internal, która działa na wewnętrzny adres IP używany przez host. Służy to do celów programistycznych i nie będzie działać w środowisku produkcyjnym poza Docker Desktop dla komputerów Mac.
Docker dla komputerów Mac Chcę połączyć się z kontenera z usługą na hoście
Host ma zmieniający się adres IP (lub żaden, jeśli nie masz dostępu do sieci). Od 18.03 r. Naszym zaleceniem jest łączenie się ze specjalną nazwą DNS host.docker.internal, która działa na wewnętrzny adres IP używany przez host.
Dostęp do bramy można również uzyskać jako gateway.docker.internal. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Jeśli włączyłeś zdalny interfejs API dokera ( na przykład) i znasz nazwę hosta lub adres IP komputera hosta, można to zrobić z dużą szybkością.-H
tcp://0.0.0.0:4243
W obrębie użytkownika mojego kontenera 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'
)
Druga linia pobiera identyfikator kontenera z /proc/self/cgroup
pliku lokalnego .
Trzecia linia zwija się na maszynie hosta (zakładając, że używasz 4243 jako portu dokera), a następnie używa węzła do analizy zwróconego JSON dla DESIRED_PORT
.
HostPort
mogą tu być przydatne informacje, niestety HostIp
może to być0.0.0.0
Mam Ubuntu 16.03. Dla mnie
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
nie nie działa (źle Ip został generowania)
Moje działające rozwiązanie było następujące:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Oto kolejna opcja dla osób korzystających z Dockera w AWS. Ta opcja pozwala uniknąć używania apk do dodawania paczki curl i oszczędza cenne 7 MB miejsca. Użyj wbudowanego wget (część monolitycznego pliku binarnego BusyBox):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, w przypadku Dockera dla Linuksa (standardowa dystrybucja), adres IP hosta zawsze będzie 172.17.0.1
.
Najprostszym sposobem na uzyskanie tego jest ifconfig
(interfejs dokujący interfejs0) z hosta:
ifconfig
Z poziomu okna dokowanego następujące polecenie z okna dokowanego: ip -4 route show default | cut -d" " -f3
Możesz go szybko uruchomić w oknie dokowanym za pomocą następującego wiersza polecenia:
# 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"
Mam nadzieję, że to pomoże.
W systemie Linux możesz biegać
HOST_IP=`hostname -I | awk '{print $1}'`
W systemie macOS komputer hosta nie jest hostem Docker. Docker zainstaluje system hosta w VirtualBox.
HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
hostname -I
ostrzega, aby „nie przyjmować żadnych założeń dotyczących kolejności danych wyjściowych”.
Jest to minimalistyczna implementacja w Node.js dla tego, kto obsługuje host na instancjach AWS EC2 , używając wspomnianej wcześniej instancji EC2 Metadata
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
i używane jako
ec2(function(err, ip) {
if(err) console.log(err)
else console.log(ip);
})
Jeśli korzystasz z kontenera systemu Windows w klastrze usługi Service Fabric, adres IP hosta jest dostępny za pośrednictwem zmiennej środowiskowej Fabric_NodeIPOrFQDN
. Zmienne środowiskowe sieci szkieletowej usług
Oto jak to robię. W tym przypadku dodaje wpis hosta do / etc / hosts w obrazie dokera wskazujący taurus-host do mojego adresu IP komputera lokalnego:
TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...
Następnie, z poziomu kontenera Docker, skrypt może użyć nazwy hosta taurus-host, aby dostać się na moją lokalną maszynę, na której znajduje się kontener Docker.
Być może kontener, który utworzyłem, jest również przydatny https://github.com/qoomon/docker-host
Możesz po prostu użyć nazwy kontenera dns, aby uzyskać dostęp do systemu hosta, np. Curl http: // dockerhost: 9200 , więc nie musisz męczyć się z żadnym adresem IP.
Rozwiązanie, którego używam, opiera się na „serwerze”, który zwraca zewnętrzny adres hosta Dockera po otrzymaniu żądania http.
Na „serwerze”:
1) Uruchom jwilder / nginx-proxy
# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
2) Uruchom kontener ipify
# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0
Teraz, gdy kontener wysyła żądanie HTTP do serwera, np
# curl http://<external server name/address>:<external server port>
adres IP hosta Docker jest zwracany przez ipify przez nagłówek http „X-Forwarded-For”
Przykład (serwer ipify ma nazwę „ipify.example.com” i działa na porcie 80, host dokera ma adres 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
Wewnątrz kontenera możesz teraz zadzwonić:
# curl http://ipify.example.com
10.20.30.40
Spróbuj tego
Uruchom okno dokowane --rm -i --net = host alpine ifconfig
W systemie Ubuntu hostname
polecenia można używać z następującymi opcjami:
-i
, --ip-address
adresy nazwy hosta-I
, --all-ip-addresses
wszystkie adresy hostaNa przykład:
$ hostname -i
172.17.0.2
Aby przypisać zmienną, można zastosować następującą linijkę:
IP=$(hostname -i)
Z https://docs.docker.com/machine/install-machine/
a) $ doker-maszyna ip
b) Uzyskaj adres IP jednego lub więcej komputerów.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2