Programming
October 28, 2021

Así fue como logré comunicar un container de Docker con otro 🐳

Mi solución fue simple: incrustar una API.

Cuando tienes una aplicación distribuida geográficamente en distintos servidores, con microservicios, se suelen usar APIs para comunicar las distintas partes del sistema. Pero en el caso de tener varios contenedores de Docker en una misma subred: ¿Cómo logramos comunicarlos?

Esta fue una de las primeras interrogantes a resolver al desarrollar mi VPN, que está basada en WireGuard.

Básicamente tengo un container de linuxserver/wireguard al cual mi bot de Telegram le envía comandos para crear configuraciones de VPN, y tengo distintos nodos de WireGuard en otros servidores, controlados por un proceso máster.

A la hora de querer comunicar mi container del bot con el de WireGuard, pensé en diferentes opciones, pero la que más lógica se sentía era crear una API dentro de WireGuard y exponerla en el propio contenedor, de forma que otros pudieran enviarle peticiones.

En este esquema, tenemos dos contenedores, uno que es el que desea comunicarse con el otro. Lo que hacemos es crear una API en el container que va a recibir las instrucciones, pudiendo incluso añadirle un nivel de autenticación. Las peticiones se harían por el protocolo HTTP, así que necesitamos un servidor web (Django, FastAPI, Flast, whatever…) y un puerto, en este ejemplo usé el 8008, pero puedes usar el que desees.

Show me the code 👨‍💻

En este ejemplo, crearemos una API usando Fast API para exponerla y que podamos enviarle comandos/instrucciones al container. Usamos un token para verificar si quien envía los comandos está autorizado, el token lo guardamos en una variable de entorno y verificamos cada petición contra ese token, si no coincide, no ejecutamos el comando y devolvemos una respuesta diciendo que se denegó la petición. Para la ejecución del comando sobre el container, usamos subprocess.

Luego creamos el archivo Dockerfile, que tendrá a linuxserver/wireguard como imagen base y sobre el cual instalaremos Python y las dependencias de Fast API, uvicorn, entre otras.

Cuando se levante el container, se ejecutará el proceso de Wireguard y se levantará la API usando el server de uvicorn. Exponemos entonces la VPN por el puerto 51820 y la API por el puerto 8008.

Una vez todo listo, creamos el archivo docker-compose.yml para levantar el servicio en producción.

Acabo de abrir el repositorio, te lo comparto por si quieres mirarlo. Ahí dentro están las dependencias en requirements.txt. No olvides crear el archivo .env y especificar el token y demás variables de entorno que necesita el container para levantarse.

Update: Muchas gracias a Reinier Hernández por contribuir en el repositorio y generalizarlo.

Más allá de este ejemplo específico, lo que quería era explicar esta forma de comunicar containers de Docker. Seguramente existan formas mejores, pero esta fue la que encontré. Siguiendo este ejemplo, puedes crear algo parecido para tu aplicación.

Espero te sea de utilidad, y si necesitas una VPN, puedes usar la mía.

Suscríbete a mi newsletter sobre startups y creatividad.