Mi Imagen y Volumen de MariaDB en Docker

Introducción

Quiero generar una imagen personalizada de MariaDB en Docker que pueda usar para crear más contenedores de MariaDB para posteriores pruebas en el ambiente Docker.

Prerrequisitos

Un anfitrión de Docker en cualquier Sistema Operativo. Nosotros estamos usando una virtual machine instance en Google Cloud Platform con Container Optimized OS el cual ya incluye el Docker 19.03.

Crear un Contenedor Base

Descargar la Imagen Oficial de MariaDB

Hagámos una búsqueda de imágenes de MariaDB en el Docker Hub y seleccionemos la imagen oficial:

pato@patocontainer ~ $ docker search mariadb
NAME                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mariadb                                MariaDB is a community-developed fork of MyS…   3476                [OK]

pato@patocontainer ~ $ docker pull mariadb
Using default tag: latest

pato@patocontainer ~ $ docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
mariadb               latest              ac9c11a18222        3 minutes ago       357MB

Crear un Volumen Nuevo

Sabemos que la imagen oficial utiliza un volume de Docker para guardar el datadir /var/lib/mysql esto es el directorio donde se almacenan todos los datos y binary logs. Entonces vamos a creae un volumen específico para guardar esos datos.

pato@patocontainer ~ $ docker volume create --name patovolmariadb
patovolmariadb

Construir un Contenedor a partir de la Imagen Oficial

Ahora vamos a crear un contenedor con el comando docker run usando la imagen pública oficial mariadb.
Estamos redireccionando el datadir hacia nuestro nuevo volumen y definimos el password del usuario root de MariaDB con la instrucción -e MYSQL_ROOT_PASSWORD.

pato@patocontainer ~ $ docker run -d --name patomariadb -v patovolmariadb:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=xxxxxx mariadb
e73e6f0a6f9aa645fdce67f05be80312942ed346ce3fc40714c9aadbbbd97c5b

pato@patocontainer ~ $ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
e73e6f0a6f9a        mariadb             "docker-entrypoint.s…"   12 seconds ago      Up 10 seconds       3306/tcp            patomariadb

pato@patocontainer ~ $ docker volume ls
DRIVER              VOLUME NAME
local               patovolmariadb

Acceso al Contenedor

Conectáte a nuestro recién creado contenedor con una sesión shell usando docker exec -it patomariadb bash:

pato@patocontainer ~ $ docker exec -it patomariadb bash
root@e73e6f0a6f9a:/# 

Instalación de Software

Primero actualizamos el Ubuntu, luego definimos la zona horaria y al final instalamos herramientas de edición y red:

root@e73e6f0a6f9a:/# apt update && apt upgrade -y
Get:1 http://ftp.osuosl.org/pub/mariadb/repo/10.4/ubuntu bionic InRelease [6265 B]

root@e73e6f0a6f9a:/# ln -fs /usr/share/zoneinfo/America/Mexico_City /etc/localtime

root@e73e6f0a6f9a:/# apt install -y vim nano net-tools iputils-ping
Reading package lists... Done

Crear Usuario de SO para Administración

Creemos un usuario para acceder y administrar el contenedor de MariaDB y así evitar usar root:

root@e73e6f0a6f9a:/# adduser pato
Adding user `pato' ...
Adding new group `pato' (1000) ...

Usuarios y Seguridad de la Base de Datos

Habilita la autenticación de unix sin password para el usuario root y asegura tu instalación con el procedimiento mysql_secure_installation:

root@e73e6f0a6f9a:/# mysql_secure_installation
Enter current password for root (enter for none):

Switch to unix_socket authentication [Y/n] Y
Change the root password? [Y/n] n

Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

Conéctate a la base de datos:

root@e73e6f0a6f9a:/# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 17
Server version: 10.4.13-MariaDB-1:10.4.13+maria~bionic mariadb.org binary distribution

MariaDB [(none)]> use mysql 

Crea un usuario de base de datos para nuestro usuario administrador con el plugin unix_socket para una conexión local sin password.

MariaDB [mysql]> CREATE USER 'pato'@'localhost' IDENTIFIED VIA unix_socket;

MariaDB [mysql]> GRANT ALL PRIVILEGES ON *.* TO 'pato'@'localhost' WITH GRANT OPTION;

Crea un usuario remoto que pueda conectarse desde cualquier lugar @'%':

MariaDB [mysql]> GRANT ALL PRIVILEGES ON *.* TO 'remoto'@'%' IDENTIFIED BY '********';

Crea un usuario para hacer respaldos con los permisos adecuados:

MariaDB [mysql]> GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT ON *.* TO respalda@localhost IDENTIFIED BY '********';

Crea un usuario para el monitor MaxScale con los privilegios aplicables:

MariaDB [mysql]> GRANT SELECT ON mysql.* TO 'maxpato'@'%' IDENTIFIED BY '********';

MariaDB [mysql]> GRANT SUPER, REPLICATION CLIENT, REPLICATION SLAVE, RELOAD, PROCESS, SHOW DATABASES, EVENT ON *.* TO 'maxpato'@'%';

y ejecuta flush privileges para que los nuevos permisos se activen:

MariaDB [mysql]> FLUSH PRIVILEGES;

Crear un Respaldo de la Base de Datos

Usando mysqldump genera un respaldo de la base de datos:

root@e73e6f0a6f9a:~# mysqldump --all-databases > initial-db.sql

Detener la Instancia

Ahora que nuestra instancia de MariaDB ha sido preparada vamos a detenerla ejecutando el comando mysqladmin:

