Comme le dit le titre. Je dois être en mesure de récupérer l'adresse IP des hôtes Docker et les cartes de port de l'hôte vers le conteneur, et de le faire à l'intérieur du conteneur.
Comme le dit le titre. Je dois être en mesure de récupérer l'adresse IP des hôtes Docker et les cartes de port de l'hôte vers le conteneur, et de le faire à l'intérieur du conteneur.
Réponses:
/sbin/ip route|awk '/default/ { print $3 }'
Comme @MichaelNeale l'a remarqué, cela n'a aucun sens d'utiliser cette méthode Dockerfile
(sauf lorsque nous avons besoin de cette adresse IP uniquement lors de la génération), car cette adresse IP sera codée en dur pendant la génération.
À partir de la version 18.03, vous pouvez utiliser host.docker.internal
l'adresse IP de l'hôte.
Fonctionne dans Docker pour Mac , Docker pour Windows et peut-être d'autres plates-formes également.
Il s'agit d'une mise à jour spécifique au Mac docker.for.mac.localhost
, disponible depuis la version 17.06 et docker.for.mac.host.internal
disponible depuis la version 17.12, qui peut également fonctionner sur cette plate-forme.
Notez, comme dans la documentation Mac et Windows , ceci est uniquement à des fins de développement.
Par exemple, j'ai des variables d'environnement définies sur mon hôte:
MONGO_SERVER=host.docker.internal
Dans mon docker-compose.yml
dossier, j'ai ceci:
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..
est donc inutile car dans la plupart des cas, vous n'avez pas d'environnement Linux ou Mac uniquement dans votre entreprise. C'est mélangé, vous avez des développeurs utilisant Linux et Mac et Windows. Ce domaine n'a aucun sens, car dans 99% des cas, il s'agit d'un environnement OS hôte mixte. Je ne développe pas de conteneur sous macOS et je ne le déploie pas sur un serveur macOS. Je le déploie sur Linux. C'est ce que tout le monde fait. Alors, à quoi ça sert même docker.for.mac..
?
docker.for.mac.host.internal
n'a pas d'importance si vous utilisez Docker avec ou sans docker-compose
. Je souhaite utiliser un hôte fixe dans les fichiers de configuration. IDK, par exemple, docker.host.internal
qui pointe toujours vers l'adresse IP de l'hôte. Quel que soit le système hôte que j'utilise. C'est tout l'intérêt d'utiliser Docker: je veux être autonome. Je comprends que c'est encore plus délicat sur macOS car vous avez une autre couche entre le système hôte et le conteneur. Mais de toute façon, à mon avis docker.for.mac.host.internal
est inutile si vous ne pouvez l'utiliser que pour macOS.
host.docker.internal
fonctionne également sur Docker pour Windows , au moins au moment de la rédaction de ce commentaire.
Mise à jour: sur Docker pour Mac , à partir de la version 18.03, vous pouvez utiliser host.docker.internal comme IP de l'hôte. Voir la réponse d'Allanberry . Pour les versions antérieures de Docker pour Mac, la réponse suivante peut toujours être utile:
Sur Docker pour Mac, le docker0
pont n'existe pas, donc les autres réponses ici peuvent ne pas fonctionner. Cependant, tout le trafic sortant est acheminé via votre hôte parent.Par conséquent, tant que vous essayez de vous connecter à une adresse IP qu'il reconnaît comme lui-même (et que le conteneur Docker ne pense pas être lui-même), vous devriez pouvoir vous connecter. Par exemple, si vous l'exécutez à partir de l'exécution de la machine parente:
ipconfig getifaddr en0
Cela devrait vous montrer l'IP de votre Mac sur son réseau actuel et votre conteneur Docker devrait également pouvoir se connecter à cette adresse. C'est bien sûr un problème si cette adresse IP change jamais, mais vous pouvez ajouter une IP de bouclage personnalisée à votre Mac que le conteneur ne pense pas être lui-même en faisant quelque chose comme ça sur la machine parente:
sudo ifconfig lo0 alias 192.168.46.49
Vous pouvez ensuite tester la connexion à partir du conteneur Docker avec telnet. Dans mon cas, je voulais me connecter à un serveur xdebug distant:
telnet 192.168.46.49 9000
Maintenant, lorsque le trafic arrive sur votre Mac, adressé au 192.168.46.49 (et que tout le trafic sortant de votre conteneur passe par votre Mac), votre Mac supposera que l'IP est elle-même. Lorsque vous avez fini d'utiliser cette IP, vous pouvez supprimer l'alias de bouclage comme ceci:
sudo ifconfig lo0 -alias 192.168.46.49
Une chose à laquelle faire attention est que le conteneur Docker n'enverra pas de trafic à l'hôte parent s'il pense que la destination du trafic est elle-même. Vérifiez donc l'interface de bouclage à l'intérieur du conteneur si vous avez des problèmes:
sudo ip addr show lo
Dans mon cas, cela a montré inet 127.0.0.1/8
que je ne pouvais pas utiliser d'IP dans la 127.*
plage. C'est pourquoi j'ai utilisé 192.168.*
dans l'exemple ci-dessus. Assurez-vous que l'IP que vous utilisez n'entre pas en conflit avec quelque chose sur votre propre réseau.
Pour ceux qui exécutent Docker dans AWS, les métadonnées d'instance pour l'hôte sont toujours disponibles à l'intérieur du conteneur.
curl http://169.254.169.254/latest/meta-data/local-ipv4
Par exemple:
$ 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+'
La seule façon consiste à transmettre les informations d'hôte en tant qu'environnement lorsque vous créez un conteneur
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(en utilisant la réponse acceptée de unix.stackexchange.com/questions/87468/… )
Le --add-host
pourrait être une solution plus propre (mais sans la partie du port, seul l'hôte peut être manipulé avec cette solution). Donc, dans votre docker run
commande, faites quelque chose comme:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
La meilleure pratique standard pour la plupart des applications qui cherchent à le faire automatiquement est: vous ne le faites pas . Au lieu de cela, la personne exécutant le conteneur doit injecter un nom d'hôte / adresse IP externe comme configuration, par exemple en tant que variable d'environnement ou fichier de configuration. Permettre à l'utilisateur d'injecter cela vous donne la conception la plus portable.
Pourquoi serait-ce si difficile? Parce que les conteneurs, de par leur conception, isolent l'application de l'environnement hôte. Par défaut, le réseau est uniquement dédié à ce conteneur et les détails de l'hôte sont protégés contre le processus s'exécutant à l'intérieur du conteneur qui peut ne pas être entièrement fiable.
Il existe différentes options en fonction de votre situation spécifique:
Si votre conteneur s'exécute avec la mise en réseau d'hôte, vous pouvez consulter la table de routage sur l'hôte directement pour voir l'itinéraire par défaut. À partir de cette question, les travaux suivants me conviennent, par exemple:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Un exemple montrant cela avec la mise en réseau d'hôte dans un conteneur ressemble à ceci:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
Pour certaines versions de Docker Desktop, ils ont injecté une entrée DNS dans la machine virtuelle intégrée:
getent hosts host.docker.internal | awk '{print $1}'
Si vous exécutez dans un environnement cloud, vous pouvez vérifier le service de métadonnées auprès du fournisseur de cloud, par exemple celui d'AWS:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Si vous voulez votre adresse externe / Internet, vous pouvez interroger un service distant comme:
curl ifconfig.co
Chacun d'eux a des limites et ne fonctionne que dans des scénarios spécifiques. L'option la plus portable consiste toujours à exécuter votre conteneur avec l'adresse IP injectée en tant que configuration, par exemple, voici une option exécutant la ip
commande précédente sur l'hôte et l'injectant en tant que variable d'environnement:
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
Commande vraiment utile .. Merci :)
Si vous voulez une IP
adresse réelle (pas un pont IP
) Windows
et que vous avez un docker 18.03
(ou plus récent), procédez comme suit:
Exécutez bash sur le conteneur depuis l'hôte où se trouve le nom de l'image nginx
(fonctionne Alpine Linux distribution
):
docker run -it nginx /bin/ash
Puis courez à l'intérieur du conteneur
/ # nslookup host.docker.internal
Name: host.docker.internal
Address 1: 192.168.65.2
192.168.65.2
est l'IP de l'hôte - pas l'IP du pont comme dans la spinus
réponse acceptée.
J'utilise ici host.docker.internal :
L'hôte a une adresse IP changeante (ou aucune si vous n'avez pas d'accès au réseau). À partir du 18.03, notre recommandation est de se connecter au nom DNS spécial host.docker.internal, qui se résout en l'adresse IP interne utilisée par l'hôte. Ceci est à des fins de développement et ne fonctionnera pas dans un environnement de production en dehors de Docker pour Windows.
Alpine Linux
? Sinon, vérifiez l'équivalent pour votre spécifique linux distribution
.
linux containers
et je n'utilise pas. windows containers
Vous pouvez le faire en cliquant avec le bouton droit sur docker icon
et en sélectionnant Switch to Linux containers
. Je pense que cela pourrait être important lorsque vous téléchargez une image. Si vous aviez à windows container
vérifier si la suppression de l'anciennginx
image et son téléchargement à nouveau vous obtiendrez un autre conteneur. Si cela ne fonctionne toujours pas pour vous - alors vous pouvez essayer de l'installer nslookup
dans le ash
.
host.docker.internal
) depuis l'intérieur du conteneur
docker run -it --rm alpine nslookup host.docker.internal
... imprime l'adresse IP de l'hôte ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
Sur Mac et Windows , vous pouvez utiliser le nom DNS spécial host.docker.internal
.
L'hôte a une adresse IP changeante (ou aucune si vous n'avez pas d'accès au réseau). À partir du 18.03, notre recommandation est de se connecter au nom DNS spécial host.docker.internal, qui se résout en l'adresse IP interne utilisée par l'hôte. C'est à des fins de développement et ne fonctionnera pas dans un environnement de production en dehors de Docker Desktop pour Mac.
Docker pour Mac Je souhaite me connecter d'un conteneur à un service sur l'hôte
L'hôte a une adresse IP changeante (ou aucune si vous n'avez pas d'accès au réseau). À partir du 18.03, notre recommandation est de se connecter au nom DNS spécial host.docker.internal, qui se résout en l'adresse IP interne utilisée par l'hôte.
La passerelle est également accessible en tant que gateway.docker.internal. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Si vous avez activé l' API distante Docker (via-H
tcp://0.0.0.0:4243
par exemple) et connaissez le nom d'hôte ou l'adresse IP de la machine hôte, cela peut être fait avec beaucoup de bash.
Au sein de l'utilisateur de mon conteneur 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'
)
La deuxième ligne récupère l'ID de conteneur de votre section locale /proc/self/cgroup
fichier .
La troisième ligne se déroule vers la machine hôte (en supposant que vous utilisez 4243 comme port de docker) puis utilise le nœud pour analyser le JSON renvoyé pour le DESIRED_PORT
.
HostPort
des informations peuvent être utiles ici, malheureusement, elles HostIp
pourraient l'être0.0.0.0
J'ai Ubuntu 16.03. Pour moi
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
ne fonctionne PAS (la mauvaise IP était en train de générer)
Ma solution de travail était que:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Voici une autre option pour ceux qui exécutent Docker dans AWS. Cette option évite d'avoir à utiliser apk pour ajouter le paquet curl et économise le précieux 7 Mo d'espace. Utilisez le wget intégré (qui fait partie du binaire monolithique BusyBox):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, dans le cas de Docker pour Linux (distribution standard), l'adresse IP de l'hôte sera toujours 172.17.0.1
.
Le moyen le plus simple de l'obtenir est via ifconfig
(interface docker0) depuis l'hôte:
ifconfig
Depuis l'intérieur d'un docker, la commande suivante d'un docker: ip -4 route show default | cut -d" " -f3
Vous pouvez l'exécuter rapidement dans un docker avec la ligne de commande suivante:
# 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"
J'espère que ça aide.
Sous Linux, vous pouvez exécuter
HOST_IP=`hostname -I | awk '{print $1}'`
Sous macOS, votre ordinateur hôte n'est pas l'hôte Docker. Docker installera son OS hôte dans VirtualBox.
HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
hostname -I
avertit de ne pas "faire d'hypothèses sur l'ordre de sortie".
Il s'agit d'une implémentation minimaliste dans Node.js pour qui exécute l'hôte sur des instances AWS EC2 , en utilisant l' instance de métadonnées EC2 susmentionnée
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
et utilisé comme
ec2(function(err, ip) {
if(err) console.log(err)
else console.log(ip);
})
Si vous exécutez un conteneur Windows sur un cluster Service Fabric, l'adresse IP de l'hôte est disponible via la variable d'environnement Fabric_NodeIPOrFQDN
. Variables d'environnement Service Fabric
Voici comment je le fais. Dans ce cas, il ajoute une entrée d'hôtes dans / etc / hosts dans l'image docker pointant l'hôte taurus vers mon IP de machine locale::
TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...
Ensuite, à partir du conteneur Docker, le script peut utiliser le nom d'hôte taurus-host pour accéder à ma machine locale qui héberge le conteneur Docker.
Peut-être que le conteneur que j'ai créé est également utile https://github.com/qoomon/docker-host
Vous pouvez simplement utiliser le nom de conteneur DNS pour accéder au système hôte, par exemple curl http: // dockerhost: 9200 , donc pas besoin de vous tracasser avec une adresse IP.
La solution que j'utilise est basée sur un "serveur" qui retourne l'adresse externe de l'hôte Docker lorsqu'il reçoit une requête http.
Sur le "serveur":
1) Démarrez jwilder / nginx-proxy
# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
2) Démarrer le conteneur ipify
# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0
Désormais, lorsqu'un conteneur envoie une requête http au serveur, par exemple
# curl http://<external server name/address>:<external server port>
l'adresse IP de l'hôte Docker est retournée par ipify via l'en-tête http "X-Forwarded-For"
Exemple (le serveur ipify a le nom "ipify.example.com" et s'exécute sur le port 80, l'hôte docker a l'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
À l'intérieur du conteneur, vous pouvez maintenant appeler:
# curl http://ipify.example.com
10.20.30.40
Essaye ça
docker run --rm -i --net = hôte alpin ifconfig
Sur Ubuntu, la hostname
commande peut être utilisée avec les options suivantes:
-i
, --ip-address
adresses pour le nom d'hôte-I
, --all-ip-addresses
toutes les adresses de l'hôtePar exemple:
$ hostname -i
172.17.0.2
Pour affecter à la variable, la ligne unique suivante peut être utilisée:
IP=$(hostname -i)
Avec https://docs.docker.com/machine/install-machine/
a) $ docker-machine ip
b) Obtenez l'adresse IP d'une ou plusieurs machines.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2