Pregunta Desde el interior de un contenedor Docker, ¿cómo me conecto al localhost de la máquina?


Así que tengo un Nginx ejecutándose dentro de un contenedor acoplable, tengo un mysql ejecutándose en localhost, quiero conectarme al MySql desde dentro de mi Nginx. MySql se está ejecutando en localhost y no está exponiendo un puerto al mundo exterior, por lo que está vinculado a localhost, no está vinculado a la dirección IP de la máquina.

¿Hay alguna forma de conectarse a este MySql o cualquier otro programa en localhost desde este contenedor de docker?


659
2018-06-20 03:54


origen


Respuestas:


Editar: Si estás usando Docker-for-mac o Docker-para-Windows 18.03+, simplemente conéctese a su servicio mysql usando el host host.docker.internal.

A partir de Docker 18.04, esto no funciona en Docker-for-Linux.


TLDR

Utilizar --net="host" en tus docker run comando, entonces 127.0.0.1 en su contenedor acoplador señalará a su host Docker.


Nota sobre los modos de red del contenedor docker

Docker ofrece diferentes modos de red cuando se ejecutan contenedores. Según el modo que elija, se conectará de manera diferente a su base de datos MySQL que se ejecuta en el host Docker.

Docker run --net = "bridge" (predeterminado)

Docker crea un puente llamado docker0 por defecto. Tanto el host Docker como los contenedores Docker tienen una dirección IP en ese puente.

en el host Docker, escriba sudo ip addr show docker0 Tendrás una salida parecida a la siguiente:

[vagrant@docker:~] $ sudo ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::5484:7aff:fefe:9799/64 scope link
       valid_lft forever preferred_lft forever

Así que aquí mi host Docker tiene la dirección IP 172.17.42.1 sobre el docker0 interfaz de red.

Ahora inicie un nuevo contenedor y obtenga un shell en él: docker run --rm -it ubuntu:trusty bash y dentro del tipo de contenedor ip addr show eth0 para descubrir cómo está configurada su interfaz de red principal:

root@e77f6a1b3740:/# ip addr show eth0
863: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 66:32:13:f0:f1:e3 brd ff:ff:ff:ff:ff:ff
    inet 172.17.1.192/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::6432:13ff:fef0:f1e3/64 scope link
       valid_lft forever preferred_lft forever

Aquí mi contenedor tiene la dirección IP 172.17.1.192. Ahora mira la tabla de enrutamiento:

root@e77f6a1b3740:/# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.17.42.1     0.0.0.0         UG    0      0        0 eth0
172.17.0.0      *               255.255.0.0     U     0      0        0 eth0

Entonces, la dirección IP del host Docker 172.17.42.1 se establece como la ruta predeterminada y se puede acceder desde su contenedor.

root@e77f6a1b3740:/# ping 172.17.42.1
PING 172.17.42.1 (172.17.42.1) 56(84) bytes of data.
64 bytes from 172.17.42.1: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 172.17.42.1: icmp_seq=2 ttl=64 time=0.201 ms
64 bytes from 172.17.42.1: icmp_seq=3 ttl=64 time=0.116 ms

Docker Run --net = "host"

Alternativamente, puede ejecutar un contenedor acoplable con configuración de red configurada en host. Tal contenedor compartirá la pila de red con el host Docker y desde el punto de vista del contenedor, localhost (o 127.0.0.1) se referirá al host docker.

Tenga en cuenta que cualquier puerto abierto en su contenedor acoplador se abriría en el host Docker. Y esto sin requerir el -p o -P  docker run opción.

Configuración de IP en mi host Docker:

[vagrant@docker:~] $ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
       valid_lft forever preferred_lft forever

y de un contenedor de docker en anfitrión modo:

[vagrant@docker:~] $ docker run --rm -it --net=host ubuntu:trusty ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
       valid_lft forever preferred_lft forever

Como puede ver, tanto el host de docker como el de docker comparten la misma interfaz de red y, por lo tanto, tienen la misma dirección de IP.