root@e73e6f0a6f9a:~# mysqladmin shutdown

o mandando el comando docker stop para detener el contenedor:

pato@patocontainer ~ $ docker stop patomariadb
patomariadb

Crear nuestra Imagen a partir del Contenedor Personalizado

Finalmente hagamos commit a nuestro contenedor para crear una Imagen de Docker y la etiquetamos hacia nuestro repositorio patomx:

pato@patocontainer ~ $ docker commit patomariadb patomx/patomariadb
sha256:143534ffe233a383ef93aa9267deaae01a7fc6b0c309439e4fb5a5791c635a7f

pato@patocontainer ~ $ docker image ls
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
patomx/patomariadb    latest              143534ffe233        12 seconds ago      453MB
mariadb               latest              ac9c11a18222        53 minutes ago      357MB

pato@patocontainer ~ $ docker container rm patomariadb
patomariadb

y entonces con el comando push subamos nuestra imagen al Docker Hub:


pato@patocontainer ~ $ docker login --username=patomx
Password:
Login Succeeded

pato@patocontainer ~ $ docker push patomx/patomariadb
The push refers to repository [docker.io/patomx/patomariadb]
ab834738fc97: Pushed
...
latest: digest: sha256:
pato@patocontainer ~ $

Replicar la Instancia de MariaDB

Ahora que hemos generado nuestra Imagen de MariaDB patomx/patomariadb vamos a crear más Contenedores de MariaDB.

Generar Nuevo(s) Contenedor(es)

Para generar una nueva instancia de MariaDB envía el comando docker run usando nuestra imagen personalizada patomx/patomariadb.

pato@patocontainer ~ $ 
docker run -d --name patomariac1 --network pato-net -v patovolmc1:/var/lib/mysql patomx/patomariadb
162aae1fbb3cca423d488150f6b482cf9fe29b3b2266b49bd692e8618bc93ae3

pato@patocontainer ~ $ docker stop patomariac1
patomariac1

Recuerda que estamos usando pato-net nuestra Red Puente de Docker y también usamos una Etiqueta de Volumen de Docker para el directorio datadir /var/lib/mysql.

Clonar Datos Guardados hacia el Nuevo Contenedor

Y queremos que los datos generados en el contenedor original también sean copiados a este nuevo:

pato@patocontainer ~ $ docker run --rm -i -t -v patovolmariadb:/origen -v patovolmc1:/destino alpine sh -c "cp -avr /origen/* /destino"	
'/origen/aria_log.00000001' -> '/destino/aria_log.00000001'
'/origen/aria_log_control' -> '/destino/aria_log_control'
...

pato@patocontainer ~ $ docker start patomariac1
patomariac1

pato@patocontainer ~ $ docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS               NAMES
162aae1fbb3c        patomx/patomariadb   "docker-entrypoint.s…"   38 seconds ago      Up 33 seconds       3306/tcp            patomariac1

pato@patocontainer ~ $ docker volume ls
DRIVER              VOLUME NAME
local               patovolmc1
local               patovolmariadb

Y eso es todo, tenemos un nuevo contenedor clonado.

Validar nuestra Nueva Instancia

Personalizaciones del SO

En la imagen original instalamos software de edición y herramientas de red, validemos que estén presentes:

pato@patocontainer ~ $ docker exec -it patomariac1 bash
root@162aae1fbb3c:/# nano -V
 GNU nano, version 2.9.3

root@162aae1fbb3c:/# netstat -na | grep LISTEN | grep 3306
tcp6       0      0 :::3306                 :::*                    LISTEN

también creamos un respaldo, revisemos que aún este aquí:

root@162aae1fbb3c:/# ls /root/initial-db.sql
/root/initial-db.sql

¡Perfecto, nuestras personalizaciones a nivel sistema operativo persistieron!

Personalizaciones de la Base de Datos

Para validar la base de datos vamos a acceder a nuestro contenedor recién creado usando el usuario administrador pato y nos vamos a contectar sin contraseña a la base de datos, esta fue una de las personalizaciones que quiero preservar en mi Imagen:

pato@patocontainer ~ $ docker exec -it --user pato patomariac1 bash
pato@162aae1fbb3c:/$ mysql

MariaDB [(none)]>

ya conectados exitosamente también validemos que los usuarios creados previamente aun estén presentes en la base de datos:

MariaDB [(none)]> use mysql
Database changed

MariaDB [mysql]> select user, host, plugin from user;
+-------------+-----------+-----------------------+
| User        | Host      | plugin                |
+-------------+-----------+-----------------------+
| mariadb.sys | localhost | mysql_native_password |
| root        | localhost | mysql_native_password |
| pato        | localhost | unix_socket           |
| remoto      | %         | mysql_native_password |
| respalda    | localhost | mysql_native_password |
| replicador  | %         | mysql_native_password |
| maxpato     | %         | mysql_native_password |
+-------------+-----------+-----------------------+
7 rows in set (0.052 sec)

¡Perfecto, todos los datos fueron duplicados aquí desde nuestra Imagen personalizada!

Conclusión

Fuimos capaces de crear una imagen base personalizada de MariaDB para su duplicación futura. Como la imagen oficial es mínima nosotros agregamos herramientas de red y de edición. También aseguramos la instalación y creamos usuarios comunes.

Con nuestra propia Imagen y Volumen de Docker ahora podemos fácilmente crear nuevos contenedores de MariaDB para cluster y replicación, evitando volver a instalar y personalizar cada vez.