Cambiar tema

Guía completa de despliegue de MySQL con Docker: persistencia de datos y replicación maestro-esclavo

Easton editorial illustration: orchestration hub with branches

Ese mensaje de error en la terminal te clava en el pecho: quince días de datos de prueba, desaparecidos. Por la tarde reinicié el contenedor de MySQL, pensando que era un reinicio normal, y los datos se fueron con el contenedor.

Desplegar MySQL con Docker parece sencillo: docker run -e MYSQL_ROOT_PASSWORD=123456 mysql y listo. Pero cuando reinicias el contenedor y los datos desaparecen, el montaje de configuración no surte efecto, la app local no conecta o en producción hay que montar replicación maestro-esclavo — esos agujeros solo los conoces cuando los pisas. En este artículo vamos de la persistencia de datos a la replicación maestro-esclavo, con cada configuración explicada al detalle.

Fundamentos del despliegue de MySQL en instancia única con Docker

La forma más simple de arrancar (y por qué no la recomendamos)

Empecemos por el error más habitual. Mucha gente, la primera vez que instala MySQL con Docker, hace algo así:

docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0

Arranca, el contenedor está bien, entras y operas la base de datos: todo perfecto. Pero es una bomba de relojería.

¿Por qué? Los contenedores son efímeros por naturaleza. Si borras el contenedor o un día reinicias sin más, los datos se pierden. MySQL guarda los datos por defecto en /var/lib/mysql dentro del contenedor; al eliminar el contenedor, ese directorio desaparece.

La primera vez que caí en esta trampa pensé que MySQL tenía un bug. Luego entendí que no era MySQL: simplemente no había configurado persistencia de datos.

Persistencia de datos: montar volumes correctamente

En resumen, persistir datos es mapear el directorio de datos de MySQL al host para que, si el contenedor cae, los datos sigan ahí.

Docker ofrece tres formas de montaje:

  1. bind mount: mapeas un directorio del host, por ejemplo /home/mysql/data
  2. named volume: volumen gestionado por Docker, sin preocuparte de la ruta física
  3. tmpfs: almacenamiento en memoria; al reiniciar se pierde, casi no se usa

En 2024 Docker recomienda named volume; el rendimiento ya es muy parecido al bind mount. Yo uso ambos según el escenario: en desarrollo, named volume por comodidad; en producción, bind mount para facilitar backups.

Comando completo:

docker run --name mysql-persistent \
  -e MYSQL_ROOT_PASSWORD=rootpwd123 \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  -d mysql:8.0

Aquí -v mysql-data:/var/lib/mysql es la clave. mysql-data es el nombre del volume (Docker lo crea solo) y /var/lib/mysql es el directorio de datos dentro del contenedor.

Comprueba que la persistencia funciona de verdad:

# Entra al contenedor y crea una base de datos
docker exec -it mysql-persistent mysql -uroot -prootpwd123 -e "CREATE DATABASE testdb;"

# Para y elimina el contenedor
docker stop mysql-persistent
docker rm mysql-persistent

# Vuelve a arrancar con el mismo volume
docker run --name mysql-persistent \
  -e MYSQL_ROOT_PASSWORD=rootpwd123 \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  -d mysql:8.0

# Comprueba: testdb sigue ahí
docker exec -it mysql-persistent mysql -uroot -prootpwd123 -e "SHOW DATABASES;"

Si ves testdb, los datos se salvaron. Esa sensación da tranquilidad.

Montaje de configuración: parámetros personalizados de MySQL

Con la persistencia resuelta, el siguiente paso: ¿cómo cambiar la configuración de MySQL?

Por ejemplo, pasar el juego de caracteres a utf8mb4 o subir el máximo de conexiones. Sin montar un archivo de configuración, toca entrar al contenedor a mano cada vez y, al reiniciar, volver a empezar.

MySQL lee configuración adicional en /etc/mysql/conf.d/; basta con montar ahí tu my.cnf.

Crea el archivo en el host:

mkdir -p /home/mysql/conf
cat > /home/mysql/conf/my.cnf << 'EOF'
[mysqld]
# Juego de caracteres
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

# Conexiones
max_connections=1000

# Plugin de autenticación (ayuda con algunos clientes)
default_authentication_plugin=mysql_native_password

[client]
default-character-set=utf8mb4
EOF

