martes, 26 de julio de 2016

CONECTANDO CONTENEDORES DOCKER A TRAVÉS DE ENLACES

Este enfoque para conectar contenedores se basa en una abstracción que Docker llamada link (enlaces). Éste era el método preferido para conectar los contenedores antes de Docker 1.9 y sólo se recomienda si estamos utilizando una versión anterior de Docker. La vinculación de un contenedor a otro es un proceso simple que implica nombres de contenedor. Vamos a comenzar por crear un contenedor.

$ docker run -d --name mysql2 -e MYSQL_ROOT_PASSWORD=miclave123 mysql

Podíamos haber utilizado el contenedor creado anteriormente o si usamos el mismo nombre, debemos recordar que el nombre de contenedor debe ser único y si queremos crearlo con el mismo nombre, debemos borrarlo primero con el comando “docker rm”.

Hemos ejecutado una instancia de un nuevo contenedor mysql. Lo hemos nombrado mysql2 utilizando el parámetro –name. También podemos observar que no hemos publicado ningún puerto en el contenedor, vamos a ver enseguida el por qué.

 Vamos a ejecutar un contenedor con wordpress en él y enlazamos nuestro nuevo contenedor mysql2.

$ docker run --name wordpress1 -p 8081:80 --link mysql2:mysql -ti wordpress /bin/bash
root@ba2cf804e098:/var/www/html#

Este comando hace muchas cosas, estamos publicando el puerto 8081 utilizando el parámetro –p para que podemos acceder a nuestra aplicación web. Hemos utilizado un nuevo parámetro denominado –link. El parámetro –link crea un vínculo cliente-servicio entre dos contenedores. El parámetro tiene dos argumentos: el nombre del contenedor de enlace y un alias para el enlace. En este caso, estamos creando una relación con el cliente, nuestro contenedor wordpress1 es el cliente, con el contenedor mysql2, que es el “servicio”. También hemos añadido un alias para ese “servicio” de mysql. El alias nos permite acceder a la información expuesta constantemente sin necesidad de preocuparse por el nombre del contenedor subyacente. El enlace le da al contenedor de servicios la capacidad de comunicarse con el contenedor cliente y comparte algunos detalles de la conexión con ella, para ayudarle a configurar las aplicaciones para hacer uso de la conexión. También recibimos un beneficio relacionado con la seguridad de esta vinculación. Cuando lanzamos nuestro contenedor mysql2 no publicamos el puerto de mysql con el parámetro –p. No lo necesitamos, al vincular los contenedores juntos, estamos permitiendo que el contenedor de cliente pueda comunicarse con cualquier puerto publicado sobre el contenedor de servicios. Pero aún mejor, sólo los contenedores vinculados explícitamente a este contenedor que utilicen el parámetro –link pueden conectarse a este puerto. Teniendo en cuenta que el puerto no se publica en el host local, ahora tenemos un modelo de seguridad muy fuerte para limitar la superficie de ataque y la exposición a la red de una aplicación en contenedores.

Si nosotros lo deseamos por razones de seguridad, por ejemplo, podemos forzar a Docker para permitir sólo la comunicación entre los contenedores si existe un enlace. Para ello, se puede iniciar el demonio Docker con el parámetro --icc=false. Esto desactiva las comunicaciones entre todos los contenedores, a menos que exista una relación. Podríamos enlazar varios contenedores juntos. Por ejemplo, si se quiere utilizar nuestra instancia mysql2 para múltiples aplicaciones web, podríamos vincular cada contenedor de aplicaciones web para el mismo contenedor mysql.

También podemos especificar el parámetro --link varias veces para enlazar a varios contenedores. Docker no puede vincular entre contenedores en hosts Docker separados. Para la creación de redes multi-host, debemos utilizar las redes Docker o Docker Networking.

Por último, en lugar de ejecutar el contenedor como un demonio, hemos lanzado una sesión interactiva. Hemos hecho esto para poder ver como nuestros contenedores están vinculados. Los vínculos de Docker pueblan información sobre el contenedor de servicios en dos lugares:
·         En el archivo /etc/hosts
·         En las variables de entorno que contienen información de conexión.

Vamos a ver el archivo host:

root@ba2cf804e098:/var/www/html# cat /etc/hosts
172.17.0.4  ba2cf804e098
127.0.0.1   localhost
.  .  .
172.17.0.2  mysql 7b8bff74363c mysql2

Podemos ver que tenemos algunas entradas útiles aquí. La primera de ellas, es la dirección de nuestra propia IP de contenedor y el nombre de host (en este caso el ID corto de contenedor). La segunda entrada que ha sido generada por el parámetro --link, es la dirección IP, el nombre y la identificación del contenedor mysql, con el nombre de host adicional especificado como alias en el enlace. Vamos a tratar de hacer ping a ese contenedor ahora.