Conectando a MySQL desde contenedores

Modo Puente

Para acceder a MySQL ejecutándose en el host Docker desde contenedores en Modo Puente, debe asegurarse de que el servicio MySQL esté escuchando las conexiones en el 172.17.42.1 Dirección IP.

Para hacerlo, asegúrese de tener cualquiera bind-address = 172.17.42.1 o bind-address = 0.0.0.0 en su archivo de configuración de MySQL (my.cnf).

Si necesita establecer una variable de entorno con la dirección IP de la puerta de enlace, puede ejecutar el siguiente código en un contenedor:

export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')

luego en su aplicación, use el DOCKER_HOST_IP variable de entorno para abrir la conexión a MySQL.

Nota: si utiliza bind-address = 0.0.0.0 su servidor MySQL escuchará las conexiones en todas las interfaces de red. Eso significa que su servidor MySQL podría ser alcanzado desde Internet; asegúrese de configurar las reglas del firewall en consecuencia.

Nota 2: si utiliza bind-address = 172.17.42.1 su servidor MySQL no escuchará las conexiones hechas a 127.0.0.1. Los procesos que se ejecutan en el host Docker que querrían conectarse a MySQL tendrían que usar 172.17.42.1 Dirección IP.

modo de host

Para acceder a MySQL ejecutándose en el host Docker desde contenedores en modo de host, puedes mantener bind-address = 127.0.0.1 en su configuración de MySQL y todo lo que necesita hacer es conectarse a 127.0.0.1 de tus contenedores:

[vagrant@docker:~] $ docker run --rm -it --net=host mysql mysql -h 127.0.0.1 -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 36
Server version: 5.5.41-0ubuntu0.14.04.1 (Ubuntu)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Nota: Usa mysql -h 127.0.0.1 y no mysql -h localhost; de lo contrario, el cliente de MySQL trataría de conectarse usando un socket de Unix.


962
2018-06-20 11:46



Para macOS y Windows

Docker v 18.03 y superior (desde el 21 de marzo de 2018)

Use su dirección IP interna o conéctese al nombre DNS especial host.docker.internal que se resolverá en la dirección IP interna utilizada por el host.

Soporte de Linux pendiente https://github.com/docker/for-linux/issues/264

MacOS con versiones anteriores de Docker

Docker para Mac v 17.12 a v 18.02

Igual que arriba, pero use docker.for.mac.host.internal en lugar.

Docker para Mac v. 17.06 a v 17.11

Igual que arriba, pero use docker.for.mac.localhost en lugar.

Docker para Mac 17.05 y abajo

Para acceder a la máquina host desde el contenedor acoplable, debe adjuntar un alias IP a su interfaz de red. Puedes enlazar cualquier IP que quieras, solo asegúrate de no utilizarlo para nada más.

sudo ifconfig lo0 alias 123.123.123.123/24 

Luego, asegúrese de que su servidor esté escuchando la IP mencionada anteriormente o 0.0.0.0. Si está escuchando en localhost 127.0.0.1 no aceptará la conexión.

¡Entonces solo apunte su contenedor acoplable a esta IP y podrá acceder a la máquina host!

Para probar, puedes ejecutar algo como curl -X GET 123.123.123.123:3000 dentro del contenedor.

El alias se reiniciará en cada reinicio así que cree un script de inicio si es necesario.

Solución y más documentación aquí: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds


197
2018-04-21 11:33



Hago un hack similar a las publicaciones anteriores para obtener la IP local para mapear a un nombre de alias (DNS) en el contenedor. El principal problema es obtener dinámicamente con un script simple que funcione tanto en Linux y OSX la dirección IP del host. Hice este script que funciona en ambos entornos (incluso en la distribución de Linux con "$LANG" != "en_*" configurado):

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

Entonces, usando Docker Compose, la configuración completa será:

Script de inicio (docker-run.sh):

export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)
docker-compose -f docker-compose.yml up

docker-compose.yml:

