Acceda al contenedor docker desde el host utilizando el nombre de los contenedores
Estoy desarrollando un servicio y usando allí docker compose para girar servicios como postgres, redis, elasticsearch. Tengo una aplicación web que se basa en RubyOnRails y escribe y lee de todos esos servicios.
Aquí está mi docker-compose.yml
version: '2'
services:
redis:
image: redis:2.8
networks:
- frontapp
elasticsearch:
image: elasticsearch:2.2
networks:
- frontapp
postgres:
image: postgres:9.5
environment:
POSTGRES_USER: elephant
POSTGRES_PASSWORD: smarty_pants
POSTGRES_DB: elephant
volumes:
- /var/lib/postgresql/data
networks:
- frontapp
networks:
frontapp:
driver: bridge
Y puedo hacer ping a contenedores dentro de esta red
$ docker-compose run redis /bin/bash
root@777501e06c03:/data# ping postgres
PING postgres (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: icmp_seq=0 ttl=64 time=0.346 ms
64 bytes from 172.20.0.2: icmp_seq=1 ttl=64 time=0.047 ms
...
Hasta ahora todo bien. Ahora quiero ejecutar la aplicación ruby on rails en mi máquina host pero poder acceder a la instancia de postgres con url como postgresql://username:password@postgres/database
actualmente que no es posible
$ ping postgres
ping: unknown host postgres
Puedo ver mi red en docker
$ docker network ls
NETWORK ID NAME DRIVER
ac394b85ce09 bridge bridge
0189d7e86b33 elephant_default bridge
7e00c70bde3b elephant_frontapp bridge
a648554a72fa host host
4ad9f0f41b36 none null
Y puedo ver una interfaz con él
$ ifconfig
br-0189d7e86b33 Link encap:Ethernet HWaddr 02:42:76:72:bb:c2
inet addr:172.18.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:76ff:fe72:bbc2/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:36 errors:0 dropped:0 overruns:0 frame:0
TX packets:60 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2000 (2.0 KB) TX bytes:8792 (8.7 KB)
br-7e00c70bde3b Link encap:Ethernet HWaddr 02:42:e7:d1:fe:29
inet addr:172.20.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:e7ff:fed1:fe29/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1584 errors:0 dropped:0 overruns:0 frame:0
TX packets:1597 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:407137 (407.1 KB) TX bytes:292299 (292.2 KB)
...
Pero no estoy seguro de qué debo hacer a continuación. Traté de jugar un poco con /etc/resolv.conf
, principalmente con nameserver
directiva, pero eso no tuvo ningún efecto.
Agradecería cualquier ayuda de sugerencias sobre cómo configurar esta configuración correctamente.
UPDATE
Después de navegar a través de los recursos de Internet logré asignar direcciones IP estáticas a las cajas. Para ahora es suficiente para mí continuar el desarrollo. Aquí está mi corriente docker-compose.yml
version: '2'
services:
redis:
image: redis:2.8
networks:
frontapp:
ipv4_address: 172.25.0.11
elasticsearch:
image: elasticsearch:2.2
networks:
frontapp:
ipv4_address: 172.25.0.12
postgres:
image: postgres:9.5
environment:
POSTGRES_USER: elephant
POSTGRES_PASSWORD: smarty_pants
POSTGRES_DB: elephant
volumes:
- /var/lib/postgresql/data
networks:
frontapp:
ipv4_address: 172.25.0.10
networks:
frontapp:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.25.0.0/16
gateway: 172.25.0.1
5 answers
Hay una aplicación de código abierto que resuelve este problema, se llama Servidor Proxy DNS
Es un servidor DNS que resuelve los nombres de host de los contenedores, si no se pudo encontrar un nombre de host que coincida, entonces soluciónelo desde Internet también
Inicie el servidor DNS
$ docker run --hostname dns.mageddo --name dns-proxy-server -p 5380:5380 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/resolv.conf:/etc/resolv.conf \
defreitas/dns-proxy-server
Se establecerá como DNS predeterminado automáticamente (y se recuperará al original cuando se detenga)
Inicie su contenedor para la prueba
docker-compose up
Docker-compose.yml
version: '2'
services:
redis:
container_name: redis
image: redis:2.8
hostname: redis.dev.intranet
network_mode: bridge # that way he can solve others containers names even inside, solve elasticsearch, for example
elasticsearch:
container_name: elasticsearch
image: elasticsearch:2.2
hostname: elasticsearch.dev.intranet
Ahora resolver su contenedores hostnames
De host
$ nslookup redis.dev.intranet
Server: 172.17.0.2
Address: 172.17.0.2#53
Non-authoritative answer:
Name: redis.dev.intranet
Address: 172.21.0.3
De otro contenedor
$ docker exec -it redis ping elasticsearch.dev.intranet
PING elasticsearch.dev.intranet (172.21.0.2): 56 data bytes
También resuelve nombres de hosts de Internet
$ nslookup google.com
Server: 172.17.0.2
Address: 172.17.0.2#53
Non-authoritative answer:
Name: google.com
Address: 216.58.202.78
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-26 14:13:42
El nombre de host del contenedor docker no se puede ver desde fuera. Lo que puede hacer es asignar un nombre al contenedor y acceder al contenedor a través del nombre. Si enlaza 2 contenedores digamos container1 y container2 entonces docker se encarga de escribir la IP y el nombre de host de container2 en el container1. Sin embargo, en su caso, su aplicación se está ejecutando en el hostmachine.
O
Conoce la IP del contenedor. Así que en el / etc / hosts de su máquina host puede agregar $IP host hostanameof container
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-15 19:16:32
Si solo está utilizando la configuración de docker-compose localmente, podría asignar los puertos de sus contenedores a su host con
elasticsearch:
image: elasticsearch:2.2
ports:
- 9300:9300
- 9200:9200
Luego use localhost:9300 (o 9200 dependiendo del protocolo) desde su aplicación web para acceder a Elasticsearch.
Una solución más compleja es ejecutar su propio dns que resuelva los nombres de los contenedores. Creo que esta solución está mucho más cerca de lo que estás pidiendo. Previsiblemente he usado skydns al ejecutar kubernetes localmente.
Hay algunas opciones ahi. Echa un vistazo a https://github.com/gliderlabs/registrator y https://github.com/jderusse/docker-dns-gen. No lo probé, pero podría asignar el puerto dns a su host de la misma manera que con los puertos elásticos en el ejemplo anterior y luego agregar localhost a su resolución.conf para poder resolver los nombres de los contenedores desde el host.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-14 09:36:27
Hay dos soluciones (excepto /etc/hosts
) describe aquí y aquí
Escribí mi propia solución en Python y la implementé como servicio para proporcionar mapeo desde el nombre de host del contenedor a su IP. Aquí está: https://github.com/nicolai-budico/dockerhosts
Inicia dnsmasq con el parámetro --hostsdir=/var/run/docker-hosts
y actualiza el archivo /var/run/docker-hosts/hosts
cada vez que se cambia una lista de contenedores en ejecución.
Una vez que se cambia el archivo /var/run/docker-hosts/hosts
, dnsmasq actualiza automáticamente su asignación y el contenedor estará disponible por nombre de host en un segundo.
$ docker run -d --hostname=myapp.local.com --rm -it ubuntu:17.10
9af0b6a89feee747151007214b4e24b8ec7c9b2858badff6d584110bed45b740
$ nslookup myapp.local.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: myapp.local.com
Address: 172.17.0.2
Hay scripts de instalación y desinstalación. Solo necesita permitir que su sistema interactúe con esta instancia de dnsmasq. Me registré en systemd-resuelto:
$ cat /etc/systemd/resolved.conf
[Resolve]
DNS=127.0.0.54
#FallbackDNS=
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=no
#Cache=yes
#DNSStubListener=udp
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-08 14:47:33
Aditya es correcto. En su caso, lo más simple es codificar su nombre de host / mapeo de IP en /etc/hosts
El problema con este enfoque, sin embargo, es que no controla la dirección IP privada que tendrá su máquina postgres. La dirección IP cambiará cada vez que inicie un nuevo contenedor, por lo que deberá actualizar su archivo /etc/hosts.
Si eso es un problema, te recomendaría que leas esta publicación de blog que explica cómo hacer cumplir que un contenedor obtenga una IP específica dirección:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-16 03:56:40