root@ba2cf804e098:/var/www/html# ping mysql
PING mysql (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.119 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.147 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.147 ms
.  .  .

El nombre de host de contenedor no tiene por que ser el ID corto, podríamos utilizar el parámetro –h o --hostname con el comando docker run para especificar un nombre de host especifico para el contenedor.

También podemos agregar entradas adicionales al fichero /etc/hosts cuando ejecutamos un contenedor utilizando el parámetro --add-host. Por ejemplo, podríamos querer añadir el nombre de host y la dirección IP del host que ejecuta Docker en nuestro contenedor.

$ docker run -p 80 --add-host=docker:10.0.0.1 --name web2 --link mysql:mysql2 …

Esto añadiría una entrada para un host llamado docker con una dirección IP 10.0.0.1 dentro del fichero /etc/hosts de nuestro contenedor.

Las direcciones IP de los contenedores cambian cuando se reinicia un contenedor, pero docker actualizará el fichero /etc/hosts del contenedor vinculado con la nueva IP.

Ahora ya tenemos conectividad con nuestro servidor mysql2, pero antes de usarlos vamos a ver más información de conexión contenida en nuestras variables de entorno. Vamos a ejecutar el comando env para ver las variables de entorno.

root@ba2cf804e098:/var/www/html# env
HOSTNAME=ba2cf804e098
MYSQL_ENV_MYSQL_ROOT_PASSWORD=miclave123
TERM=xterm
PHP_INI_DIR=/usr/local/etc/php
PHP_FILENAME=php-5.6.16.tar.xz
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP=tcp://172.17.0.2:3306
WORDPRESS_VERSION=4.4
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
GPG_KEYS=0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
PWD=/var/www/html
MYSQL_ENV_MYSQL_VERSION=5.7.10-1debian8
HOME=/root
SHLVL=1
PHP_SHA256=8ef43271d9bd8cc8f8d407d3ba569de9fa14a28985ae97c76085bb50d597de98
WORDPRESS_SHA1=d647a77c63f2ba06578f7747bd4ac295e032f57a
MYSQL_PORT_3306_TCP_PROTO=tcp
MYSQL_NAME=/wordpress1/mysql
MYSQL_PORT_3306_TCP_ADDR=172.17.0.2
PHP_EXTRA_BUILD_DEPS=apache2-dev
MYSQL_ENV_MYSQL_MAJOR=5.7
MYSQL_PORT=tcp://172.17.0.2:3306
PHP_VERSION=5.6.16
PHP_EXTRA_CONFIGURE_ARGS=--with-apxs2
_=/usr/bin/env

Podemos ver un montón de variables de entorno aquí, entre ellas algunas con el prefijo MYSQL. Docker crea automáticamente estas variables cuando vinculamos los contenedores wordpress y mysql. Comienzan con MYSQL, ya que es el alias que usamos cuando creamos nuestro enlace.

Las variables de entorno creadas automáticamente incluyen una variedad de información:
• El nombre de host del contenedor.
• El protocolo, IP y puerto del servicio que se ejecuta en el contenedor.
• Los protocolos específicos, IP, y los puertos de varios servicios que se ejecutan en el contenedor.
• Los valores de las variables de entorno especificadas al iniciar el contenedor.

Las variables precisas variarán de un contenedor a otro, dependiendo de lo que esté configurado en ese contenedor (por ejemplo, lo que se ha definido por la instrucción ENV y EXPOSE en el fichero Dockerfile del contenedor). Incluyen información que podemos usar dentro de nuestras aplicaciones para vincular consistentemente entre los contenedores.

Nuestra aplicación entonces tiene dos formas de conectar wordpress a mysql:
·         El uso de parte de la información de conexión en nuestras variables de entorno.
·         El uso de DNS y la información del fichero /etc/hosts

Veamos el primer método, nuestra aplicación podría leer de las variables de entorno MYSQL_PORT y podría usar la salida de host y puerto resultante para configurar la conexión mysql. Nuestra aplicación puede ahora utilizar esta información de conexión para encontrar mysql en un contenedor vinculado. Éste abstrae la necesidad de codificar una dirección IP y el puerto para proporcionar conectividad.

Alternativamente, existe el DNS local que es más flexible, que es la solución más habitual.


También podríamos configurar los servidores DNS para nuestros contenedores, utilizando el parámetro -dns y --dns-search en el comando docker run. Esto nos permite establecer la ruta de resolución de DNS y dominios de búsqueda locales. Si no se especifica, Docker utilizará la resolución de DNS que tenga configurada el anfitrión Docker.

No hay comentarios:

Publicar un comentario