myapp:
  build: .
  ports:
    - "80:80"
  extra_hosts:
    - "dockerhost:$DOCKERHOST"

Entonces cambia http://localhost a http://dockerhost en tu código

Para obtener una guía más avanzada de cómo personalizar el DOCKERHOST script, echa un vistazo a esta publicación con una explicación de cómo funciona.


48
2017-08-03 21:30



Esto funcionó para mí en una pila NGINX / PHP-FPM sin tocar ningún código o red donde la aplicación solo espera poder conectarse a localhost

Montar mysqld.sock del host al interior del contenedor.

Encuentre la ubicación del archivo mysql.sock en el host que ejecuta mysql:
netstat -ln | awk '/mysql(.*)?\.sock/ { print $9 }'

Monta ese archivo donde se espera en la ventana acoplable:
docker run -v /hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock

Posibles ubicaciones de mysqld.sock:

/tmp/mysqld.sock
/var/run/mysqld/mysqld.sock 
/var/lib/mysql/mysql.sock
/Applications/MAMP/tmp/mysql/mysql.sock # if running via MAMP

29
2018-05-27 13:36



Para aquellos en Windows, suponiendo que está utilizando el controlador de red Bridge, querrá vincular específicamente MySQL a la dirección IP de la interfaz de red hyper-v.

Esto se realiza a través del archivo de configuración bajo la carpeta normalmente oculta C: \ ProgramData \ MySQL.

La vinculación a 0.0.0.0 no funcionará. La dirección necesaria también se muestra en la configuración del acoplador, y en mi caso era 10.0.75.1.


8
2017-12-10 15:53



Solución para Windows 10

Docker Community Edition 17.06.0-ce-win18 2017-06-28 (estable)

Puede usar el nombre DNS del host docker.for.win.localhost, para resolver la IP interna. (Advertencia algunas fuentes mencionadas windows pero debería ser win)

Visión de conjunto
Necesitaba hacer algo similar, es conectar desde mi contenedor Docker a mi servidor local, que estaba ejecutando el Azure Storage Emulator y CosmosDB Emulator.

los Azure Storage Emulator por defecto escucha en 127.0.0.1, aunque también puedes cambiar la IP, también estoy buscando una solución que funcione con la configuración predeterminada.

Esto también funciona para conectar desde mi contenedor Docker a SQL Server y IIS, ambos se ejecutan localmente en mi host con configuraciones de puerto predeterminadas.


8
2017-11-09 10:49



Editar: Terminé prototipando el concepto en GitHub. Revisa:  https://github.com/sivabudh/system-in-a-box


Primero, mi respuesta está dirigida a 2 grupos de personas: los que usan una Mac y los que usan Linux.

los anfitrión el modo de red no funciona en una Mac. Tienes que usar un alias de IP, mira: https://stackoverflow.com/a/43541681/2713729

¿Qué es un modo de red host? Ver: https://docs.docker.com/engine/reference/run/#/network-settings

En segundo lugar, para aquellos de ustedes que están usando Linux (mi experiencia directa fue con Ubuntu 14.04 LTS y estoy actualizando a 16.04 LTS en producción pronto), , puede hacer que el servicio que se ejecuta dentro de un contenedor Docker se conecte a localhost servicios que se ejecutan en el host Docker (por ejemplo, su computadora portátil).

¿Cómo?

La clave es cuando ejecuta el contenedor Docker, tiene que ejecutarlo con el anfitrión modo. El comando se ve así:

docker run --network="host" -id <Docker image ID>

Cuando haces un ifconfig (necesitaras apt-get install net-tools su contenedor para ifconfig para ser llamado) dentro de su contenedor, verá que las interfaces de red son las mismas que en el host Docker (por ejemplo, su computadora portátil).

Es importante tener en cuenta que soy un usuario de Mac, pero ejecuto Ubuntu bajo Parallels, por lo que usar una Mac no es una desventaja. ;-)

Y así es como se conecta el contenedor NGINX al MySQL ejecutándose en un localhost.


7
2018-02-07 07:15