
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:
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.
¿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
- Ficha de MySQL: qué es, licencia, arquitectura, alternativas y versiones con soporte.
- Radar de versiones de MySQL: hasta cuándo recibe parches cada versión.
- Cómo instalar PostgreSQL con Docker y pgAdmin, la misma guía para el otro gran motor open source.
Contenido elaborado con asistencia de inteligencia artificial — Equipo Editorial Dataprix. Verifica la información antes de tomar decisiones.
