Cómo instalar MySQL con Docker y phpMyAdmin, paso a paso

Cómo instalar MySQL con Docker y phpMyAdmin, paso a paso

Con Docker se puede tener MySQL funcionando en el ordenador sin instalarlo en el sistema: un solo fichero describe la base de datos y la consola phpMyAdmin, se arranca con un comando y si es necesario se puede eliminar sin dejar rastro. Esta guía lo monta paso a paso, con los comandos y las salidas tal como se ven en pantalla.

En resumen: crea una carpeta con el fichero docker-compose.yml de esta guía, ejecuta docker compose up -d y tendrás MySQL en localhost:3306 y phpMyAdmin en http://localhost:8080. Los datos se guardan en un volumen y sobreviven aunque pares o borres los contenedores. Y un detalle que evita disgustos: usa --default-character-set=utf8mb4 con el cliente mysql o las tildes se guardarán mal.

Probado el 26 de octubre de 2026 con MySQL 9.7.4 (la versión de soporte largo más reciente), phpMyAdmin 5.2.3, Docker 28.5.1 y Docker Compose 2.40, en Docker Desktop. Los comandos son los mismos en Windows, macOS y Linux.

Qué necesitas

  • Docker instalado. En Windows y macOS, Docker Desktop; en Linux, Docker Engine con el complemento Compose. Las instrucciones oficiales están en docs.docker.com.
  • Una terminal: PowerShell o Terminal de Windows, la Terminal de macOS o la de tu distribución Linux.
  • Los puertos 3306 y 8080 libres. Si ya tienes un MySQL o un MariaDB instalado, mira el apartado de problemas frecuentes.

Para comprobar que Docker funciona:

docker --version
docker compose version

Paso 1. Crea la carpeta y el fichero docker-compose.yml

Crea una carpeta para el proyecto, por ejemplo mysql-docker, y dentro un fichero llamado docker-compose.yml con este contenido:

services:
  mysql:
    image: mysql:9.7
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: cambia-esta-clave-root
      MYSQL_DATABASE: tienda
      MYSQL_USER: app
      MYSQL_PASSWORD: cambia-esta-clave
    ports:
      - "127.0.0.1:3306:3306"
    volumes:
      - datos-mysql:/var/lib/mysql
    restart: unless-stopped

  phpmyadmin:
    image: phpmyadmin
    container_name: phpmyadmin
    environment:
      PMA_HOST: mysql
    ports:
      - "127.0.0.1:8080:80"
    depends_on:
      - mysql
    restart: unless-stopped

volumes:
  datos-mysql:

Qué hace cada parte:

Línea Para qué sirve
image: mysql:9.7 La imagen oficial de MySQL, rama 9.7, que es de soporte largo (LTS). Fijar la rama evita que una actualización te cambie de versión mayor sin avisar.
MYSQL_ROOT_PASSWORD La contraseña del administrador root. Guárdala para tareas de administración; para el día a día usa el usuario de la aplicación.
MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD Crean la base de datos tienda y un usuario app con todos los permisos sobre ella, la primera vez que arranca.
"127.0.0.1:3306:3306" Publica el puerto 3306 solo en tu ordenador. Sin el 127.0.0.1, cualquier equipo de tu red podría intentar conectarse.
datos-mysql:/var/lib/mysql Guarda los datos en un volumen de Docker, fuera del contenedor.
PMA_HOST: mysql Le dice a phpMyAdmin a qué servidor conectarse: el servicio mysql del mismo fichero.

Paso 2. Arranca los contenedores

Desde la carpeta del proyecto:

docker compose up -d

La primera vez tarda algo más porque descarga las imágenes y MySQL prepara sus ficheros. Comprueba que los dos contenedores están en marcha:

docker compose ps

NAME         IMAGE        STATUS          PORTS
mysql        mysql:9.7    Up 22 seconds   127.0.0.1:3306->3306/tcp
phpmyadmin   phpmyadmin   Up 20 seconds   127.0.0.1:8080->80/tcp

Paso 3. Comprueba que MySQL responde

En el registro del contenedor tiene que aparecer que el servidor acepta conexiones:

docker compose logs mysql

...
[Server] /usr/sbin/mysqld: ready for connections. Version: '9.7.4' ... port: 3306  MySQL Community Server - GPL.

Y puedes conectarte con el cliente mysql, que viene dentro del contenedor. Te pedirá la contraseña del usuario app:

docker compose exec mysql mysql --default-character-set=utf8mb4 -u app -p tienda -e "SELECT VERSION();"

Enter password:
VERSION()
9.7.4

Paso 4. Crea una tabla de ejemplo

Guarda estas sentencias en un fichero ejemplo.sql dentro de la carpeta del proyecto:

CREATE TABLE clientes (
  id     INT AUTO_INCREMENT PRIMARY KEY,
  nombre VARCHAR(80) NOT NULL,
  ciudad VARCHAR(40) NOT NULL,
  alta   DATE NOT NULL DEFAULT (CURRENT_DATE)
);

