Conectar dos contenedores Docker que tengan sus propios archivos Docker Compose
El contenedor proveedor crea una red Docker que puede ser utilizada por un contenedor consumidor.
Quería crear una red entre un contenedor de base de datos Docker y un contenedor de aplicación Docker , ambos con sus propios archivos Docker Compose . Y también quería asegurarme de hacerlo bien antes de implementar esto en los archivos docker-compose reales. Prueba primero bebé ...
También hice esto hace algún tiempo, pero tenía que mirar en esto de nuevo porque Docker Compose ahora tiene una opción de nombre en la sección de redes. Escribo este post para documentar cómo lo hice, espero que os sea útil también.
Dos contenedores y comandos para las pruebas
En esta configuración estoy usando dos contenedores:
- container#1: el contenedor de la base de datos
- container#2: el contenedor de la aplicación
Una buena herramienta para jugar con contenedores y redes es la imagen Busybox . Es pequeña y contiene un montón de comandos de red.
Contenedor de base de datos
El contenedor de la base de datos (el proveedor) debe contener un deamon que está escuchando las conexiones entrantes. En el contenedor de la aplicación (el consumidor) ejecutamos un programa que llama al deamon en el contenedor de la base de datos.
Para la escucha (un deamon de base de datos real está escuchando) primero probé el comando obvio netcat , por ejemplo cuando se escucha el puerto 1234:
nc -l -p 1234
Pero parecía que netcat terminaba cuando la conexión se cerraba (por telnet) y esto terminaba el contenedor. Netcat también tiene una opción persistente '-k' pero no funcionó, es un problema conocido. Parece que hay una versión mejor llamada ncat pero no está disponible en la imagen Busybox .
Por eso uso el comando httpd :
httpd -f -v -p 1234
Resumen, en el contenedor de base de datos utilizamos httpd como servicio de escucha.
Contenedor de aplicaciones
Desgraciadamente curl no está disponible en la imagen Busybox y el comando wget en Busybox no soporta otros puertos que no sean el 80. Por eso utilizo telnet en el contenedor de aplicaciones para conectarme al servidor httpd .
Por último, utilizo netstat para comprobar los puertos de escucha en los contenedores.
Los dos archivos docker-compose
El archivo de la base de datos docker-compose , db.yml
En el contenedor de la base de datos creamos el grafo 'postgres12_network'.
# db.yml
version: '3.7'
services:
postgres12:
image: busybox
container_name: postgres12_container
command: /bin/httpd -f -v -p 1234
networks:
- default
networks:
default:
name: postgres12_network
El archivo de la aplicación docker-compose , app.yml
En el contenedor de la aplicación consumimos la red 'postgres12_network'.
# app.yml
version: '3.7'
services:
app:
image: busybox
container_name: app_container
command: sleep infinity
networks:
- default
- postgres
networks:
postgres:
external:
name: postgres12_network
Probando el contenedor de la base de datos
Prepárate, aquí usamos muchas ventanas de terminal.
Abre una ventana de terminal, e inicia el contenedor de base de datos:
docker-compose -f db.yml up
Para comprobar si el contenedor está en marcha, abre otra ventana de terminal y escribe:
docker ps
Resultado:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ab28dc6d47b busybox "/bin/httpd -f -v -p…" 19 minutes ago Up 19 minutes postgres12_container
Para comprobar si la red Docker está creada, escribe:
docker network ls
Resultado:
NETWORK ID NAME DRIVER SCOPE
539decc283dd postgres12_network bridge local
En una tercera ventana de terminal entramos en el contenedor de la base de datos, utilizando exec, e iniciamos una sesión de shell (sh) :
docker-compose -f db.yml exec postgres12 /bin/sh
Comprobar si el deamon httpd está escuchando el puerto 1234:
netstat -l -t
Resultado:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:41825 0.0.0.0:* LISTEN
tcp 0 0 :::1234 :::* LISTEN
Conéctese ahora al deamon httpd :
telnet postgres12 1234
Resultado:
Connected to postgres12
En telnet, pulsa <ENTER> o escribe algo más y pulsa <ENTER>.
Resultado:
HTTP/1.1 408 Request Timeout
Date: Wed, 26 May 2021 11:42:22 GMT
Connection: close
Content-type: text/html
<HTML><HEAD><TITLE>408 Request Timeout</TITLE></HEAD>
<BODY><H1>408 Request Timeout</H1>
No request appeared within 60 seconds
</BODY></HTML>
Connection closed by foreign host
Puede parecer malo, pero en realidad tiene buena pinta, ¡tenemos una respuesta del deamon httpd !
En la primera ventana de la terminal debería aparecer un mensaje como
postgres12_container | [::ffff:192.168.48.2]:33264: response:400
Si intentas telnet con un puerto diferente, el mensaje será:
telnet: can't connect to remote host (192.168.48.2): Connection refused
Hasta aquí todo bien, pasemos al contenedor de aplicaciones.
Probando el contenedor de aplicaciones
Abre una ventana de terminal, e inicia el contenedor de aplicaciones:
docker-compose -f app.yml up
En otra ventana de terminal comprueba si el contenedor está en marcha, escribe:
docker ps
Resultado:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9df4c69b8772 busybox "sleep infinity" 58 seconds ago Up 57 seconds app_container
4ab28dc6d47b busybox "/bin/httpd -f -v -p…" 42 minutes ago Up 42 minutes postgres12_container
Los dos contenedores están en marcha ahora.
En otra ventana de terminal entramos en el contenedor de aplicación, usando exec, e iniciamos una sesión de shell (sh) :
docker-compose -f app.yml exec app /bin/sh
Comprueba si podemos conectarnos al deamon httpd en el contenedor de base de datos:
telnet postgres12 1234
Resultado:
Connected to postgres12
Muy bien, todo funciona como se espera.
Resumen
Es curioso (NO) que la pregunta que responde + sobre cómo conectar dos contenedores Docker tenga una gran cantidad de votos en Stack Overflow, ver enlaces abajo. Creo que la documentación en el sitio web de Docker ha mejorado mucho, pero necesita más ejemplos (triviales). La opción 'name' en la sección de redes facilita la definición de redes y la lectura de lo que ocurre en un archivo docker-compose .
Finalmente, Busybox es una imagen pequeña pero también muy limitada. Estaría bien que se añadieran más comandos de red.
Enlaces / créditos
BusyBox - The Swiss Army Knife of Embedded Linux
https://www.busybox.net/downloads/BusyBox.html
Communication between multiple docker-compose projects
https://stackoverflow.com/questions/38088279/communication-between-multiple-docker-compose-projects/38089080#38089080
netcat - keep listening for connection in Debian
https://superuser.com/questions/1008348/netcat-keep-listening-for-connection-in-debian
Networking in Compose
https://docs.docker.com/compose/networking/
Leer más
Docker Docker-compose
Recientes
- Cómo ocultar las claves primarias de la base de datos UUID de su aplicación web
- Don't Repeat Yourself (DRY) con Jinja2
- SQLAlchemy, PostgreSQL, número máximo de filas por user
- Mostrar los valores en filtros dinámicos SQLAlchemy
- Transferencia de datos segura con cifrado de Public Key y pyNaCl
- rqlite: una alternativa de alta disponibilidad y dist distribuida SQLite
Más vistos
- Usando Python's pyOpenSSL para verificar los certificados SSL descargados de un host
- Usando UUIDs en lugar de Integer Autoincrement Primary Keys con SQLAlchemy y MariaDb
- Conectarse a un servicio en un host Docker desde un contenedor Docker
- Usando PyInstaller y Cython para crear un ejecutable de Python
- SQLAlchemy: Uso de Cascade Deletes para eliminar objetos relacionados
- Flask RESTful API validación de parámetros de solicitud con esquemas Marshmallow