Cómo comunicarse entre contenedores Docker a través de " hostname"
Planeo dividir mi servidor monolítico en muchos contenedores docker pequeños, pero aún no he encontrado una buena solución para la "comunicación entre contenedores". Este es mi escenario objetivo:
Sé cómo vincular contenedores y cómo exponer puertos, pero ninguna de estas soluciones me satisface.
¿Hay alguna solución para comunicarse a través de nombres de host (nombres de contenedores) entre los contenedores como en una red de servidores tradicional?
6 answers
Editar: Después de Docker 1.9, el comando docker network
(ver abajo https://stackoverflow.com/a/35184695/977939) es la forma recomendada de lograr esto.
Mi solución es configurar un dnsmasq en el host para que el registro DNS se actualice automáticamente: los registros "A" tienen los nombres de los contenedores y apuntan a las direcciones IP de los contenedores automáticamente (cada 10 segundos). El script de actualización automática se pega aquí:
#!/bin/bash
# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}
# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}
# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}
declare -A service_map
while true
do
changed=false
while read line
do
name=${line##* }
ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
then
service_map[$name]=$ip
# write to file
echo $name has a new IP Address $ip >&2
echo "host-record=$name,$ip" > "${DNSMASQ_CONFIG}/docker-$name"
changed=true
fi
done < <(${DOCKER} ps | ${TAIL} -n +2)
# a change of IP address occured, restart dnsmasq
if [ $changed = true ]
then
systemctl restart dnsmasq
fi
${SLEEP} $INTERVAL
done
Asegúrese de que su servicio dnsmasq es disponible en docker0
. Luego, inicie su contenedor con --dns HOST_ADDRESS
para usar este servicio mini dns.
Referencia: http://docs.blowb.org/setup-host/dnsmasq.html
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-05-23 12:10:33
La nueva función de red le permite conectarse a contenedores mediante su nombre, por lo que si crea una nueva red, cualquier contenedor conectado a esa red puede llegar a otros contenedores por su nombre. Ejemplo:
1) Crear nueva red
$ docker network create <network-name>
2) Conectar contenedores a la red
$ docker run --net=<network-name> ...
O
$ docker network connect <network-name> <container-name>
3) Ping contenedor por nombre
docker exec -ti <container-name-A> ping <container-name-B>
64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms
Ver esta sección de la documentación;
Nota: A diferencia del legado links
la nueva red no creará variables de entorno, ni compartirá variables de entorno con otros contenedores.
Esta característica actualmente no admite alias
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-02-03 18:21:30
Eso debería ser lo que --link
es para, al menos para la parte del nombre del host.
Con docker 1.10, y PR 19242 , eso sería:
docker network create --net-alias=[]: Add network-scoped alias for the container
(véase la última sección más adelante)
Eso es lo que Actualizando el archivo /etc/hosts
detalles
Además de las variables de entorno, Docker añade una entrada de host para el contenedor de origen al archivo
/etc/hosts
.
Por ejemplo, inicie un servidor LDAP:
docker run -t --name openldap -d -p 389:389 larrycai/openldap
Y definir una imagen para prueba ese servidor LDAP:
FROM ubuntu
RUN apt-get -y install ldap-utils
RUN touch /root/.bash_aliases
RUN echo "alias lds='ldapsearch -H ldap://internalopenldap -LL -b
ou=Users,dc=openstack,dc=org -D cn=admin,dc=openstack,dc=org -w
password'" > /root/.bash_aliases
ENTRYPOINT bash
Puede exponer el contenedor 'openldap
'como' internalopenldap
' dentro de la imagen de prueba con link link:
docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest
Entonces, si escribe 'lds' , ese alias funcionará:
ldapsearch -H ldap://internalopenldap ...
Eso devolvería a la gente. El significado internalopenldap
se alcanza correctamente desde la imagen ldaptest
.
Por supuesto, docker 1.7 agregará libnetwork
, que proporciona una implementación nativa de Go para conectar contenedores. Ver la entrada del blog .
Se se introdujo una arquitectura más completa, con el Modelo de Red de Contenedores (CNM)
Que actualizará la CLI de Docker con nuevos comandos "network", y documentará cómo se usa el indicador "-net
" para asignar contenedores a redes.
Docker 1.10 tiene una nueva sección Alias de ámbito de red, ahora oficialmente documentado en network connect
:
Mientras que los enlaces proporcionan una resolución de nombre privado que se localiza dentro de un contenedor, el alias de ámbito de red proporciona una forma para que un contenedor sea descubierto por un nombre alternativo por cualquier otro contenedor dentro del ámbito de una red en particular.
A diferencia del alias de enlace, que es definido por el consumidor de un servicio, el alias de ámbito de red es definido por el contenedor que ofrece el servicio a la red.Continuando con el ejemplo anterior, cree otro contenedor en
isolated_nw
con un alias de red.
$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17
--alias=[]
Añadir alias de ámbito de red para el contenedor
Puede usar la opción
--link
para vincular otro contenedor con un alias preferidoPuede pausar, reiniciar y detener contenedores que están conectados a una red. Los contenedores en pausa permanecen conectados y pueden ser revelados por una inspección de red. Cuando el contenedor se detiene, no aparece en la red hasta que lo reinicie.
Si se especifica, la(s) dirección (es) IP del contenedor se vuelve a aplicar cuando se reiniciar. Si la dirección IP ya no está disponible, el contenedor no se inicia.
Una forma de garantizar que la dirección IP está disponible es especificar un
--ip-range
al crear la red, y elegir las direcciones IP estáticas fuera de ese rango. Esto garantiza que la dirección IP no se proporcione a otro contenedor mientras este no esté en la red.
$ docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 multi-host-network
$ docker network connect --ip 172.20.128.2 multi-host-network container2
$ docker network connect --link container1:c1 multi-host-network container2
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-08-12 07:04:14
EDIT : Ya no es bleeding edge: http://blog.docker.com/2016/02/docker-1-10 /
Respuesta original
Luché con él toda la noche.
Si no le teme a bleeding edge, la última versión de Docker enginey Docker compose ambas implementan libnetwork.
Con el archivo de configuración correcto (que debe colocarse en la versión 2), creará servicios que se verán entre sí. Y, además, puedes escalarlos con docker-compose también (puede escalar cualquier servicio que desee que no vincule el puerto en el host)
Aquí hay un ejemplo archivo
version: "2"
services:
router:
build: services/router/
ports:
- "8080:8080"
auth:
build: services/auth/
todo:
build: services/todo/
data:
build: services/data/
Y la referencia para esta nueva versión del archivo compose: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md
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-07-04 08:07:29
Por lo que sé, usando solo Docker esto no es posible. Necesita algunos DNS para asignar ip: s del contenedor a nombres de host.
Si desea una solución lista para usar. Una solución es usar por ejemplo Kontena. Viene con tecnología de superposición de red de Weave y esta tecnología se utiliza para crear redes LAN privadas virtuales para cada servicio y cada servicio puede ser alcanzado por service_name.kontena.local-address
.
Aquí hay un ejemplo simple del archivo YAML de la aplicación de Wordpress donde el servicio de Wordpress se conecta al servidor MySQL con wordpress-mysql.kontena.dirección local:
wordpress:
image: wordpress:4.1
stateful: true
ports:
- 80:80
links:
- mysql:wordpress-mysql
environment:
- WORDPRESS_DB_HOST=wordpress-mysql.kontena.local
- WORDPRESS_DB_PASSWORD=secret
mysql:
image: mariadb:5.5
stateful: true
environment:
- MYSQL_ROOT_PASSWORD=secret
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
2015-05-30 12:52:44
Acabo de encontrar el Blog Tumtum y me topé con este párrafo en la documentación oficial de Docker. No se si me había perdido este párrafo todo el tiempo o si fue añadido recientemente, pero eso debería ser exactamente lo que necesito:)
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
2015-06-11 17:53:37