Arranca el contenedor montando ese archivo:

docker run --name mysql-custom \
  -e MYSQL_ROOT_PASSWORD=rootpwd123 \
  -p 3306:3306 \
  -v /home/mysql/conf:/etc/mysql/conf.d \
  -v /home/mysql/data:/var/lib/mysql \
  -d mysql:8.0

Aquí montas dos cosas: configuración y datos.

Verifica que la configuración aplicó:

docker exec -it mysql-custom mysql -uroot -prootpwd123 -e "SHOW VARIABLES LIKE 'character%';"

Si character_set_server es utf8mb4, la configuración está activa.

Solucionar conexiones desde fuera del contenedor

El contenedor corre, los datos persisten y la config está montada. Conectas desde tu aplicación local y…

ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (Connection refused)

o

ERROR 1045 (28000): Access denied for user 'root'@'172.17.0.1'

Yo también me topé con estos dos errores y tardé un rato en entenderlos.

Problema 1: Connection refused

Casi siempre es el mapeo de puertos. Al arrancar el contenedor usa -p 3306:3306 para exponer el 3306 del contenedor en el host.

Si el 3306 del host ya está ocupado (por ejemplo, tienes MySQL instalado localmente), mapea otro puerto:

-p 3307:3306  # Accedes por 3307 en el host; dentro del contenedor sigue siendo 3306

Otra causa habitual es el firewall. En un servidor Linux:

# CentOS/RHEL
sudo firewall-cmd --zone=public --add-port=3306/tcp --permanent
sudo firewall-cmd --reload

# Ubuntu
sudo ufw allow 3306/tcp

Problema 2: Access denied

Es un tema de permisos. MySQL crea root por defecto solo para localhost; desde otra IP no entra.

Solución: cambiar el host de root a % (cualquier IP):

# Entra al contenedor
docker exec -it mysql-custom mysql -uroot -prootpwd123

# Ejecuta este SQL
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'rootpwd123';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Dos matices:

  1. El plugin mysql_native_password suele ir mejor con clientes antiguos
  2. En producción no hagas esto: no dejes que root conecte desde cualquier IP; crea usuarios dedicados y limita IPs

Tras el cambio, la aplicación externa debería conectar.

Con esto, el despliegue básico de MySQL en Docker en instancia única ya no debería darte grandes sorpresas.

Gestionar con Docker Compose de forma ordenada

Por qué recomendamos Docker Compose

Para desarrollo local, los docker run de antes bastan. En el día a día aparecen otros problemas:

  1. Comandos largos y difíciles de recordar
  2. Parámetros que se escriben mal (rutas de volume, etc.)
  3. En equipo, cada uno arranca distinto y la configuración se desordena
  4. Varios contenedores (MySQL + Redis + Nginx) y arrancarlos uno a uno es pesado

Ahí entra Docker Compose.

En la práctica, Compose mete esa cadena de docker run en un YAML. Arrancas con docker-compose up -d, paras con docker-compose down, y el archivo va al repositorio.

Un compañero nuevo pregunta «¿cómo levanto MySQL?» y le pasas el docker-compose.yml; clona, un comando y listo.

Configuración de MySQL en instancia única con Compose

Configuración completa, línea a línea:

version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql-standalone
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpwd123
      MYSQL_DATABASE: myapp
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppwd123
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./conf/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./logs:/var/log/mysql
    networks:
      - mysql-network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-prootpwd123"]
      interval: 10s
      timeout: 5s
      retries: 3

volumes:
  mysql-data:

networks:
  mysql-network:
    driver: bridge

Detalle de lo importante:

environment:

  • MYSQL_ROOT_PASSWORD: contraseña de root, obligatoria
  • MYSQL_DATABASE: base que se crea al arrancar
  • MYSQL_USER y MYSQL_PASSWORD: usuario normal (más seguro que root)

volumes:

  • mysql-data:/var/lib/mysql: persistencia con named volume
  • ./conf/my.cnf:/etc/mysql/conf.d/my.cnf: configuración con ruta relativa
  • ./logs:/var/log/mysql: logs en el host para depurar

restart: always: reinicio automático del contenedor y tras reiniciar el servidor

healthcheck: ping periódico a MySQL; si falla, reinicio

networks: red propia para que varios contenedores se hablen entre sí