INSERT INTO clientes (nombre, ciudad) VALUES
  ('Ana García', 'Madrid'),
  ('Jordi Puig', 'Barcelona'),
  ('Lucía Pérez', 'Valencia');

SELECT id, nombre, ciudad FROM clientes ORDER BY id;

Y ejecútalas en la base de datos tienda. Como el contenido llega desde un fichero, la contraseña no se puede escribir en el teclado: se pasa con la variable MYSQL_PWD.

docker compose exec -T -e MYSQL_PWD=cambia-esta-clave mysql mysql --default-character-set=utf8mb4 -t -u app tienda < ejemplo.sql

+----+---------------+-----------+
| id | nombre        | ciudad    |
+----+---------------+-----------+
|  1 | Ana García    | Madrid    |
|  2 | Jordi Puig    | Barcelona |
|  3 | Lucía Pérez   | Valencia  |
+----+---------------+-----------+

No te saltes --default-character-set=utf8mb4. Al probar esta guía, el cliente mysql de la imagen se conectó por defecto con el juego de caracteres latin1, y los nombres con tilde se guardaron mal codificados: la «í» de «García» acabó ocupando cuatro bytes en lugar de dos. La tabla los mostraba casi bien, pero los datos ya estaban estropeados. Con la opción se guardan correctamente.

Paso 5. Entra en phpMyAdmin

Abre http://localhost:8080 en el navegador y entra con el usuario app y la contraseña de MYSQL_PASSWORD:

Pantalla de inicio de sesión de phpMyAdmin con el usuario app
Inicio de sesión en phpMyAdmin. Captura de Dataprix.

A la izquierda verás la base de datos tienda; al pulsar en la tabla clientes aparecen sus filas, con las tildes en su sitio. Desde la pestaña SQL puedes escribir y ejecutar consultas.

phpMyAdmin mostrando las tres filas de la tabla clientes de la base de datos tienda
La tabla de ejemplo en phpMyAdmin. Captura de Dataprix.

¿Por qué PMA_HOST: mysql y no localhost? phpMyAdmin corre en su propio contenedor, y para él localhost es ese contenedor. Dentro de la red que crea Docker Compose, cada servicio se alcanza por su nombre.

Paso 6. Conéctate desde tus aplicaciones

Las aplicaciones que corren en tu ordenador se conectan a localhost, porque el puerto está publicado ahí:

Host localhost (o 127.0.0.1)
Puerto 3306
Base de datos tienda
Usuario app
Cadena de conexión mysql://app:cambia-esta-clave@localhost:3306/tienda

Si la aplicación también va en un contenedor del mismo docker-compose.yml, usa como host mysql, igual que phpMyAdmin. Y configura su conexión con el juego de caracteres utf8mb4.

Paso 7. Parar, arrancar y borrar

Los datos viven en el volumen datos-mysql, no en el contenedor. Puedes parar y borrar los contenedores sin perderlos:

docker compose down
docker compose up -d
docker compose exec mysql mysqladmin -u app -p ping

mysqld is alive

Y la tabla sigue con sus tres filas. Para parar sin borrar los contenedores, docker compose stop, y para volver a arrancarlos, docker compose start.

Cuidado con docker compose down -v: la opción -v borra también el volumen, y con él todas las bases de datos. Úsala solo cuando quieras empezar de cero.

Problemas frecuentes

El puerto 3306 ya está en uso

Suele pasar si ya hay un MySQL o un MariaDB instalado en el sistema. Cambia el puerto de tu lado en el docker-compose.yml, por ejemplo a "127.0.0.1:3307:3306", y conéctate a localhost:3307. phpMyAdmin no cambia: habla con el contenedor por dentro de la red de Docker.

Las tildes y las eñes salen mal

Casi siempre es el juego de caracteres de la conexión, no el de la tabla. Usa --default-character-set=utf8mb4 con el cliente mysql y utf8mb4 en la cadena de conexión de tu aplicación. Si los datos ya se guardaron mal, lo más limpio es borrarlos y volver a cargarlos con la conexión correcta.

He cambiado la contraseña en el fichero y no funciona

Las variables MYSQL_* solo se aplican la primera vez, cuando el volumen está vacío. Después, la contraseña se cambia desde el propio MySQL, con ALTER USER, o borrando el volumen si no hay nada que conservar.

MySQL tarda en estar listo

En el primer arranque MySQL inicializa sus ficheros y crea la base de datos y el usuario; hasta que no aparece ready for connections en el registro, las conexiones fallan. Espera unos segundos y vuelve a probar.

Antes de usarlo en serio

Este montaje está pensado para desarrollo, pruebas y aprendizaje en tu propio ordenador. Para un servidor compartido o en producción conviene, como mínimo, poner contraseñas robustas guardadas fuera del fichero, no exponer los puertos ni phpMyAdmin a la red, programar copias de seguridad con mysqldump y mantener la imagen fijada en una rama de soporte largo.

Para seguir

Contenido elaborado con asistencia de inteligencia artificial — Equipo Editorial Dataprix. Verifica la información antes de tomar decisiones.