Comunicación entre contenedores e introducción a Docker Compose.
Anteriormente vimos como se trabaja con un contenedor de Docker. En este
capítulo vamos a ir un poco más allá y ver como podemos trabajar con varios
contenedores que además estén conectados entre si. Para ello vamos a
utilizar con un ejemplo práctico que es como enlazar un contenedor que tenga
phpMyAdmin con uno que este ejecutando Mysql o
Mariadb.
1.1 Requisitos.
Para poder ejecutar contenedores de Docker lo primero es tener Docker
Community Edition (CE) instalado. Puedes ver como hacerlo en el
capitulo que previamente vimos sobre Docker. En este ejemplo yo estoy trabajando en una maquina con Linux.
1.2 Enlazar un contenedor PhpMyAdmin con otro que contenga MariaDB o
MySQL.
Lo primero que tenemos que hacer es descargar las imágenes de Docker Hub de
PhpMyAdmin
y de por ejemplo
MariaDB.
y
Para conectar dos contenedores podemos hacerlo de dos formas.
1.2.1 Usando el parámetro --link.
Los enlaces permiten que los contenedores se reconozcan entre si y
transfieran información de forma segura de un contenedor a otro. Para crear
un enlace utilizaremos el parámetro --link.
docker run -d \
--rm \
--name mibase \
-p 3306:3306 \
-e MARIADB_ROOT_PASSWORD=contraseña \
mariadb:latest
Una vez que el contenedor de Mariadb esta en ejecución procedemos a
crear el contenedor de PhpMyAdmin.
docker run -d \
--rm \
--name phpmyadminc \
--link mibase \
-e PMA_HOST=mibase \
-p 8080:80 \
phpmyadmin
La variable de entorno PMA_HOST, como nos dice las instrucciones que
podemos encontrar en docker hub sobre PhpMyAdmin nos sirve para indicar el
nombre del contenedor al que nos queremos conectar desde PhpMyAdmin.
Con el parámetro --link hemos creado un enlace entre ambos
contenedores
Para comprobar que todo funciona bien, abrimos un navegador web y accedemos
a la dirección:
En este caso, tal como especificamos, usando el usuario root y el password
"contraseña" nos debería funcionar bien.
1.2.1 Usando un "user-defined bridge network".
Para empezar creamos el "user-defined bridge network"
docker network create mi_red
La idea es que los contenedores usen esa red que hemos creado como puente
de comunicación entre ellos.
Por tanto ejecutamos el contenedor para Mariadb de una forma muy
parecida a como lo hicimos anteriormente, solo que especificando que usen
"mi_red" como medio de comunicación.
docker run -d \
--rm \
--name mibase \
--network mi_red \
-p 3306:3306 \
-e MARIADB_ROOT_PASSWORD=contraseña \
mariadb:latest
y hacemos lo mismo con el contenedor de PhpMyAdmin especificando
también que use como puente de comunicación "mi_red" y también no olvidemos
la variable de entorno "PMA_HOST"
docker run -d \
--rm \
--name phpmyadminc \
--network mi_red \
-e PMA_HOST=mibase \
-p 8080:80 \
phpmyadmin
Para comprobar que todo funciona bien volvemos a abrir un navegador web y
entramos en la siguiente dirección http:/localhost:8080. Si todo va bien nos
saldrá la pantalla de phpmyadmin en donde podremos loguearnos.
Al igual que podemos eliminar los contenedores, también podemos eliminar la
conexión de red que hemos creado. Para ello basta con teclear el siguiente
comando:
En los ejemplos anteriores al cerrar los contenedores se nos perdía la
información. Vamos a ver ahora un ejemplo en el que usaremos ambos
contenedores pero usando persistencia de datos, es decir que cuando cerremos
los contenedores la base que creemos quede guardada en nuestro
ordenador.
1.3 Ejemplo de uso con persistencia de datos de PhpMyAdmin y MariaDb.
En los ejemplos anteriores al cerrar los contenedores perdíamos toda la
información, desaparecían las bases de datos que hubiésemos creado. En este
ejemplo vamos a hacer los mismo, pero de forma que la información sobre la
base de datos que creemos, se guarde de unas sesiones a otras.
Con el argumento -v vinculamos un directorio que esta en nuestro ordenador
con el directorio de destino en el contendor. Como los datos de las bases de
datos en el contenedor se guardan en el directorio /var/lib/mysql para
vincularlos ejecutaré la siguiente sentencia pero entrando primeramente en
el directorio de mi ordenador donde quiero que se guarden los datos (o
vincular mejor dicho). En vez de usar "$(pwd)" también se puede poner
directamente el directorio absoluto a donde queremos vincular los
datos.
docker run -d \
--rm \
--name mibase \
-p 3306:3306 \
-e MARIADB_ROOT_PASSWORD=contraseña \
-v $(pwd):/var/lib/mysql \
mariadb:latest
Creamos un contenedor con PhpMyAdmin que esté enlazado con el contenedor
anterior.
docker run -d \
--rm \
--name phpmyadminc \
--link mibase \
-e PMA_HOST=mibase \
-p 8080:80 \
phpmyadmin
Para ver si funciona entramos en phpmyadmin y creamos una nueva base
de datos. Yo la llamaré "mibasededatos"
Ahora cerramos todo y volvemos a hacer lo mismo, para ver si se han
vinculado correctamente los datos y la base de datos que hemos creado no ha
desaparecido al cerrar los contenedores. No obstante si entras en el
directorio del ordenador que has elegido para vincular los datos verás como
antes estaba vacío y ahora contiene los datos que se han ido
vinculando.
Efectivamente, ahí sigue la base de datos que hemos creado. Ya que el
directorio local esta vinculado con el del contenedor automáticamente.
Tal como nos dice la
documentación de Microsoft para VS Code, Docker-Compose
es una herramienta desarrollada para ayudar a definir y compartir
aplicaciones entre varios contenedores. Tan solo es necesario crear un
archivo YAML para definir los servicios y, con un solo comando, ponerlo todo
en marcha o eliminarlo.
1.4.1 Instalación de Docker Compose.
Lo primero es ejecutar la siguiente instrucción para descargar la versión
estable de Docker-Compose:
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Luego le damos permisos de ejecución al binario que nos hemos
descargado.
$ sudo chmod +x /usr/local/bin/docker-compose
Para finalizar comprobamos que la instalación haya finalizado
correctamente:
$ docker-compose --version
docker-compose version 1.29.2, build 5becea4c
1.4.2. Creación del archivo docker-compose.yml con Mariadb y
PhpMyAdmin.
1.- En la raíz del proyecto de la aplicación, crearemos un archivo
llamado docker-compose.yml con el que ejecutaremos dos servicios
Mariadb y PhpMyAdim.
2.- En el archivo de Compose, lo primero que tenemos que definir es la
versión del esquema del archivo YAML que vamos a utilizar. En la mayor parte
de los casos lo mejor es utilizar la última versión. Podemos consultar las
versiones de esquema y sus compatibilidades en la
referencia de archivos de Compose.
Archivo docker-compose.yml
version: "3.8"
3.- A continuación, definimos la lista de servicios o contenedores que
queremos ejecutar como parte de la aplicación. Podemos poner el nombre de
los servicios como nosotros queramos. En este caso lo típico sería usar como
nombre de servicio Mariadb y PhpMyAdmin pero para ver que podemos cambiar de
nombre usaremos miBase y miPhpmyadminc. El nombre que utilicemos para los
servicios, que hemos elegido libremente, se convertirá automáticamente en un
alias de red, lo que nos será muy útil al definir el servicio para
Mariadb.
Archivo docker-compose.yml
version: "3.8"
services:
miBase:
miPhpmyadminc:
4.- Lo siguiente a hacer es ir pasando o traducir todas las instrucciones
que hemos usado anteriormente para ejecutar los contenedores a este archivo.
Por ejemplo para crear ejecutar MariaDb y PhpmyAdmin con persistencia de
datos usamos las siguientes instrucciónes.
docker run -d \
--rm \
--name mibase \
-p 3306:3306 \
-e MARIADB_ROOT_PASSWORD=contraseña \
-v $(pwd):/var/lib/mysql \
mariadb:latest
docker run -d \
--rm \
--name phpmyadminc \
--link mibase \
-e PMA_HOST=mibase \
-p 8080:80 \
phpmyadmin
Ahora en el archivo yaml en el que hemos puesto el nombre de los servicios,
tenemos que poner que imágenes se van a utilizar.
Archivo docker-compose.yml
version: "3.8"
services:
miBase:
image: mariadb:latest
miPhpmyadminc:
image: phpmyadmin:latest
Para traducir los puertos, cambiamos el argumento -p por la clave "ports" de la siguiente forma:
Archivo docker-compose.yml
version: "3.8"
services:
miBase:
image: mariadb:latest
ports:
- 3306:3306
miPhpmyadminc:
image: phpmyadmin:latest
ports:
- 8080:80
Continuamos traduciendo las variables de entorno que utilizan cada uno de
los contenedores. En vez del argumento -e utilizamos la clave
"environment"
Archivo docker-compose.yml
version: "3.8"
services:
miBase:
image: mariadb:latest
ports:
- 3306:3306
environment:
- MARIADB_ROOT_PASSWORD=contraseña
miphpmyadminc:
image: phpmyadmin:latest
ports:
- 8080:80
environment:
- PMA_HOST=miBase
Como hemos usado persistencia de datos para guardar las bases de datos que
creemos en el directorio que estemos trabajando del ordenador, sustituimos
el argumento -v por la clave "volumes". Si hubiésemos especificado un
directorio de trabajo en Docker utilizaríamos la clave "working_dir" aunque
en este ejemplo no es el caso.
Una cosa importante es que cuando usamos docker run para ejecutar los
contenedores, se crea automáticamente el volumen con su nombre. Pero esto no
sucede cuando se ejecuta Compose. Aquí tenemos que definir el volumen
en la sección volumes: de
nivel superior, y después, especificar el punto de montaje en la
configuración del servicio. Para que se usen las opciones predeterminadas
solo se tiene que proporcionar el nombre del volumen. Pero hay
muchas más opciones disponibles.
IMPORTANTE: cuando ejecutamos en los ejemplos anteriores
docker run con la opcion -v
para tener persistencia de datos, utilice $(pwd) para que se creara la
sincronización dentro del directorio con el que estamos trabajando. Sin
embargo esto no funciona en docker Compose que se basa en python. Podemos
hacer la persistencia de otra forma que también nos valdría para el
caso de que usemos
docker run que es creando un
volumen de docker.
Para crear un volumen de Docker usamos la instrucción:
$ docker volume create Nombre_del_volumen
Por ejemplo, yo para usar en el archivo yaml crearé uno llamado
"almacen"
$ docker volume create almacen
Esto creará un espacio donde se sincronizarán los datos en nuestro disco
local, fuera del contenedor o contenedores. Para obtener información y poder
localizar donde están los archivos podemos usar:
$ docker volume inspect almacen
[
{
"CreatedAt": "2021-09-19T18:59:27+02:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/almacen/_data",
"Name": "almacen",
"Options": {},
"Scope": "local"
}
]
Tenemos
opciones para
crear, inspeccionar, listar o eliminar los volúmenes que hayamos creado, lo
mismo que para los contenedores.
Así nuestro archivo yaml para persistencia quedaría de la siguiente
forma.
Archivo docker-compose.yml
version: "3.8"
services:
miBase:
image: mariadb:latest
ports:
- 3306:3306
environment:
- MARIADB_ROOT_PASSWORD=contraseña
volumes:
- almacen:/var/lib/mysql
miPhpmyadminc:
image: phpmyadmin:latest
ports:
- 8080:80
environment:
- PMA_HOST=miBase
volumes:
almacen:
Para finalizar usamos la clave
depends_on para indicar al
servicio miPhpmyadminc que no se ejecute hasta que el servicio
miBase se haya iniciado.
Archivo docker-compose.yml
version: "3.8"
services:
miBase:
image: mariadb:latest
ports:
- 3306:3306
environment:
- MARIADB_ROOT_PASSWORD=contraseña
volumes:
- almacen:/var/lib/mysql
miPhpmyadminc:
image: phpmyadmin:latest
ports:
- 8080:80
environment:
- PMA_HOST=miBase
depends_on:
- miBase
volumes:
almacen:
5.- Para ejecutar nuestro archivo docker-compose.yml ejecutamos,
desde donde este se encuentre:
$ docker-compose up -d
En donde la opcion -d es para que se ejecute en segundo plano.
Para comprobar que funciona volvemos a abrir el navegador web, ir al
localhost:8080 y ver si podemos logearnos en Phpmyadmin y crear nuestra base
de datos que conservará los datos una vez hayamos cerrado los
contenedores.
Otros comandos útiles que podemos utilizar con Docker-compose son:
- docker-compose up crea y
ejecuta una colección de contenedores.
-
docker-compose stop detiene
los contenedores.
-
docker-compose start inicia
los contenedores.
-
docker-compose down detiene
y retira los contenedores.