Redes en Docker

Este es uno de los capítulos del tutorial Tutorial de Docker. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.

Inicialmente, en este tutorial sobre docker, empezaste manejando contenedores independientes, que no tenían ninguna relación con otros contenedores. Si bien, en el episodio 8 viste que había posibilidades de orquestar contenedores, es decir, que los contenedores se podían relacionar unos con otros. Posteriormente, en el episodio anterior, viste que podías compartir almacenamiento entre contenedores. En este nuevo capítulo, verás que no solo puedes compartir almacenamiento, sino que también puedes compartir la misma red, de forma que sea mas sencillo relacionar unos contenedores con otros. Así, en este capítulo darás unos primeros pasos de redes en Docker.

Redes en Docker

Redes en Docker

Existen diferentes tipos de redes en Docker y con diferentes usos y funcionalidades. En principio me voy a centrar únicamente en dos, dejando para futuros tutoriales el resto de redes.

Para este tutorial, vas a utilizar una imagen de alpine. Lo cierto es que tendrás que levantar tantos contenedores como sean necesarios para ver como se relacionan unos con otros, y que sentido tienen esto de las redes.

Gestión de redes en Docker

Antes de adentrarte en esto de las redes en Docker, te indico los comandos que tienes a tu alcance para gestionar las redes,

  • connect te permitirá conectar un contenedore a un red
  • disconnect hace la operación opuesta a la anterior, es decir, desconecta un contenedor de una red
  • create es el comando que debes utilizar para crear una red
  • inspect te permite obtener información detallada de una red
  • ls es el comando a utilizar para ver las redes que tienes
  • prune es el comando con el que borrará todas las redes que no estés utilizando
  • rm te permite borrar una o mas redes

Tipos de controladores de red en Docker

Existen diferentes tipos controladores de red (network drivers) en Docker.

  • driver este es el controlador por defecto. Es el que en condiciones normales tienes que utilizar para conectar contenedores entre si. Por esta razón es la mejor solución para conectar contenedores que se encuentran corriendo en el mismo anfitrión.
  • host este tipo de controlador elimina el aislamiento entre el contenedor y el anfitrión.
  • overlay. Permite conectar diferentes contenedores en diferentes nodos.
  • macvila permite asingar una dirección MAC a un contenedor.
  • none inhabilita todas las redes.

A parte, es posible instalar complementos de terceros.

¿Que tienes ahora mismo?

Primero ejecuta docker network ls. Verás que tienes tres redes actualmente levantadas,

NETWORK ID          NAME                DRIVER              SCOPE
71a745e5a64f        bridge              bridge              local
710dfcf36358        host                host                local
510679f5fa28        none                null                local

Como ves el nombre de cada una de estas redes se corresponde con el driver, para que no haya lugar a confusión.

Por otro lado, ejecuta ip a. Verás el siguiente resultado, aunque te muestro de forma resumida para no ocupar mas de lo debido con información inútil. Bueno, mejor te muestro el resultado de ip -o link show | awk -F": " '{print $2}'

lo
wlp2s0
docker0

Si, tienes una nuevo interfaz de red docker0.

Dos contenedores independientes o casi….

Ahora levanta dos contenedores, en principio un alpine, aunque puedes hacerlo con cualquier otra distro. Te indico alpine, por aquello de que es ligerito.

docker run -dit --rm --name alpine1 alpine sh
docker run -dit --rm --name alpine2 alpine sh

Un par de observaciones por recordar conceptos que viste en capítulos anteriores. La opción -dit es para levantar el contenedor detached e interactivo. Mientras que la opción --rm, lo que hará será que al detener el contenedor se borre automáticamente.

Ejecuta ahora docker network inspect bridge. Verás que en el apartado Containers están listados los dos contenedores alpine1 y alpine2, con sus respectivas IP. En mi caso 172.17.0.1 y 172.17.0.2.

Si haces ping desde el anfitrión, host, ping 172.17.0.1, verás que tienes respuesta. Lo mismo que si lo haces con alpine2. Ahora bien, si intentas ping alpine1, te indicará el error Fallo temporal en la resolución del nombre.

Un paso más allá…

Entra en el primer contenedor docker attach alpine1. Si haces ping contra el segundo contenedor ping 172.17.0.2, verás que obtienes respuesta. Sin embargo, al igual que en el caso anterior, si haces ping alpine2, te devolverá el mismo error.