Pasos de uso:

  1. Crea la estructura de carpetas:
mkdir -p mysql-docker/{conf,logs}
cd mysql-docker
  1. Crea conf/my.cnf:
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
max_connections=1000
default_authentication_plugin=mysql_native_password

[client]
default-character-set=utf8mb4
  1. Crea docker-compose.yml (el de arriba)

  2. Arranca:

docker-compose up -d
  1. Estado:
docker-compose ps

Verás algo así:

       Name                     Command                  State                 Ports
------------------------------------------------------------------------------------------------
mysql-standalone      docker-entrypoint.sh mysqld      Up (healthy)    0.0.0.0:3306->3306/tcp

Fíjate en (healthy): el healthcheck pasó.

  1. Logs:
docker-compose logs -f mysql

-f sigue el log en tiempo real, como tail -f. Si algo falla al arrancar, suele estar en los logs.

  1. Parar y quitar contenedores:
docker-compose down

Solo borra contenedores, no el volume (los datos siguen). Para borrar también los datos:

docker-compose down -v  # ¡Cuidado! Borra todos los datos

En desarrollo local casi siempre uso Compose: configuras una vez y arrancar/parar es un comando.

Replicación maestro-esclavo lista para producción

Idea rápida de la replicación maestro-esclavo de MySQL

¿Para qué montar replicación?

MySQL en una sola máquina vale para proyectos pequeños; con más carga se queda corto. La replicación resuelve sobre todo dos cosas:

  1. Separación lectura/escritura: el maestro escribe (INSERT, UPDATE, DELETE) y los esclavos leen (SELECT). Muchas apps leen más de lo que escriben; repartir lecturas entre esclavos mejora el rendimiento
  2. Copia de seguridad y disponibilidad: si cae el maestro, el esclavo puede seguir sirviendo lecturas al menos

La idea es simple:

  • El maestro (Master) activa binlog y registra cambios
  • El esclavo (Slave) se conecta al maestro y lee el binlog
  • En el esclavo, un hilo IO trae el binlog al relay log y un hilo SQL ejecuta esas sentencias
  • Así los cambios del maestro llegan al esclavo

En Docker, básicamente:

  1. Dos contenedores con server-id distintos
  2. Binlog activo en el maestro
  3. El esclavo se enlaza al maestro e inicia la replicación

Suena complejo, pero con Compose suele ser arrancar y listo.

Configuración del nodo Master

El maestro necesita: binlog, server-id y usuario de replicación.

  1. Archivo conf/master.cnf:
[mysqld]
# ID único; maestro y esclavo no pueden repetirse
server-id=1

# Log binario
log-bin=mysql-bin

# Formato ROW: registra cambios fila a fila, más seguro
binlog-format=ROW

# Juego de caracteres
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

# Opcional: bases a replicar (sin esto, todas)
# binlog-do-db=myapp

# Opcional: bases a excluir
# binlog-ignore-db=mysql
# binlog-ignore-db=information_schema
  1. docker-compose del maestro:
version: '3.8'

services:
  mysql-master:
    image: mysql:8.0
    container_name: mysql-master
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpwd123
      MYSQL_DATABASE: myapp
    ports:
      - "3306:3306"
    volumes:
      - master-data:/var/lib/mysql
      - ./conf/master.cnf:/etc/mysql/conf.d/master.cnf
      - ./logs/master:/var/log/mysql
    networks:
      - mysql-replication

volumes:
  master-data:

networks:
  mysql-replication:
    driver: bridge
  1. Arranca el maestro:
docker-compose up -d mysql-master
  1. Usuario de replicación:
docker exec -it mysql-master mysql -uroot -prootpwd123
-- Crear usuario de replicación
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'replpwd123';

-- Permisos de replicación
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

FLUSH PRIVILEGES;

-- Estado del maestro: anota File y Position
SHOW MASTER STATUS;

SHOW MASTER STATUS devuelve algo como:

+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      156 |              |                  |
+------------------+----------+--------------+------------------+

Importante: guarda File y Position; los necesitas en el esclavo.

Configuración del nodo Slave

  1. Archivo conf/slave.cnf:
[mysqld]
# ID único, distinto del maestro
server-id=2

# Relay log
relay-log=relay-bin

# Solo lectura en el esclavo (evita escrituras accidentales)
read-only=1

