DEV Community

Cover image for MySQL 8 en Docker de manera fácil y para toda la familia
Lito
Lito

Posted on • Edited on

MySQL 8 en Docker de manera fácil y para toda la familia

Estaba yo por aquí con mi feliz vida de programador y usuario Linux (GNU/Linux para los puristas) cuando de repente se muestra ante mí una situación que no sucede de manera habitual (dentro de mi bonito mundo): Necesitar dos versiones diferentes de un mismo servicio corriendo al mismo tiempo y sin entrar en conflicto.

Como usuario Linux siempre he tenido opciones sencillas para disponer de versiones de cierto software según necesidades, o bien no depender de versiones.

Servicios como Apache, nginx o Redis, con tener siempre la última ya vas servido. Otros como PHP o PostgreSQL puedes instalar todas las versiones que quieras sin que entren en conflicto entre sí, pero con MySQL no hay esa posibilidad "sencilla".

Para un nuevo proyecto necesitaba MySQL 8 ya que dispone de muchas mejoras en funcionalidades de geoposicionamiento, a parte de un mejor rendimiento en general cuando se trabaja con gran cantidad de datos, así que finalmente opté por la vía Docker.

Si no te metes en fregaos, es bastante más sencillo de lo que parece :)

Estos son los pasos a seguir:

# Instalamos los paquetes necesarios desde los repositorios oficiales de Ubuntu
$> sudo apt install docker.io

# Iniciamos el servicio
$> sudo systemctl start docker

# Activamos Docker al inicio del sistema
$> sudo systemctl enable docker

# Descargamos la imagen de MySQL
$> sudo docker pull mysql/mysql-server

# Creamos un volumen para almacenar los datos de manera persistente
# La localización será /var/lib/docker/volumes/mysql-8-data
$> sudo docker volume create mysql-8-data

# Iniciamos la instancia con la última versión de MySQL 8
# Mapeamos el puerto 3307 de nuestra máquina para 3306 de Docker
# Asignamos el volumen anterior para que las bases de datos sean persistentes
$> sudo docker run \
    -p 3307:3306 \
    -v mysql-8-data:/var/lib/mysql \
    --name mysql-8 \
    --restart always \
    -d mysql/mysql-server:latest

# Esperamos unos segundos y veremos la contraseña que se genera durante la instalación
$> sudo docker logs mysql-8 2>&1 | grep GENERATED
[Entrypoint] GENERATED ROOT PASSWORD: exTeNg0L9uMuquwWyP4DaebPAdr

# Accedemos por bash de Docker a la instalación
$> sudo docker exec -it mysql-8 bash

# Nos autenticamos en MySQL usando las credenciales de los logs (exTeNg0L9uMuquwWyP4DaebPAdr)
bash-4.2# mysql -uroot -p

# Creamos un usuario root para conexión externa a Docker con contraseña diferente
mysql> CREATE USER 'root'@'%' IDENTIFIED BY '!dC^:kI4*wT:|UE';
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

# Ups! no podemos, debemos actualizar primero nuestro usuario y mantenemos la contraseña
mysql> ALTER USER USER() IDENTIFIED BY 'exTeNg0L9uMuquwWyP4DaebPAdr';
Query OK, 0 rows affected (0.03 sec)

# Ahora sí, creamos un usuario root para conexión externa a Docker con contraseña diferente
mysql> CREATE USER 'root'@'%' IDENTIFIED BY '!dC^:kI4*wT:|UE';
Query OK, 0 rows affected (0.04 sec)

# Le asignamos los privilegios de puto amo
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
Query OK, 0 rows affected (0.03 sec)

# Creamos la base de datos de nuestro proyecto
mysql> CREATE DATABASE `project` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Query OK, 1 row affected (0.06 sec)

# Creamos el usuario con el que nos autenticaremos en ella desde nuestra aplicación
mysql> CREATE USER 'project'@'%' IDENTIFIED WITH mysql_native_password BY '*43i0;l+6=7:*lA';
Query OK, 0 rows affected (0.04 sec)

# Le asignamos los permisos
mysql> GRANT ALL PRIVILEGES ON `project`.* TO 'project'@'%';
Query OK, 0 rows affected (0.02 sec)

mysql> exit

bash-4.2# exit

# Probamos la conexión desde fuera de Docker con la contraseña de usuario (*43i0;l+6=7:*lA)
# Recuerda indicar el puerto de esta instalación con -P3307
$> mysql --protocol=tcp -P3307 -uproject -p project

Tal y como indica @frandieguez , podemos pasarle directamente los parámetros a MySQL para comenzar con unos ya preestablecidos por nosotros, simplemente hay que lanzar docker run de la siguiente manera:

$> sudo docker run \
    -p 3307:3306 \
    -v mysql-8-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=XXXX -e MYSQL_USER=XXXX -e MYSQL_DATABASE=XXXX \
    --name mysql-8 \
    --restart always \
    -d mysql/mysql-server:latest \

Si todo ha ido bien (que debería) pues ya tenemos una instancia Docker en nuestro equipo/servidor que nos provee de MySQL 8.

Si necesitas toquetear la configuración de MySQL no podrás hacerlo directamente desde docker shell ya que no dispone de editor.

La solución más sencilla (para mí) es la siguiente:

# Copiamos el fichero de configuración desde el contenedor a nuestro equipo
$> sudo docker cp mysql-8:/etc/my.cnf my.cnf

# Editamos la configuración a nuestro gusto
$> sudo vi my.cnf

# Pasamos de nuevo el fichero al contenedor
$> sudo docker cp my.cnf mysql-8:/etc/my.cnf

# Reiniciamos el contenedor
$> sudo docker restart mysql-8

Así ya tendremos nuestro MySQL totalmente customizado.

Enjoy!

Top comments (4)

Collapse
 
frandieguez profile image
Fran Diéguez • Edited

Boas lito,

podes aforrar alguns pasos da configuracion empregando as ENV vars MYSQL_USER, MYSQL_PASSWORD e MYSQL_DATABASE no momento de arrincar por primeira vez o container


$> sudo docker run -p 3307:3306 -e MYSQL_ROOT_PASSWORD=XXXX -e MYSQL_USER=XXXX -e MYSQL_DATABASE=XXX -v mysql-8-data:/var/lib/mysql --name=mysql-8 -d mysql/mysql-server:latest

Ademais eu para editar o /etc/mysql/my.cnf montariao como volume cara fora.

-v ./custom.cnf:/etc/mysql/conf.d/config-file.cnf
Collapse
 
lito profile image
Lito • Edited

Sí, o primeiro comentario íbao engadir tamén como opción posible, pero quería evitar no posible complicar a instalación/configuración. Así xa ven co usuario por defecto root e co contrasinal seguro.

O segundo, casi igual, tes que buscar un lugar local donde montalo e acordarte que o tes montado aí. Total para un par de veces que se toca ese arquivo, pois casi nin vale a pena.

Gracias polos comentarios! así tamén quedan como achega para o resto de usuarios :)

Collapse
 
xcause profile image
Xcause

se puede establacer que la aplicación tenga otra dirección del mismo entorno de la red local?
digamos como si fuera una máquina más con las mismas direcciones del dhcp de la intranet?

Collapse
 
lito profile image
Lito

Sí, pero no es nada sencillo.

Aquí tienes un artículo que detalla como implementarlo blog.codeaholics.org/2013/giving-d...

Suerte!