Como dice el título. Necesito poder recuperar la dirección IP que alojan los docker y los mapas de puertos del host al contenedor, y hacerlo dentro del contenedor.
Como dice el título. Necesito poder recuperar la dirección IP que alojan los docker y los mapas de puertos del host al contenedor, y hacerlo dentro del contenedor.
Respuestas:
/sbin/ip route|awk '/default/ { print $3 }'
Como notó @MichaelNeale, no tiene sentido usar este método Dockerfile
(excepto cuando necesitamos esta IP solo durante el tiempo de compilación), porque esta IP se codificará durante el tiempo de compilación.
A partir de la versión 18.03, puede usar host.docker.internal
como IP del host.
Funciona en Docker para Mac , Docker para Windows y quizás también en otras plataformas.
Esta es una actualización específica de Mac docker.for.mac.localhost
, disponible desde la versión 17.06 y docker.for.mac.host.internal
disponible desde la versión 17.12, que también puede funcionar en esa plataforma.
Tenga en cuenta que, como en la documentación de Mac y Windows , esto es solo para fines de desarrollo.
Por ejemplo, tengo variables de entorno establecidas en mi host:
MONGO_SERVER=host.docker.internal
En mi docker-compose.yml
archivo, tengo esto:
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..
lo tanto, es inútil ya que en la mayoría de los casos no tiene un entorno solo para Linux o Mac en su empresa. Es mixto, tienes desarrolladores que usan Linux, Mac y Windows. Este dominio no tiene sentido ya que en el 99% es un entorno de sistema operativo host mixto. No desarrollo un contenedor en macOS y lo implemento en un servidor macOS. Lo implemento en Linux. Esto es lo que todos hacen. Entonces, ¿cuál es el punto docker.for.mac..
?
docker.for.mac.host.internal
no importa si está utilizando Docker con o sin docker-compose
. Quiero usar un host fijo en los archivos de configuración. IDK, por ejemplo, docker.host.internal
que siempre apunta a la dirección IP del host. Independientemente del sistema host que esté usando. Este es el objetivo de usar Docker: quiero ser autónomo. Entiendo que es aún más complicado en macOS porque tienes otra capa entre el sistema host y el contenedor. Pero de todos modos, en mi opinión docker.for.mac.host.internal
es inútil si solo puedes usarlo para macOS.
host.docker.internal
también funciona en Docker para Windows , al menos al momento de escribir este comentario.
Actualización: en Docker para Mac , a partir de la versión 18.03, puede usar host.docker.internal como la IP del host. Ver la respuesta de allanberry . Para versiones anteriores de Docker para Mac, la siguiente respuesta puede ser útil:
En Docker para Mac, el docker0
puente no existe, por lo que otras respuestas aquí pueden no funcionar. Sin embargo, todo el tráfico saliente se enruta a través de su host principal, por lo que siempre que intente conectarse a una IP, se reconocerá como sí mismo (y el contenedor del acoplador no cree que sea él mismo), debería poder conectarse. Por ejemplo, si ejecuta esto desde la máquina principal, ejecute:
ipconfig getifaddr en0
Esto debería mostrarle la IP de su Mac en su red actual y su contenedor Docker también debería poder conectarse a esta dirección. Por supuesto, esto es un problema si esta dirección IP cambia alguna vez, pero puede agregar una IP de bucle invertido personalizada a su Mac que el contenedor no cree que sea en sí misma al hacer algo como esto en la máquina principal:
sudo ifconfig lo0 alias 192.168.46.49
Luego puede probar la conexión desde el contenedor acoplable con telnet. En mi caso, quería conectarme a un servidor xdebug remoto:
telnet 192.168.46.49 9000
Ahora, cuando el tráfico ingresa a su Mac con la dirección 192.168.46.49 (y todo el tráfico que sale de su contenedor pasa a través de su Mac), su Mac asumirá que la IP es en sí misma. Cuando termine de usar esta IP, puede eliminar el alias de bucle invertido como este:
sudo ifconfig lo0 -alias 192.168.46.49
Una cosa a tener en cuenta es que el contenedor de la ventana acoplable no enviará tráfico al host principal si cree que el destino del tráfico es él mismo. Por lo tanto, compruebe la interfaz de bucle invertido dentro del contenedor si tiene problemas:
sudo ip addr show lo
En mi caso, esto mostró lo inet 127.0.0.1/8
que significa que no podía usar ninguna IP en el 127.*
rango. Es por eso que usé 192.168.*
en el ejemplo anterior. Asegúrese de que la IP que usa no entre en conflicto con algo en su propia red.
Para aquellos que ejecutan Docker en AWS, los metadatos de instancia para el host todavía están disponibles desde el interior del contenedor.
curl http://169.254.169.254/latest/meta-data/local-ipv4
Por ejemplo:
$ 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 única forma es pasar la información del host como entorno cuando crea un contenedor
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(usando la respuesta aceptada de unix.stackexchange.com/questions/87468/… )
El --add-host
podría ser una solución más limpia (pero sin la parte de puerto, sólo el anfitrión puede ser manejado con esta solución). Entonces, bajo tu docker run
mando, haz algo como:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
La mejor práctica estándar para la mayoría de las aplicaciones que buscan hacer esto automáticamente es: no lo hace . En su lugar, haga que la persona que ejecuta el contenedor inyecte un nombre de host externo / dirección IP como configuración, por ejemplo, como una variable de entorno o un archivo de configuración. Permitir que el usuario inyecte esto le brinda el diseño más portátil.
¿Por qué sería tan difícil? Debido a que los contenedores, por diseño, aislarán la aplicación del entorno del host. La red tiene un espacio de nombres solo para ese contenedor de forma predeterminada, y los detalles del host están protegidos del proceso que se ejecuta dentro del contenedor, que puede no ser totalmente confiable.
Existen diferentes opciones según su situación específica:
Si su contenedor se está ejecutando con redes de host, puede mirar la tabla de enrutamiento en el host directamente para ver la ruta predeterminada. De esta pregunta, lo siguiente funciona para mí, por ejemplo:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Un ejemplo que muestra esto con la red de host en un contenedor se ve así:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
Para algunas versiones de Docker Desktop, inyectaron una entrada DNS en la VM incorporada:
getent hosts host.docker.internal | awk '{print $1}'
Si está ejecutando en un entorno de nube, puede verificar el servicio de metadatos del proveedor de la nube, por ejemplo, el de AWS:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Si desea su dirección externa / de internet, puede consultar un servicio remoto como:
curl ifconfig.co
Cada uno de estos tiene limitaciones y solo funciona en escenarios específicos. La opción más portátil aún es ejecutar su contenedor con la dirección IP inyectada como configuración, por ejemplo, aquí hay una opción que ejecuta el ip
comando anterior en el host y lo inyecta como una variable de entorno:
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
Comando realmente útil ... Gracias :)
Si desea una IP
dirección real (no un puente IP
) Windows
y tiene docker 18.03
(o más reciente), haga lo siguiente:
Ejecute bash en el contenedor desde el host donde está el nombre de la imagen nginx
(funciona Alpine Linux distribution
):
docker run -it nginx /bin/ash
Luego corre dentro del contenedor
/ # nslookup host.docker.internal
Name: host.docker.internal
Address 1: 192.168.65.2
192.168.65.2
es la IP del host, no la IP del puente como en la spinus
respuesta aceptada.
Estoy usando aquí host.docker.internal :
El host tiene una dirección IP cambiante (o ninguna si no tiene acceso a la red). A partir del 18.03 en adelante, nuestra recomendación es conectarse al nombre DNS especial host.docker.internal, que se resuelve en la dirección IP interna utilizada por el host. Esto es para fines de desarrollo y no funcionará en un entorno de producción fuera de Docker para Windows.
Alpine Linux
? Si no, entonces verifique el equivalente para su específico linux distribution
.
linux containers
y no estoy usando windows containers
. Puede hacerlo haciendo clic derecho en docker icon
y seleccionando Switch to Linux containers
. Creo que eso podría ser importante cuando estás descargando una imagen. Si ha windows container
comprobado si al eliminar una nginx
imagen anterior y descargarla nuevamente obtendrá otro contenedor. Si aún así no funciona, puede intentar instalarlo nslookup
en el ash
.
host.docker.internal
) desde el interior del contenedor
docker run -it --rm alpine nslookup host.docker.internal
... imprime la dirección IP del host ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
En Mac y Windows , puede usar el nombre DNS especial host.docker.internal
.
El host tiene una dirección IP cambiante (o ninguna si no tiene acceso a la red). A partir del 18.03 en adelante, nuestra recomendación es conectarse al nombre DNS especial host.docker.internal, que se resuelve en la dirección IP interna utilizada por el host. Esto es para fines de desarrollo y no funcionará en un entorno de producción fuera de Docker Desktop para Mac.
Docker para Mac Quiero conectarme desde un contenedor a un servicio en el host
El host tiene una dirección IP cambiante (o ninguna si no tiene acceso a la red). A partir del 18.03 en adelante, nuestra recomendación es conectarse al nombre DNS especial host.docker.internal, que se resuelve en la dirección IP interna utilizada por el host.
También se puede acceder a la puerta de enlace como gateway.docker.internal. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Si habilitó la API remota de Docker (a través de, por ejemplo) y conoce el nombre de host o la dirección IP de la máquina host, esto se puede hacer con mucho bash.-H
tcp://0.0.0.0:4243
Dentro del usuario de mi contenedor 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 segunda línea toma la ID del contenedor de su /proc/self/cgroup
archivo local .
La tercera línea se enrolla en la máquina host (suponiendo que esté utilizando 4243 como puerto del acoplador) y luego usa el nodo para analizar el JSON devuelto para el DESIRED_PORT
.
HostPort
puede ser información útil aquí, desafortunadamente HostIp
podría ser0.0.0.0
Tengo Ubuntu 16.03. Para mi
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
no no trabajar (ip estaba generando mal)
Mi solución de trabajo fue que:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Aquí hay otra opción para aquellos que ejecutan Docker en AWS. Esta opción evita tener que usar apk para agregar el paquete de rizos y ahorra los preciosos 7mb de espacio. Use el wget incorporado (parte del binario monolítico BusyBox):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, en el caso de Docker para Linux (distribución estándar), la dirección IP del host siempre será 172.17.0.1
.
La forma más fácil de obtenerlo es a través de ifconfig
(interface docker0) desde el host:
ifconfig
Desde el interior de una ventana acoplable, el siguiente comando desde una ventana acoplable: ip -4 route show default | cut -d" " -f3
Puede ejecutarlo rápidamente en una ventana acoplable con la siguiente línea de comando:
# 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"
Espero que ayude.
En linux puedes correr
HOST_IP=`hostname -I | awk '{print $1}'`
En macOS, su máquina host no es el host Docker. Docker instalará su sistema operativo host en VirtualBox.
HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
hostname -I
advierte que no "haga suposiciones sobre el orden de la salida".
Esta es una implementación minimalista en Node.js para quién ejecuta el host en instancias de AWS EC2 , utilizando la instancia de metadatos de EC2 mencionada anteriormente.
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
y usado como
ec2(function(err, ip) {
if(err) console.log(err)
else console.log(ip);
})
Si está ejecutando un contenedor de Windows en un clúster de Service Fabric, la dirección IP del host está disponible a través de la variable de entorno Fabric_NodeIPOrFQDN
. Variables de entorno de Service Fabric
Así es como lo hago. En este caso, agrega una entrada de hosts en / etc / hosts dentro de la imagen del acoplador apuntando taurus-host a la IP de mi máquina local:
TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...
Luego, desde el contenedor Docker, el script puede usar el nombre de host taurus-host para acceder a mi máquina local que aloja el contenedor docker.
Quizás el contenedor que he creado también sea útil https://github.com/qoomon/docker-host
Simplemente puede usar el nombre del contenedor dns para acceder al sistema host, por ejemplo, curl http: // dockerhost: 9200 , por lo que no es necesario molestarse con ninguna dirección IP.
La solución que uso se basa en un "servidor" que devuelve la dirección externa del host Docker cuando recibe una solicitud http.
En el "servidor":
1) Inicie jwilder / nginx-proxy
# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
2) Inicie el contenedor ipify
# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0
Ahora, cuando un contenedor envía una solicitud http al servidor, p. Ej.
# curl http://<external server name/address>:<external server port>
ipify devuelve la dirección IP del host Docker a través del encabezado http "X-Fordered-For"
Ejemplo (el servidor ipify tiene el nombre "ipify.example.com" y se ejecuta en el puerto 80, el host docker tiene 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
Dentro del contenedor ahora puede llamar:
# curl http://ipify.example.com
10.20.30.40
Prueba esto
docker run --rm -i --net = host ifconfig alpino
En Ubuntu, el hostname
comando se puede usar con las siguientes opciones:
-i
, --ip-address
direcciones para el nombre de host-I
, --all-ip-addresses
todas las direcciones para el hostPor ejemplo:
$ hostname -i
172.17.0.2
Para asignar a la variable, se puede usar la siguiente línea:
IP=$(hostname -i)
Con https://docs.docker.com/machine/install-machine/
a) $ docker-machine ip
b) Obtenga la dirección IP de una o más máquinas.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2