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
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 reddisconnect
hace la operación opuesta a la anterior, es decir, desconecta un contenedor de una redcreate
es el comando que debes utilizar para crear una redinspect
te permite obtener información detallada de una redls
es el comando a utilizar para ver las redes que tienesprune
es el comando con el que borrará todas las redes que no estés utilizandorm
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