# Juego de caracteres
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
  1. Añade el esclavo al docker-compose.yml:
version: '3.8'

services:
  mysql-master:
    image: mysql:8.0
    container_name: mysql-master
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpwd123
      MYSQL_DATABASE: myapp
    ports:
      - "3306:3306"
    volumes:
      - master-data:/var/lib/mysql
      - ./conf/master.cnf:/etc/mysql/conf.d/master.cnf
      - ./logs/master:/var/log/mysql
    networks:
      - mysql-replication

  mysql-slave:
    image: mysql:8.0
    container_name: mysql-slave
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpwd123
    ports:
      - "3307:3306"  # En el host accedes al esclavo por 3307
    volumes:
      - slave-data:/var/lib/mysql
      - ./conf/slave.cnf:/etc/mysql/conf.d/slave.cnf
      - ./logs/slave:/var/log/mysql
    networks:
      - mysql-replication
    depends_on:
      - mysql-master

volumes:
  master-data:
  slave-data:

networks:
  mysql-replication:
    driver: bridge
  1. Arranca el esclavo:
docker-compose up -d mysql-slave
  1. Enlaza el esclavo al maestro:
docker exec -it mysql-slave mysql -uroot -prootpwd123
-- Conexión al maestro (sustituye File y Position por los tuyos)
CHANGE MASTER TO
  MASTER_HOST='mysql-master',           -- Nombre del contenedor maestro en la red Docker
  MASTER_PORT=3306,
  MASTER_USER='repl',
  MASTER_PASSWORD='replpwd123',
  MASTER_LOG_FILE='mysql-bin.000003',   -- De SHOW MASTER STATUS
  MASTER_LOG_POS=156;                   -- De SHOW MASTER STATUS

START SLAVE;

SHOW SLAVE STATUS\G

Verificar la sincronización maestro-esclavo

En SHOW SLAVE STATUS\G mira sobre todo:

Slave_IO_Running: Yes       # Hilo IO; debe ser Yes
Slave_SQL_Running: Yes      # Hilo SQL; debe ser Yes
Seconds_Behind_Master: 0    # Retraso en segundos; 0 = en tiempo real
Last_IO_Error:              # Vacío = bien
Last_SQL_Error:             # Vacío = bien

Si Slave_IO_Running y Slave_SQL_Running son Yes, la replicación está activa.

Prueba real:

  1. Datos en el maestro:
docker exec -it mysql-master mysql -uroot -prootpwd123 -e "
USE myapp;
CREATE TABLE test_table (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO test_table VALUES (1, 'test data');
"
  1. Consulta en el esclavo:
docker exec -it mysql-slave mysql -uroot -prootpwd123 -e "
USE myapp;
SELECT * FROM test_table;
"

Si ves la fila insertada, la sincronización funciona.

Depuración de problemas frecuentes

La primera vez suele haber tropiezos. Los más habituales:

Problema 1: Slave_IO_Running es No

Posibles causas:

  • Red: comprueba que comparten red; docker exec -it mysql-slave ping mysql-master
  • Usuario repl mal creado o sin permisos
  • MASTER_LOG_FILE o MASTER_LOG_POS incorrectos: vuelve a SHOW MASTER STATUS

Problema 2: Slave_SQL_Running es No

Posibles causas:

  • Error SQL: mira Last_SQL_Error
  • Datos distintos entre maestro y esclavo: si el maestro ya tenía datos, exporta del maestro, importa en el esclavo y luego configura replicación

Problema 3: Seconds_Behind_Master siempre alto

Posibles causas:

  • Esclavo con pocos recursos: CPU, RAM, disco
  • Mucha escritura en el maestro: más esclavos
  • Red lenta: revisa latencia

Si no avanzas, reinicia la configuración del esclavo:

-- En el esclavo
STOP SLAVE;
RESET SLAVE;

-- Vuelve a CHANGE MASTER TO y START SLAVE

Optimización de rendimiento y buenas prácticas

Recomendaciones de rendimiento para MySQL en Docker

Muchos temen que Docker ralentice MySQL. Hace años era más cierto; en 2024 el impacto suele quedar por debajo del 5 % y en cargas intensivas de I/O casi no se nota.

Aun así, conviene optimizar:

1. Tipo de volume

  • named volume: Docker elige el driver; cómodo en desarrollo
  • bind mount: directorio del host; mejor en producción (backup y monitorización)
# named volume
volumes:
  - mysql-data:/var/lib/mysql

# bind mount
volumes:
  - /data/mysql:/var/lib/mysql

2. Modo de red

La red bridge por defecto suele bastar. Si buscas el máximo rendimiento, prueba host:

services:
  mysql:
    network_mode: "host"  # Red del host; mejor rendimiento

Con host no hace falta ports; el contenedor escucha directamente el 3306 del host.

3. Límites de recursos

En producción limita recursos para que MySQL no se coma el servidor:

services:
  mysql:
    image: mysql:8.0
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          memory: 1G

Necesitas docker-compose --compatibility up o Docker Swarm.

4. Gestión de logs

Sin límite, los logs del contenedor pueden llenar el disco:

services:
  mysql:
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "3"

Lista de buenas prácticas en producción

Resumen de lo que aprendí a base de errores.

Seguridad:

  1. No uses contraseñas por defecto o débiles
# ❌ No hagas esto
MYSQL_ROOT_PASSWORD: 123456

# ✅ Contraseña fuerte o Docker secrets
MYSQL_ROOT_PASSWORD: "Mx8#kL9$pQ2@vN4!"
  1. Docker secrets para datos sensibles
services:
  mysql:
    image: mysql:8.0
    secrets:
      - mysql_root_password
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password

secrets:
  mysql_root_password:
    file: ./secrets/mysql_root_password.txt
  1. Restringir acceso de red
networks:
  mysql-network:
    driver: bridge
    internal: true  # Solo entre contenedores, sin acceso externo

Si hace falta acceso externo, usa un contenedor de aplicación como proxy; no expongas MySQL directamente.

Operaciones:

  1. Backup periódico del directorio de datos
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
docker exec mysql-master mysqldump -uroot -prootpwd123 --all-databases > backup_$DATE.sql

# O backup del directorio de datos
tar -czf mysql-data-backup_$DATE.tar.gz /data/mysql/

En producción, backup diario automático y al menos 7 días de retención.

  1. Healthcheck para monitorizar
healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
  interval: 10s
  timeout: 5s
  retries: 3
  start_period: 30s

Reinicio automático si cae; mejor con alertas.

  1. Volume aparte para logs
volumes:
  - ./logs:/var/log/mysql

Logs fuera del volume de datos: más fácil depurar y no llenas los datos.

Alta disponibilidad:

  1. Al menos un maestro y un esclavo; a menudo un maestro y varios esclavos

Con mucha lectura, 3–5 esclavos reparten SELECT.

  1. Balanceo para lectura/escritura

MySQL Router, ProxySQL o lógica en la aplicación:

  • Escritura (INSERT/UPDATE/DELETE) → maestro
  • Lectura (SELECT) → esclavos con balanceo
  1. Prueba periódica del failover

No esperes a que caiga el maestro para descubrir que el esclavo no sirve:

-- En el esclavo
STOP SLAVE;
RESET SLAVE ALL;
SET GLOBAL read_only=0;  -- Quita solo lectura y promueve a maestro

En producción, soluciones maduras (MHA, Orchestrator) para conmutación automática.

Conclusión

Repasemos lo esencial.

Desde el despliegue básico de MySQL en Docker, persistencia, montaje de configuración y conexión externa, hasta Docker Compose y replicación maestro-esclavo en producción: este flujo cubre los escenarios habituales.

Puntos clave:

  1. La persistencia es obligatoria; no corras MySQL en un contenedor «desnudo»
  2. Monta la configuración; juego de caracteres y conexiones conviene dejarlos listos desde el principio
  3. Docker Compose es la norma; configuración centralizada y mejor para el equipo
  4. La replicación no es tan difícil; lo crítico es el archivo de config y el orden de los pasos
  5. En producción, seguridad y backups; contraseñas fuertes y copias regulares

Todo el código de configuración de este artículo lo he probado y puedes copiarlo a tu proyecto cambiando contraseñas y puertos.

Si es tu primera vez con MySQL en Docker, empieza por instancia única: entiende persistencia y montaje de config antes de la replicación. Paso a paso.

Si algo falla, en los logs suele estar la pista. Si te atasacas, comenta y respondo cuando pueda.

Docker para MySQL suele ser mucho más cómodo que el despliegue tradicional: configuras una vez y corre en cualquier sitio.

Flujo completo de despliegue de MySQL con Docker

Desde la persistencia de datos hasta la replicación maestro-esclavo: soluciona pérdida de datos al reiniciar, montaje de configuración y fallos de conexión

⏱️ Estimated time: 1 hr

  1. 1

    Step 1: Despliegue en instancia única: persistencia y montaje de configuración

    Persistencia de datos:
    • Monta el directorio de datos con Volume:
    docker run -d -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
    • Montaje de archivo de configuración:
    docker run -d -v mysql-data:/var/lib/mysql -v ./my.cnf:/etc/mysql/conf.d/my.cnf -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
    • Variables de entorno:
    MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD

    Verificar persistencia:
    • Tras eliminar y recrear el contenedor, los datos siguen ahí
  2. 2

    Step 2: Configuración de replicación maestro-esclavo

    Configurar el maestro:
    • Activar binlog: en my.cnf configurar log-bin=mysql-bin
    • Definir server-id: server-id=1
    • Crear usuario de replicación:
    CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
    GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

    Configurar el esclavo:
    • Indicar la dirección del maestro:
    CHANGE MASTER TO
    MASTER_HOST='master',
    MASTER_USER='repl',
    MASTER_PASSWORD='password',
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=0;
    • Iniciar replicación: START SLAVE;
    • Verificar estado: SHOW SLAVE STATUS\G;
  3. 3

    Step 3: Solución de problemas comunes y despliegue en producción

    Problemas frecuentes:
    • Fallo de conexión: revisar mapeo de puertos -p 3306:3306, red y firewall
    • Pérdida de datos: configurar persistencia con Volume
    • Juego de caracteres: en my.cnf character-set-server=utf8mb4
    • Permisos: revisar permisos del Volume chmod 755

    Despliegue en producción:
    • Gestionar varios contenedores con docker-compose
    • Configurar healthcheck
    • Límites de recursos (deploy.resources)
    • Estrategia de copias de seguridad (backup periódico del Volume)
    • Usar Volume con nombre para facilitar la gestión

FAQ

¿Cómo evitar la pérdida de datos al desplegar MySQL con Docker?
Persistencia de datos:

1) Montar el directorio de datos con Volume:
docker run -d -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0