Para salir del contenedor si detenerlo ejecuta Ctrl+p Ctrl+q.

Detén el segundo contendor, operación con la que lo vas a borrar, por el simple hecho de que lo has definido así al iniciarlo, y vuelve a levantarlo con la siguiente opción,

docker run -dit --rm --name alpine2 --link alpine1 alpine sh

Entra ahora en el contenedor docker attach alpine2 y haz un ping al primer contenedor, pero, esta vez utilizando su nombre ping alpine1… Si se resuelve el nombre. Pero si lo haces al revés, es decir desde el primer contenedor, verás que en este caso, es incapaz de resolver el nombre.

Por ahora, ya hemos terminado con estos contenedores, así que detenlos. Recuerda que como los has iniciado con la opción rm, no va a ser necesario que los borres a posteriori.

docker stop $(docker ps -q)

Creando redes

Ahora, en lugar de utilizar la red por defecto, vas a crear tu propia red, y posteriormente levantar los correspondientes contenedores. Así, para crear la red, utiliza la siguiente instrucción,

docker network create --driver bridge red1

Una vez creada, levanta los dos contenedores, pero esta vez utilizando las siguientes instrucciones,

docker run -dit --rm --name alpine1 --network red1 alpine sh
docker run -dit --rm --name alpine2 --network red1 alpine sh

Si ahora ejecutas docker network inspect red1, verás que están definidos los dos contenedores como pertenecientes a esta red. De hecho, si entras en el contenedor 1 docker attach alpine1 y haces un ping al segundo contenedor, pero esta vez por nombre, en lugar de por IP, ping alpine1, verás que si obtinienes respuesta, lo mismo, para el caso de que entres en el primero de los contenedores.

Un contenedor en dos redes Docker

Por supuesto, puedes tener un contenedor conectado a dos redes Docker. Para ello, crea una nueva red con la definición que has visto anteriormente,

docker network create --driver bridge red2

Ahora levanta un tercer contenedor que tenga una pata en esta red,

docker run -dit --rm --name alpine3 --network red2 alpine sh

Y conecta este tercer contenedor alpine3 con la primera de las redes red1. Para hacer esto, ejecuta la siguiente instrucción,

docker network connect red1 alpine3

Así tienes el contenedor alpine3 con una pata en cada una de las redes red1 y red2. De esta manera desde este contendor puedes hacer ping a los otros dos contenedores. Pero, si levantamos otro contenedor mas que esté en esta seguna red y que solo esté conectado con alpine3, no verá a los otros contenedores, vamos allá,

docker run -dit --name alpine4 --network red2 alpine sh

Así si intentas hacer ping desde alpine3 a cualquier otro docker, ya sea directamente por su nombre o por la IP, verás que tienes respuesta de cualquiera de ellos. Si por el contrario, lo intentas hacer desde este último contenedor alpine4, verás que solo te responde alpine3, tanto por IP como por nombre. Si intentas hacer ping desde alpine4 a alpine1 ó alpine2, verás que ninguno de los dos te da respuesta, ni por IP ni por nombre.

Una vez hayas terminado de jugar con todos los contenedores, tan solo tienes que hacer docker stop $(docker ps -q), y se detendrán y borrarán todos los contenedores. Y lo único que te resta por hacer es borrar las redes. Esto último, es tan sencillo como ejecutar docker network prune, que borrará todas las redes que no se estén utilizando excepto a las que están por defecto.

La red host

Como he indicado anteriormente, puedes conectar un contendor a la red host, de forma que estará directamente accesible desde el anfitrión. Para probar esto, utiliza un contenedor de nginx. Así, ejecuta la siguiente instrucción,

docker run -d --rm --name nginx1 --network host nginx

Ahora en tu navegador dirígete a localhost. Verás que aparece la pantalla de bienvenidad de Nginx. Los puertos expuestos de tu contenedor están ahí.

Si intentas levantar un segundo contenedor Nginx en la red host, verás que no es posible.

Conclusión

Con esto tienes una primera visión de las posibilidades que te ofrecen las redes más básicas de Docker. A partir de aquí deja correr tu imaginación para las puertas que se te abren para hacer casi cualquier cosa que puedas imaginar.


Más información,

Imagen de portada de Alina Grubnyak en Unsplash

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *