Introducción

Hasta ahora, hemos trabajado con un solo contenedor y lo hemos accedido localmente. Pero a medida que avanzamos hacia casos de uso más realistas, necesitaremos acceder al contenedor desde el mundo exterior, compartir almacenamiento externo dentro del contenedor, comunicarnos con contenedores que se ejecutan en otros hosts, y así sucesivamente. En este capítulo, aprenderemos a cumplir con algunos de esos requisitos. Comencemos por entender la configuración de red predeterminada de Docker y luego pasaremos a casos de uso avanzados.

Cuando el demonio de Docker se inicia, crea un puente de Ethernet virtual con el nombre docker0. Tal vez podamos obtener más información sobre docker0 utilizando el comando ip addr en el sistema que ejecuta el demonio de Docker:

Diagrama

Como podemos ver, docker0 tiene la dirección IP 172.17.0.1/16. Docker elige aleatoriamente una dirección y una subred de un rango privado definido en RFC 1918 (https://tools.ietf.org/html/rfc1918). Utilizando esta interfaz de puente, los contenedores pueden comunicarse entre sí y con el sistema host.

Por defecto, cada vez que Docker inicia un contenedor, crea un par de interfaces de Ethernet virtuales y luego realiza las siguientes acciones con el par:

  • Conecta un extremo del par veth a la interfaz de puente docker0 en el host de Docker, llamemos a este extremo el extremo del host

  • Conecta el otro extremo del par veth al contenedor recién creado como su interfaz eth0, llamemos a este extremo del par veth el extremo del contenedor

Comencemos un contenedor y examinemos las direcciones IP de sus interfaces de red:

Diagrama

En la captura de pantalla anterior, el extremo del contenedor del par veth se llama eth0@if17, donde 17 es el índice de interfaz del extremo del host del par veth. Podemos utilizar este índice para identificar el extremo del host del par veth en el host de Docker. La interfaz eth0 del contenedor se le asigna la dirección IP 172.17.0.3, que pertenece a la subred docker0, es decir, 172.17.0.1/16.

Ahora, echemos un vistazo a la interfaz en el índice decimoséptimo:

Diagrama

Aquí, el extremo del host de la interfaz veth se llama vethe8b40b8@if16, donde 16 es el índice de interfaz del extremo del contenedor del par veth. Dado que la interfaz en el índice 16 se asigna al espacio de nombres de red del contenedor, no se muestra en el host de Docker. El motor de Docker genera automáticamente el nombre del extremo del host del par veth generando un número hexadecimal de siete dígitos y luego lo agrega a la cadena veth. En este ejemplo, e8b40b8 es el número aleatorio generado por el motor de Docker. El motor de Docker también garantiza que este número aleatorio sea único dentro del host de Docker. Si se observa detenidamente, también se puede notar que el extremo del host de la interfaz veth está unido al puente docker0.

Ahora crearemos algunos contenedores más y examinaremos el puente docker0 utilizando el comando de administración de puente de Ethernet de Linux, brctl.

NOTA

La distribución de Linux Ubuntu no suele incluir la herramienta brctl, por lo que debemos instalar el paquete bridge-utils o aprovechar una de las características útiles de Docker que nos permite compartir la pila de red del host de Docker con el contenedor de Docker, como se describe en la receta Conectar contenedor a la red del host.

Aquí, estamos utilizando la opción --network=host del comando docker container run para conectarnos a la pila de red del host de Docker. Dado que la imagen alpine viene con la herramienta de comando brctl, elegiremos iniciar nuestro contenedor con la imagen alpine y ejecutar el comando brctl show para mostrar los detalles del puente, como se muestra en la siguiente captura de pantalla:

Diagrama

Evidentemente, todos los extremos del host de los pares veth están unidos al puente docker0 predeterminado. Además de configurar el puente docker0, Docker también crea reglas NAT de iptables, para que todos los contenedores puedan comunicarse con el mundo exterior de forma predeterminada, pero el mundo exterior no puede comunicarse con los contenedores. Veamos las reglas NAT en el host de Docker:

Diagrama

En la salida anterior, se configura una regla POSTROUTING para la subred 172.17.0.0/16. El único propósito de esta regla es cambiar la dirección IP de origen de los paquetes de datos que se originan en la subred 172.17.0.0/16 a la dirección IP del host. Aparentemente, la subred 172.17.0.0/16 se asigna a nuestro puente docker0. Esencialmente, esta regla POSTROUTING permite que los contenedores de Docker se conecten al mundo exterior, como se puede ver en la siguiente salida de traceroute:

Diagrama

Genial, ¿verdad? Sin embargo, de forma predeterminada, Docker no realiza ninguna configuración de red para que el mundo exterior se conecte a los contenedores. Sin embargo, cuando se hospeda un servicio dentro del contenedor, debe ser accesible desde el mundo exterior. La receta Acceder a contenedores desde el exterior demuestra cómo abrir el servicio que se ejecuta dentro del contenedor al mundo exterior. Además, tenemos otras recetas que se centran en varios aspectos de la red de contenedores de un solo host.

NOTA

Para obtener más información sobre los diferentes tipos de redes que discutimos en la sección anterior, visite: https://docs.docker.com/network/.

En este capítulo, nos centramos solo en la red de contenedores de un solo host. Junto con las redes de contenedores de un solo host, también examinaremos cómo compartir y persistir datos en el paradigma del contenedor.