2) Montaje de archivo de configuración:
docker run -d -v mysql-data:/var/lib/mysql -v ./my.cnf:/etc/mysql/conf.d/my.cnf -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0

3) Variables de entorno:
• MYSQL_ROOT_PASSWORD
• MYSQL_DATABASE
• MYSQL_USER
• MYSQL_PASSWORD

Verificar persistencia: elimina el contenedor y créalo de nuevo; los datos siguen ahí.

Causa raíz:
Al reiniciar el contenedor se pierden los datos porque Docker guarda los datos en la capa del contenedor por defecto; al borrar el contenedor desaparecen. Hay que configurar persistencia.
¿Cómo configurar la replicación maestro-esclavo de MySQL?
Configurar el maestro:
1) Activar binlog (en my.cnf: log-bin=mysql-bin)
2) Definir server-id (server-id=1)
3) Crear usuario de replicación:
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

Configurar el esclavo:
1) Indicar la dirección del maestro:
CHANGE MASTER TO
MASTER_HOST='master',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
2) Iniciar replicación: START SLAVE;
3) Verificar estado: SHOW SLAVE STATUS\G;
¿Cómo solucionar fallos de conexión a MySQL en Docker?
Problemas frecuentes:
• Fallo de conexión: revisar mapeo de puertos -p 3306:3306, red y firewall
• Pérdida de datos: configurar persistencia con Volume
• Juego de caracteres: en my.cnf character-set-server=utf8mb4
• Permisos: revisar permisos del Volume chmod 755

Pasos de comprobación:
1) Confirmar que el contenedor está en ejecución (docker ps)
2) Revisar mapeo de puertos (docker port container-name)
3) Revisar la red (docker network inspect network-name)
4) Ver logs del contenedor (docker logs container-name)

14 min de lectura · Publicado el: 18 dic 2025 · Actualizado el: 21 ago 2026

Comentarios

Inicia sesión con GitHub para dejar un comentario

Easton BlogEaston Blog