Comme le titre l'indique. Je dois pouvoir récupérer l'adresse IP des hôtes du menu fixe et les cartes du port de l'hôte au conteneur, et ce, à l'intérieur du conteneur.
/sbin/ip route|awk '/default/ { print $3 }'
Comme @MichaelNeale l'a remarqué, il n'y a aucun sens à utiliser cette méthode dans 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 lors de la génération.
Sur Docker pour Mac, à partir de la version 18.03, vous pouvez utiliser Host.docker.internal
comme adresse IP de l'hôte.
Notez que, comme dans la documentation _, "ceci est destiné au développement [s] et ne fonctionnera pas dans un environnement de production en dehors de Docker pour Mac." En effet, dans Docker pour Mac, "vous ne pouvez pas voir une interface docker0 sur l'hôte. Cette interface est en fait dans la machine virtuelle".
Il s’agit d’une mise à jour de docker.for.mac.localhost
, disponible depuis la version 17.06, et de docker.for.mac.Host.internal
, disponible depuis la version 17.12, qui peut aussi toujours fonctionner.
Par exemple, j'ai des variables d'environnement définies sur mon hôte:
MONGO_SERVER=Host.docker.internal
Dans mon fichier docker-compose.yml
, 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
Mise à jour: sur Docker pour Mac, à partir de la version 18.03, vous pouvez utiliser Host.docker.internal comme adresse IP de l'hôte. Voir Réponse d'Allanberry . Pour les versions précédentes de Docker pour Mac, la réponse suivante peut toujours être utile:
Sur Docker pour Mac, le pont docker0
n’existant pas, d’autres réponses risquent de ne pas fonctionner. Toutefois, tout le trafic sortant est acheminé via votre hôte parent. Par conséquent, vous devriez pouvoir vous connecter tant que vous essayez de vous connecter à une adresse IP reconnue comme telle (et que le conteneur docker ne le pense pas lui-même). Par exemple, si vous exécutez ceci à partir de la machine parent, exécutez:
ipconfig getifaddr en0
Cela devrait vous montrer l'adresse 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 adresse IP de bouclage personnalisée à votre Mac que le conteneur ne pense pas être elle-même en procédant comme ceci sur la machine parente:
Sudo ifconfig lo0 alias 192.168.46.49
Vous pouvez ensuite tester la connexion depuis le conteneur de menu fixe avec telnet. Dans mon cas, je voulais me connecter à un serveur xdebug distant:
telnet 192.168.46.49 9000
Maintenant, lorsque le trafic entrant dans votre Mac et adressé pour 192.168.46.49 (et que tout le trafic quittant votre conteneur passe par votre Mac), votre Mac supposera que l'IP est lui-même. Lorsque vous avez fini d'utiliser cette adresse IP, vous pouvez supprimer l'alias de bouclage de la manière suivante:
Sudo ifconfig lo0 -alias 192.168.46.49
Une chose à laquelle il faut 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 rencontrez des problèmes:
Sudo ip addr show lo
Dans mon cas, cela montrait inet 127.0.0.1/8
, ce qui signifie que je ne pouvais utiliser aucune adresse IP dans la plage 127.*
. C'est pourquoi j'ai utilisé 192.168.*
dans l'exemple ci-dessus. Assurez-vous que l'adresse IP que vous utilisez ne soit pas en conflit avec quelque chose sur votre propre réseau.
Pour ceux qui exécutent Docker dans AWS, les métadonnées 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
Le seul moyen consiste à transmettre les informations sur l'hôte en tant qu'environnement lorsque vous créez un conteneur.
run --env <key>=<value>
Le --add-Host
pourrait être une solution plus propre (mais sans la partie port, seul l'hôte peut être traité avec cette solution). Donc, dans votre docker run
, faites quelque chose comme:
docker run --add-Host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
Docker pour Mac Je souhaite me connecter depuis un conteneur à un service de 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, nous vous recommandons de vous connecter au nom DNS spécial Host.docker.internal, qui correspond à 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 que vous connaissez le nom d'hôte ou l'adresse IP de la machine hôte, vous pouvez le faire avec beaucoup de bash.
Dans la variable bashrc
de mon conteneur:
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 fichier /proc/self/cgroup
local.
La troisième ligne se courbe sur la machine hôte (en supposant que vous utilisez 4243 comme port de docker), puis utilise node pour analyser le JSON renvoyé pour le DESIRED_PORT
.
Si vous voulez une vraie adresse IP
(pas un pont IP
) sur Windows
et que vous avez docker 18.03
(ou plus récent), procédez comme suit:
Exécutez bash sur le conteneur de l'hôte où le nom de l'image est nginx
(fonctionne sur 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'adresse IP de l'hôte - pas l'adresse IP du pont comme dans la réponse acceptée spinus
.
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, nous vous recommandons de vous connecter au nom DNS spécial Host.docker.internal, qui correspond à l'adresse IP interne utilisée par l'hôte. Ceci à des fins de développement et ne fonctionnera pas dans un environnement de production en dehors de Docker pour Windows.
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 enregistre le précieux 7 Mo d'espace disque. Utilisez le wget intégré (partie du binaire monolithique BusyBox):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
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 système d'exploitation hôte dans VirtualBox.
Host_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
La meilleure pratique standard pour la plupart des applications cherchant à le faire automatiquement est la suivante: vous ne le faites pas. Au lieu de cela, la personne qui exécute le conteneur injecte un nom d’hôte externe/une adresse IP en configuration, par exemple. comme variable d'environnement ou fichier de configuration. Permettre à l'utilisateur d'injecter ceci vous donne la conception la plus portable.
Pourquoi cela serait-il si difficile? Parce que les conteneurs vont, de par leur conception, isoler l'application de l'environnement hôte. Le réseau est par défaut d'espacement de noms pour ce conteneur uniquement, et les détails de l'hôte sont protégés du processus s'exécutant à l'intérieur du conteneur, qui peut ne pas être totalement fiable.
Il existe différentes options en fonction de votre situation spécifique:
Si votre conteneur fonctionne avec la mise en réseau de l'hôte, vous pouvez consulter la table de routage de l'hôte directement pour voir la route par défaut, par exemple:
ip r s 0/0 | awk '{print $3}
Un exemple montrant cela avec la mise en réseau de l'hôte dans un conteneur ressemble à ceci:
docker run --rm --net Host busybox /bin/sh -c "ip r s 0/0 | awk '{print \$3}'"
Pour certaines versions de Docker Desktop, ils ont injecté une entrée DNS:
getent hosts Host.docker.internal | awk '{print $1}'
Si vous utilisez un environnement cloud, vous pouvez vérifier le service de métadonnées auprès du fournisseur de cloud, par exemple. le AWS one:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Si vous voulez votre adresse externe/internet, vous pouvez interroger un service distant tel que:
curl ifconfig.co
Chacun de ceux-ci ont des limites et ne fonctionnent 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 commande ip
précédente sur l'hôte et l'injectant en tant que variable d'environnement:
docker run --rm -e Host_IP=$(ip r s 0/0 | awk '{print $3}') busybox printenv Host_IP
J'ai Ubuntu 16.03. Pour moi
docker run --add-Host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
est-ce que NOT fonctionne (une mauvaise adresse IP était générée)
Ma solution de travail était que:
docker run --add-Host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Ceci est une implémentation minimaliste dans Node.js pour qui exécute l'hôte sur instances AWS EC2 , en utilisant le précédent mentionné instance de métadonnées EC2
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);
})
Voici comment je le fais. Dans ce cas, il ajoute une entrée d'hôtes dans/etc/hosts au sein de l'image du menu fixe qui pointe taurus-Host vers l'adresse IP de mon ordinateur local:
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 à la machine locale hébergeant le conteneur Docker.
La solution que j'utilise repose sur un "serveur" qui renvoie l'adresse externe de l'hôte Docker lorsqu'il reçoit une demande http.
Sur le "serveur":
1) Démarrer 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 ex.
# curl http://<external server name/address>:<external server port>
l'adresse IP de l'hôte Docker est renvoyée par ipify via l'en-tête http "X-Forwarded-For"
Exemple (le serveur ipify porte le nom "ipify.example.com" et s’exécute sur le port 80, l’hôte du menu fixe 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
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 , vous n'avez donc pas besoin de vous soucier d'une adresse 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
Sur Ubuntu, la commande hostname
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, vous pouvez utiliser la ligne suivante:
IP=$(hostname -i)