networking - networks - Cómo comunicarse entre contenedores Docker a través de "hostname"
docker network restart (6)
Acabo de encontrar el blog de Tumtum y me topé con este párrafo en la documentación oficial de Docker . No sé si me había perdido este párrafo todo el tiempo o si se había agregado recientemente, pero eso debería ser exactamente lo que necesito :)
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 contenedor) entre los contenedores como en una red de servidor tradicional?
Editar: después de Docker 1.9, el comando de
docker network
Docker (consulte a continuación
https://.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 esté 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
Hasta donde yo sé, al usar solo Docker, esto no es posible. Necesita algunos DNS para asignar ip del contenedor a los nombres de host.
Si quieres una solución lista para usar.
Una solución es utilizar, 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 se puede acceder a cada servicio mediante
service_name.kontena.local-address
.
Aquí hay un ejemplo simple del archivo YAML de la aplicación Wordpress donde el servicio Wordpress se conecta al servidor MySQL con la dirección wordpress-mysql.kontena.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
La nueva función de red le permite conectarse a contenedores por 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) Contenedor de ping 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
Vea this sección de la documentación;
Nota: a
diferencia de los
links
heredados, la nueva red
no
creará variables de entorno ni compartirá variables de entorno con otros contenedores.
Esta característica actualmente no admite alias
Para eso debería ser
--link
, al menos para la parte del nombre de host.
Con
docker 1.10 y PR 19242
, eso sería:
docker network create --net-alias=[]: Add network-scoped alias for the container
(ver la última sección a continuación)
Eso es lo que
actualiza los
detalles del
archivo
/etc/hosts
Además de las variables de entorno, Docker agrega una entrada de host para el contenedor de origen al
/etc/hosts
.
Por ejemplo, inicie un servidor LDAP:
docker run -t --name openldap -d -p 389:389 larrycai/openldap
Y defina una imagen para probar 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:
docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest
Luego, si escribe ''lds'', ese alias funcionará:
ldapsearch -H ldap://internalopenldap ...
Eso devolvería a la gente.
Lo que significa que
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
publicación
del
blog
.
Introdujo una arquitectura más completa, con el modelo de red de contenedores (CNM)
Eso actualizará la Docker CLI con nuevos comandos de "red" y documentará cómo se usa el indicador "
-net
" para asignar contenedores a las redes.
docker 1.10 tiene una nueva sección Alias de ámbito de red , ahora github.com/docker/docker/blob/… :
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 de que un contenedor sea descubierto por un nombre alternativo por cualquier otro contenedor dentro del alcance de una red en particular.
A diferencia del alias de enlace, que está definido por el consumidor de un servicio, el alias de ámbito de red está 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=[]
Agregar 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 los contenedores que están conectados a una red. Los contenedores en pausa permanecen conectados y pueden ser revelados por una inspección de la red. Cuando se detiene el contenedor, no aparece en la red hasta que lo reinicie.
Si se especifica, las direcciones IP del contenedor se vuelven a aplicar cuando se reinicia un contenedor detenido. 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 contenedor 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
EDITAR : ya no es sangrienta: http://blog.docker.com/2016/02/docker-1-10/
Respuesta original
Luché con eso toda la noche.
Si no le teme a la vanguardia, la última versión del
motor
Docker
y
Docker compose
implementan libnetwork.
Con el archivo de configuración correcto (que debe colocarse en la versión 2), creará servicios que todos se verán. Y, además, puede escalarlos con docker-compose también (puede escalar cualquier servicio que desee que no se una al puerto en el host)
Aquí hay un file ejemplo
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 de componer archivo: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md