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:

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?

Author: Matthew Murdoch, 2015-05-30

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

 18
Author: xuhdev,
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

 143
Author: Hemerson Varela,
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)

https://blog.docker.com/media/2015/04/cnm-model.jpg

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 preferido

Puede 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
 12
Author: VonC,
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

 3
Author: Dolanor,
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
 1
Author: Lauri,
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:)

 0
Author: Patrick Gotthard,
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