Objetivo del proyecto
En esta práctica vamos a crear un entorno de desarrollo web usando Docker. El objetivo es tener un sistema parecido a XAMPP o MAMP, pero más profesional, portable y fácil de reconstruir.
El entorno permitirá trabajar con:
- Apache
- PHP
- Extensiones comunes de PHP
- MySQL
- phpMyAdmin
- Mailpit para probar correos
- Redis como servicio adicional opcional
- Una carpeta local donde guardaremos todos nuestros proyectos web
Todos los contenedores tendrán el prefijo:
DEV_
De esta forma podremos identificarlos fácilmente dentro de Docker.
1. ¿Qué vamos a construir?
El sistema tendrá esta estructura:
Carpeta local del alumno
│
▼
+-----------------------------+
| Carpeta DEVLOCAL |
| |
| proyecto1/ |
| proyecto2/ |
| pruebas/ |
| _docker/ |
+-------------+---------------+
│
▼
+-----------------------------+
| Docker Compose |
+-------------+---------------+
│
▼
+-----------------------------+
| DEV_apache_php |
| DEV_mysql |
| DEV_phpmyadmin |
| DEV_mailpit |
| DEV_redis |
+-----------------------------+
El alumno podrá crear una carpeta con un proyecto PHP y verlo desde el navegador.
Por ejemplo:
http://localhost:8080/pruebas/
2. Requisitos previos
Cada alumno necesitará:
- Un ordenador con Windows, Ubuntu o macOS.
- Docker instalado.
- Un editor de código, por ejemplo VS Code.
- Terminal o consola.
- Navegador web.
Docker Compose se usará para definir y levantar varios contenedores a la vez. Docker lo describe como una herramienta para definir y ejecutar aplicaciones multicontenedor.
3. Instalación de Docker en Windows
En Windows se recomienda usar Docker Desktop.
Docker Desktop para Windows incluye Docker Engine, Docker CLI y Docker Compose. La documentación oficial indica que Docker Desktop puede usar WSL 2 como motor de ejecución en Windows.
Pasos recomendados
- Instalar o activar WSL 2.
- Instalar Docker Desktop para Windows.
- Reiniciar el equipo si lo solicita.
- Abrir Docker Desktop.
- Comprobar que Docker está funcionando.
Desde PowerShell o Terminal de Windows:
docker --version
docker compose version
Si ambos comandos responden con una versión, Docker está funcionando correctamente.
Carpeta recomendada en Windows
Para evitar problemas con permisos o sincronización, se recomienda crear la carpeta directamente en C:\.
mkdir C:\DEVLOCAL
No es recomendable usar carpetas dentro de OneDrive para este tipo de práctica.
4. Instalación de Docker en Ubuntu
En Ubuntu se puede instalar Docker Engine directamente desde los repositorios oficiales de Docker. La documentación oficial recomienda configurar primero el repositorio apt de Docker y después instalar Docker Engine y sus plugins.
Actualizar paquetes
sudo apt update
sudo apt upgrade -y
Instalar dependencias
sudo apt install -y ca-certificates curl gnupg
Crear carpeta para claves
sudo install -m 0755 -d /etc/apt/keyrings
Descargar clave oficial de Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Dar permisos a la clave
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Añadir repositorio oficial
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Instalar Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Comprobar instalación
docker --version
docker compose version
Permitir usar Docker sin sudo
sudo usermod -aG docker $USER
Después de este comando, el alumno debe cerrar sesión y volver a entrar.
Carpeta recomendada en Ubuntu
mkdir -p ~/DEVLOCAL
5. Instalación de Docker en macOS
En macOS se recomienda instalar Docker Desktop para Mac. La documentación oficial diferencia entre Mac con chip Intel y Mac con Apple Silicon, por lo que hay que descargar la versión adecuada.
Pasos recomendados
- Descargar Docker Desktop para Mac.
- Elegir la versión correcta:
- Mac Intel.
- Mac Apple Silicon.
- Instalar la aplicación.
- Abrir Docker Desktop.
- Esperar a que Docker arranque completamente.
- Comprobar desde Terminal:
docker --version
docker compose version
Carpeta recomendada en macOS
En el caso de este ejemplo usaremos:
/Users/antoniooteroveiga/DEVLOCAL
Para otro usuario sería algo similar a:
/Users/nombre_usuario/DEVLOCAL
6. Crear la estructura del proyecto
La estructura será la misma en Windows, Ubuntu y macOS.
Windows
Desde PowerShell:
mkdir C:\DEVLOCAL
mkdir C:\DEVLOCAL\_docker
mkdir C:\DEVLOCAL\_docker\php
mkdir C:\DEVLOCAL\_docker\apache
mkdir C:\DEVLOCAL\pruebas
Ubuntu
Desde Terminal:
mkdir -p ~/DEVLOCAL/_docker/php
mkdir -p ~/DEVLOCAL/_docker/apache
mkdir -p ~/DEVLOCAL/pruebas
macOS
Desde Terminal:
mkdir -p /Users/antoniooteroveiga/DEVLOCAL/_docker/php
mkdir -p /Users/antoniooteroveiga/DEVLOCAL/_docker/apache
mkdir -p /Users/antoniooteroveiga/DEVLOCAL/pruebas
La estructura final será:
DEVLOCAL/
├── _docker/
│ ├── docker-compose.yml
│ ├── inicio.sh
│ ├── inicio.bat
│ ├── php/
│ │ ├── Dockerfile
│ │ ├── php.ini
│ │ └── msmtprc
│ └── apache/
│ └── 000-default.conf
└── pruebas/
└── index.php
7. Crear el archivo docker-compose.yml
Este archivo define todos los servicios del entorno.
Debe estar dentro de:
DEVLOCAL/_docker/docker-compose.yml
Contenido:
services:
apache_php:
build:
context: .
dockerfile: php/Dockerfile
container_name: DEV_apache_php
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ../:/var/www/html
- ./apache/000-default.conf:/etc/apache2/sites-available/000-default.conf
- ./php/php.ini:/usr/local/etc/php/conf.d/dev-custom.ini
- ./php/msmtprc:/etc/msmtprc
depends_on:
- mysql
- mailpit
networks:
- DEV_network
mysql:
image: mysql:8.4
container_name: DEV_mysql
restart: unless-stopped
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: devdb
MYSQL_USER: devuser
MYSQL_PASSWORD: devpass
volumes:
- DEV_mysql_data:/var/lib/mysql
networks:
- DEV_network
phpmyadmin:
image: phpmyadmin:latest
container_name: DEV_phpmyadmin
restart: unless-stopped
ports:
- "8081:80"
environment:
PMA_HOST: mysql
PMA_PORT: 3306
PMA_USER: root
PMA_PASSWORD: root
UPLOAD_LIMIT: 256M
depends_on:
- mysql
networks:
- DEV_network
mailpit:
image: axllent/mailpit:latest
container_name: DEV_mailpit
restart: unless-stopped
ports:
- "8025:8025"
- "1025:1025"
networks:
- DEV_network
redis:
image: redis:latest
container_name: DEV_redis
restart: unless-stopped
ports:
- "6379:6379"
networks:
- DEV_network
volumes:
DEV_mysql_data:
networks:
DEV_network:
name: DEV_network
8. Crear el archivo Dockerfile
Este archivo construirá nuestro contenedor de Apache con PHP.
Debe estar en:
DEVLOCAL/_docker/php/Dockerfile
Contenido:
FROM php:8.3-apache
RUN apt-get update && apt-get install -y \
git \
unzip \
zip \
curl \
msmtp \
msmtp-mta \
libzip-dev \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libicu-dev \
libonig-dev \
libxml2-dev \
libssl-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install \
mysqli \
pdo \
pdo_mysql \
zip \
gd \
intl \
mbstring \
bcmath \
soap \
opcache \
&& a2enmod rewrite headers expires \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
Con esto tendremos disponibles muchas extensiones habituales de PHP:
mysqlipdo_mysqlgdzipintlmbstringbcmathsoapopcache
También tendremos instalado Composer, muy útil para proyectos PHP modernos.
9. Crear el archivo php.ini
Debe estar en:
DEVLOCAL/_docker/php/php.ini
Contenido:
display_errors = On
display_startup_errors = On
error_reporting = E_ALL
upload_max_filesize = 256M
post_max_size = 256M
memory_limit = 512M
max_execution_time = 300
max_input_vars = 5000
date.timezone = Europe/Madrid
opcache.enable = 1
opcache.enable_cli = 1
sendmail_path = "/usr/bin/msmtp -t"
Este archivo ajusta PHP para un entorno de desarrollo.
No es una configuración pensada para producción. En producción no deberíamos mostrar errores directamente al usuario.
10. Crear el archivo msmtprc
Este archivo permitirá enviar correos desde PHP hacia Mailpit.
Debe estar en:
DEVLOCAL/_docker/php/msmtprc
Contenido:
defaults
auth off
tls off
account mailpit
host mailpit
port 1025
from devlocal@example.test
account default : mailpit
Mailpit capturará los correos y podremos verlos desde el navegador.
11. Crear la configuración de Apache
Debe estar en:
DEVLOCAL/_docker/apache/000-default.conf
Contenido:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/dev_error.log
CustomLog ${APACHE_LOG_DIR}/dev_access.log combined
</VirtualHost>
La directiva importante es:
AllowOverride All
Esto permite usar archivos .htaccess, necesarios en muchos proyectos PHP, como WordPress, Laravel o aplicaciones con URLs amigables.
12. Crear una página de prueba
Creamos el archivo:
DEVLOCAL/pruebas/index.php
Contenido:
<?php
echo "<h1>Entorno DEV funcionando</h1>";
echo "<p>Apache y PHP están funcionando correctamente.</p>";
echo "<h2>Información de PHP</h2>";
phpinfo();
13. Levantar el entorno manualmente
Windows
Desde PowerShell:
cd C:\DEVLOCAL\_docker
docker compose up -d --build
Ubuntu
Desde Terminal:
cd ~/DEVLOCAL/_docker
docker compose up -d --build
macOS
Desde Terminal:
cd /Users/antoniooteroveiga/DEVLOCAL/_docker
docker compose up -d --build
14. Comprobar los contenedores
Ejecutamos:
docker ps
Deberíamos ver contenedores parecidos a estos:
DEV_apache_php
DEV_mysql
DEV_phpmyadmin
DEV_mailpit
DEV_redis
15. Acceder al entorno desde el navegador
Apache + PHP
http://localhost:8080
Proyecto de pruebas
http://localhost:8080/pruebas/
phpMyAdmin
http://localhost:8081
Datos de acceso:
Servidor: mysql
Usuario: root
Contraseña: root
También podemos usar:
Servidor: mysql
Usuario: devuser
Contraseña: devpass
Mailpit
http://localhost:8025
MySQL desde el equipo anfitrión
Para conectarse desde DBeaver, DataGrip, VS Code o MySQL Workbench:
Host: localhost
Puerto: 3307
Usuario: devuser
Contraseña: devpass
Base de datos: devdb
MySQL desde PHP
Desde código PHP, el host no será localhost, sino el nombre del servicio Docker:
Host: mysql
Puerto: 3306
Usuario: devuser
Contraseña: devpass
Base de datos: devdb
16. Probar conexión con MySQL desde PHP
Creamos el archivo:
DEVLOCAL/pruebas/mysql.php
Contenido:
<?php
$host = "mysql";
$db = "devdb";
$user = "devuser";
$pass = "devpass";
$conexion = new mysqli($host, $user, $pass, $db);
if ($conexion->connect_error) {
die("Error de conexión: " . $conexion->connect_error);
}
echo "<h1>Conexión correcta con MySQL</h1>";
echo "<p>La base de datos devdb está disponible.</p>";
$conexion->close();
Abrimos en el navegador:
http://localhost:8080/pruebas/mysql.php
Si todo está correcto, veremos un mensaje confirmando la conexión.
17. Probar envío de correo con Mailpit
Creamos el archivo:
DEVLOCAL/pruebas/mail.php
Contenido:
<?php
$destino = "alumno@example.test";
$asunto = "Prueba desde PHP";
$mensaje = "Este correo ha sido enviado desde PHP y capturado por Mailpit.";
$cabeceras = "From: devlocal@example.test";
if (mail($destino, $asunto, $mensaje, $cabeceras)) {
echo "<h1>Correo enviado correctamente</h1>";
echo "<p>Abre Mailpit para verlo.</p>";
} else {
echo "<h1>Error al enviar el correo</h1>";
}
Abrimos:
http://localhost:8080/pruebas/mail.php
Después entramos en Mailpit:
http://localhost:8025
Ahí debería aparecer el correo capturado.
18. Crear script de inicio para Ubuntu y macOS
Creamos el archivo:
DEVLOCAL/_docker/inicio.sh
Contenido:
#!/bin/bash
clear
echo "=============================================="
echo " ENTORNO DEVLOCAL - DOCKER PHP MYSQL"
echo "=============================================="
echo ""
DEV_PATH="$(cd "$(dirname "$0")" && pwd)"
cd "$DEV_PATH" || exit 1
echo "Levantando contenedores DEV..."
echo ""
docker compose up -d
echo ""
echo "Esperando a que los servicios arranquen..."
sleep 3
echo ""
echo "=============================================="
echo " CONTENEDORES ACTIVOS"
echo "=============================================="
echo ""
docker ps --filter "name=DEV_"
echo ""
echo "=============================================="
echo " INFORMACION DE CONEXION"
echo "=============================================="
echo ""
echo "Servidor Apache + PHP:"
echo " URL principal: http://localhost:8080"
echo " Carpeta web: Carpeta DEVLOCAL del alumno"
echo ""
echo "Proyecto de prueba:"
echo " http://localhost:8080/pruebas/"
echo ""
echo "phpMyAdmin:"
echo " URL: http://localhost:8081"
echo " Servidor: mysql"
echo " Usuario root: root"
echo " Password root: root"
echo ""
echo "MySQL desde PHP:"
echo " Host: mysql"
echo " Puerto: 3306"
echo " Base de datos: devdb"
echo " Usuario: devuser"
echo " Password: devpass"
echo ""
echo "MySQL desde el equipo:"
echo " Host: localhost"
echo " Puerto: 3307"
echo " Base de datos: devdb"
echo " Usuario: devuser"
echo " Password: devpass"
echo ""
echo "Mailpit:"
echo " Panel web: http://localhost:8025"
echo " SMTP interno: mailpit:1025"
echo ""
echo "Redis:"
echo " Host desde Docker: redis"
echo " Host desde equipo: localhost"
echo " Puerto: 6379"
echo ""
echo "=============================================="
echo " COMANDOS UTILES"
echo "=============================================="
echo ""
echo "Parar entorno:"
echo " docker compose down"
echo ""
echo "Ver logs:"
echo " docker compose logs -f"
echo ""
echo "Entrar al contenedor PHP:"
echo " docker exec -it DEV_apache_php bash"
echo ""
echo "Entrar a MySQL:"
echo " docker exec -it DEV_mysql mysql -u root -p"
echo ""
echo "=============================================="
echo " ENTORNO DEV LISTO"
echo "=============================================="
echo ""
Damos permisos de ejecución:
chmod +x inicio.sh
Lo ejecutamos:
./inicio.sh
19. Crear script de inicio para Windows
Creamos el archivo:
DEVLOCAL/_docker/inicio.bat
Contenido:
@echo off
cls
echo ==============================================
echo ENTORNO DEVLOCAL - DOCKER PHP MYSQL
echo ==============================================
echo.
cd /d "%~dp0"
echo Levantando contenedores DEV...
echo.
docker compose up -d
echo.
echo Esperando a que los servicios arranquen...
timeout /t 3 > nul
echo.
echo ==============================================
echo CONTENEDORES ACTIVOS
echo ==============================================
echo.
docker ps --filter "name=DEV_"
echo.
echo ==============================================
echo INFORMACION DE CONEXION
echo ==============================================
echo.
echo Servidor Apache + PHP:
echo URL principal: http://localhost:8080
echo Carpeta web: Carpeta DEVLOCAL del alumno
echo.
echo Proyecto de prueba:
echo http://localhost:8080/pruebas/
echo.
echo phpMyAdmin:
echo URL: http://localhost:8081
echo Servidor: mysql
echo Usuario root: root
echo Password root: root
echo.
echo MySQL desde PHP:
echo Host: mysql
echo Puerto: 3306
echo Base de datos: devdb
echo Usuario: devuser
echo Password: devpass
echo.
echo MySQL desde Windows:
echo Host: localhost
echo Puerto: 3307
echo Base de datos: devdb
echo Usuario: devuser
echo Password: devpass
echo.
echo Mailpit:
echo Panel web: http://localhost:8025
echo SMTP interno: mailpit:1025
echo.
echo Redis:
echo Host desde Docker: redis
echo Host desde Windows: localhost
echo Puerto: 6379
echo.
echo ==============================================
echo COMANDOS UTILES
echo ==============================================
echo.
echo Parar entorno:
echo docker compose down
echo.
echo Ver logs:
echo docker compose logs -f
echo.
echo Entrar al contenedor PHP:
echo docker exec -it DEV_apache_php bash
echo.
echo Entrar a MySQL:
echo docker exec -it DEV_mysql mysql -u root -p
echo.
echo ==============================================
echo ENTORNO DEV LISTO
echo ==============================================
echo.
pause
Para ejecutarlo, el alumno puede hacer doble clic sobre inicio.bat o ejecutarlo desde PowerShell.
20. Script para parar el entorno
Ubuntu y macOS
Creamos:
DEVLOCAL/_docker/parar.sh
Contenido:
#!/bin/bash
cd "$(dirname "$0")" || exit 1
echo "Parando entorno DEV..."
docker compose down
echo "Entorno detenido."
Permisos:
chmod +x parar.sh
Ejecución:
./parar.sh
Windows
Creamos:
DEVLOCAL/_docker/parar.bat
Contenido:
@echo off
cls
cd /d "%~dp0"
echo Parando entorno DEV...
docker compose down
echo.
echo Entorno detenido.
pause
21. Comandos básicos que debe conocer el alumno
Levantar contenedores
docker compose up -d
Levantar y reconstruir
docker compose up -d --build
Parar contenedores
docker compose down
Ver contenedores activos
docker ps
Ver todos los contenedores
docker ps -a
Ver logs
docker compose logs -f
Ver logs de un servicio concreto
docker compose logs -f apache_php
Entrar al contenedor de PHP
docker exec -it DEV_apache_php bash
Entrar al contenedor de MySQL
docker exec -it DEV_mysql mysql -u root -p
Contraseña:
root
22. Crear varios proyectos web
El alumno puede crear diferentes carpetas dentro de DEVLOCAL.
Por ejemplo:
DEVLOCAL/
├── pruebas/
├── tienda/
├── blog/
├── reservas/
└── ejercicios_php/
Cada proyecto se abrirá desde el navegador así:
http://localhost:8080/pruebas/
http://localhost:8080/tienda/
http://localhost:8080/blog/
http://localhost:8080/reservas/
http://localhost:8080/ejercicios_php/
23. Ejercicio práctico
Parte 1: Comprobar PHP
Crear una carpeta llamada:
alumno_php
Dentro crear un archivo:
index.php
Con este contenido:
<?php
$nombre = "Alumno";
$curso = "Desarrollo Web con PHP";
echo "<h1>Hola, $nombre</h1>";
echo "<p>Estamos trabajando en el curso de $curso.</p>";
Abrir:
http://localhost:8080/alumno_php/
Parte 2: Comprobar MySQL
Crear un archivo:
conexion.php
Contenido:
<?php
$conexion = new mysqli("mysql", "devuser", "devpass", "devdb");
if ($conexion->connect_error) {
die("Error: " . $conexion->connect_error);
}
echo "Conexión correcta con MySQL";
Abrir:
http://localhost:8080/alumno_php/conexion.php
Parte 3: Crear una tabla desde phpMyAdmin
Entrar en:
http://localhost:8081
Seleccionar la base de datos:
devdb
Crear una tabla llamada:
alumnos
Con estos campos:
| Campo | Tipo | Extra |
|---|---|---|
| id | INT | AUTO_INCREMENT, PRIMARY KEY |
| nombre | VARCHAR(100) | |
| VARCHAR(150) | ||
| fecha_alta | DATETIME |
SQL:
CREATE TABLE alumnos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL,
fecha_alta DATETIME DEFAULT CURRENT_TIMESTAMP
);
Insertar datos:
INSERT INTO alumnos (nombre, email) VALUES
('Ana', 'ana@example.test'),
('Luis', 'luis@example.test'),
('Marta', 'marta@example.test');
Parte 4: Leer datos desde PHP
Crear:
listar.php
Contenido:
<?php
$conexion = new mysqli("mysql", "devuser", "devpass", "devdb");
if ($conexion->connect_error) {
die("Error: " . $conexion->connect_error);
}
$resultado = $conexion->query("SELECT * FROM alumnos");
echo "<h1>Listado de alumnos</h1>";
echo "<table border='1' cellpadding='8'>";
echo "<tr>";
echo "<th>ID</th>";
echo "<th>Nombre</th>";
echo "<th>Email</th>";
echo "<th>Fecha de alta</th>";
echo "</tr>";
while ($fila = $resultado->fetch_assoc()) {
echo "<tr>";
echo "<td>" . $fila["id"] . "</td>";
echo "<td>" . $fila["nombre"] . "</td>";
echo "<td>" . $fila["email"] . "</td>";
echo "<td>" . $fila["fecha_alta"] . "</td>";
echo "</tr>";
}
echo "</table>";
$conexion->close();
Abrir:
http://localhost:8080/alumno_php/listar.php
24. Preguntas de reflexión para el alumno
- ¿Qué diferencia hay entre instalar Apache, PHP y MySQL directamente en el sistema y hacerlo con Docker?
- ¿Qué ventaja tiene que todos los servicios estén definidos en un archivo
docker-compose.yml? - ¿Por qué PHP se conecta a MySQL usando el host
mysqly nolocalhost? - ¿Qué es un volumen en Docker?
- ¿Dónde se guardan los datos de MySQL en este proyecto?
- ¿Qué pasaría si ejecutamos
docker compose down -v? - ¿Para qué sirve phpMyAdmin?
- ¿Para qué sirve Mailpit?
- ¿Por qué no deberíamos usar contraseñas como
rootodevpassen producción? - ¿Qué diferencia hay entre un entorno de desarrollo y un entorno de producción?
25. Problemas frecuentes
Docker no arranca en Windows
Posibles causas:
- Docker Desktop no está abierto.
- WSL 2 no está instalado o activado.
- La virtualización está desactivada en BIOS/UEFI.
- El equipo necesita reiniciarse.
Docker recomienda usar el backend WSL 2 en Windows para Docker Desktop.
El puerto 8080 ya está ocupado
Puede ocurrir si otro servicio ya está usando ese puerto.
Solución: cambiar en docker-compose.yml:
ports:
- "8080:80"
Por ejemplo:
ports:
- "8090:80"
Después habría que entrar por:
http://localhost:8090
El puerto 3307 ya está ocupado
Cambiar:
ports:
- "3307:3306"
Por ejemplo:
ports:
- "3308:3306"
No aparecen los cambios en PHP
Probar a recargar el navegador con:
Ctrl + F5
También se puede reiniciar el contenedor:
docker compose restart apache_php
Error de permisos en Ubuntu
Si Docker pide sudo, puede faltar añadir el usuario al grupo docker.
sudo usermod -aG docker $USER
Después hay que cerrar sesión y volver a entrar.
phpMyAdmin no conecta
Comprobar que MySQL está activo:
docker ps
También se pueden ver los logs:
docker compose logs -f mysql
26. Cómo borrar todo y empezar de nuevo
Para parar los contenedores:
docker compose down
Para parar y borrar también los datos de MySQL:
docker compose down -v
Cuidado: este comando borra el volumen de MySQL. Si hay bases de datos creadas, se perderán.
29. Ampliaciones posibles
Cuando el entorno básico funcione, se pueden añadir mejoras:
- Crear dominios locales como
tienda.localhost. - Añadir HTTPS local.
- Añadir un contenedor de Node.js.
- Añadir un contenedor específico para Laravel.
- Crear plantillas para WordPress.
- Añadir copias de seguridad automáticas de MySQL.
- Crear un script para exportar e importar bases de datos.
- Crear varios entornos: desarrollo, pruebas y producción.
30. Conclusión
Con esta práctica hemos creado un entorno de desarrollo web completo usando Docker. El resultado es similar a XAMPP o MAMP, pero con una ventaja importante: todo el entorno queda definido mediante archivos.
Esto permite:
- Repetir la instalación en diferentes sistemas operativos.
- Compartir el entorno con otros compañeros.
- Evitar conflictos con instalaciones locales.
- Trabajar con varios servicios a la vez.
- Preparar al alumno para entornos profesionales basados en contenedores.
Docker Compose facilita levantar todos los servicios con un solo comando, lo que lo convierte en una herramienta especialmente útil para desarrollo web moderno.
Script Cerrar
Además del script
inicio, vamos a crear un script llamadocerrar. Este script no solamente permite apagar el entorno, sino también eliminarlo de diferentes formas según lo que necesitemos. Esto es importante porque no siempre queremos borrar los datos. A veces solo queremos detener los contenedores, y otras veces queremos empezar desde cero.
Diferencia entre las opciones
| Opción | Comando | ¿Borra contenedores? | ¿Borra datos MySQL? | ¿Borra imágenes? |
|---|---|---|---|---|
| Parar | docker compose stop | No | No | No |
| Eliminar contenedores | docker compose down | Sí | No | No |
| Eliminar con volúmenes | docker compose down -v | Sí | Sí | No |
| Destruir completo | docker compose down -v --rmi local | Sí | Sí | Sí |
docker compose stop
Detiene los contenedores, pero no los elimina.
Es como apagar una máquina virtual.
docker compose down
Detiene y elimina los contenedores, pero mantiene los volúmenes.
Es decir, si teníamos una base de datos MySQL con datos, normalmente se conservará.
docker compose down -v
Detiene y elimina los contenedores, y también borra los volúmenes.
En este proyecto significa que se borrarán los datos de MySQL.
docker compose down -v --rmi local
Además de eliminar contenedores y volúmenes, elimina imágenes locales creadas por el proyecto.
En nuestro caso, puede borrar la imagen personalizada de Apache + PHP, por lo que en el siguiente arranque habrá que reconstruirla con:
docker compose up -d --build
Recomendación para uso diario
Para el día a día, lo normal es usar la opción:
1) Parar contenedores
o:
2) Parar y eliminar contenedores
La opción 3 y 4 solo deberían usarse cuando queramos empezar desde cero.
Especialmente la opción 3:
docker compose down -v
porque borra los datos de MySQL.
Script para Ubuntu y macOS: cerrar.sh
Crear el archivo:
nano /Users/antoniooteroveiga/DEVLOCAL/_docker/cerrar.sh
Contenido:
#!/bin/bash
clear
echo "=============================================="
echo " CERRAR ENTORNO DEVLOCAL"
echo "=============================================="
echo ""
DEV_PATH="$(cd "$(dirname "$0")" && pwd)"
cd "$DEV_PATH" || exit 1
echo "Este script permite cerrar o destruir el entorno Docker DEV."
echo ""
echo "Elige una opcion:"
echo ""
echo " 1) Parar contenedores"
echo " Equivale a: docker compose stop"
echo ""
echo " 2) Parar y eliminar contenedores"
echo " Equivale a: docker compose down"
echo ""
echo " 3) Parar, eliminar contenedores y borrar volumenes"
echo " Equivale a: docker compose down -v"
echo " AVISO: se borraran las bases de datos de MySQL."
echo ""
echo " 4) Parar, eliminar contenedores, volumenes e imagenes del proyecto"
echo " Equivale a: docker compose down -v --rmi local"
echo " AVISO: se borraran las bases de datos y las imagenes creadas localmente."
echo ""
echo " 5) Ver contenedores DEV activos"
echo ""
echo " 6) Cancelar"
echo ""
read -p "Selecciona una opcion [1-6]: " opcion
echo ""
case "$opcion" in
1)
echo "Parando contenedores..."
docker compose stop
echo ""
echo "Contenedores detenidos."
;;
2)
echo "Parando y eliminando contenedores..."
docker compose down
echo ""
echo "Contenedores eliminados. Los volumenes se conservan."
;;
3)
echo "ATENCION: esta opcion borrara los volumenes."
echo "Esto eliminara los datos persistentes de MySQL."
echo ""
read -p "Escribe BORRAR para confirmar: " confirmacion
if [ "$confirmacion" = "BORRAR" ]; then
echo ""
echo "Eliminando contenedores y volumenes..."
docker compose down -v
echo ""
echo "Entorno eliminado con volumenes."
else
echo ""
echo "Operacion cancelada. No se ha borrado nada."
fi
;;
4)
echo "ATENCION: esta opcion borrara contenedores, volumenes e imagenes locales."
echo "Esto eliminara los datos de MySQL y obligara a reconstruir la imagen PHP."
echo ""
read -p "Escribe DESTRUIR para confirmar: " confirmacion
if [ "$confirmacion" = "DESTRUIR" ]; then
echo ""
echo "Eliminando contenedores, volumenes e imagenes locales..."
docker compose down -v --rmi local
echo ""
echo "Entorno destruido."
else
echo ""
echo "Operacion cancelada. No se ha borrado nada."
fi
;;
5)
echo "Mostrando contenedores DEV..."
echo ""
docker ps -a --filter "name=DEV_"
;;
6)
echo "Operacion cancelada."
;;
*)
echo "Opcion no valida."
;;
esac
echo ""
echo "=============================================="
echo " PROCESO FINALIZADO"
echo "=============================================="
echo ""
Dar permisos de ejecución:
chmod +x /Users/antoniooteroveiga/DEVLOCAL/_docker/cerrar.sh
Ejecutarlo:
cd /Users/antoniooteroveiga/DEVLOCAL/_docker
./cerrar.sh
Versión más portable
Si quieres que funcione sin depender de tu usuario concreto, es mejor decirles que creen el archivo dentro de _docker y que lo ejecuten desde ahí.
cd ~/DEVLOCAL/_docker
nano cerrar.sh
chmod +x cerrar.sh
./cerrar.sh
El script ya detecta automáticamente la carpeta donde está, gracias a esta línea:
DEV_PATH="$(cd "$(dirname "$0")" && pwd)"
Por eso vale tanto para Ubuntu como para macOS.
Script para Windows: cerrar.bat
Crear el archivo:
C:\DEVLOCAL\_docker\cerrar.bat
Contenido:
@echo off
cls
cd /d "%~dp0"
:menu
cls
echo ==============================================
echo CERRAR ENTORNO DEVLOCAL
echo ==============================================
echo.
echo Este script permite cerrar o destruir el entorno Docker DEV.
echo.
echo Elige una opcion:
echo.
echo 1) Parar contenedores
echo Equivale a: docker compose stop
echo.
echo 2) Parar y eliminar contenedores
echo Equivale a: docker compose down
echo.
echo 3) Parar, eliminar contenedores y borrar volumenes
echo Equivale a: docker compose down -v
echo AVISO: se borraran las bases de datos de MySQL.
echo.
echo 4) Parar, eliminar contenedores, volumenes e imagenes del proyecto
echo Equivale a: docker compose down -v --rmi local
echo AVISO: se borraran las bases de datos y las imagenes creadas localmente.
echo.
echo 5) Ver contenedores DEV activos
echo.
echo 6) Cancelar
echo.
set /p opcion=Selecciona una opcion [1-6]:
if "%opcion%"=="1" goto parar
if "%opcion%"=="2" goto eliminar
if "%opcion%"=="3" goto volumenes
if "%opcion%"=="4" goto destruir
if "%opcion%"=="5" goto ver
if "%opcion%"=="6" goto cancelar
echo.
echo Opcion no valida.
pause
goto menu
:parar
cls
echo Parando contenedores...
echo.
docker compose stop
echo.
echo Contenedores detenidos.
pause
goto fin
:eliminar
cls
echo Parando y eliminando contenedores...
echo.
docker compose down
echo.
echo Contenedores eliminados. Los volumenes se conservan.
pause
goto fin
:volumenes
cls
echo ATENCION: esta opcion borrara los volumenes.
echo Esto eliminara los datos persistentes de MySQL.
echo.
set /p confirmacion=Escribe BORRAR para confirmar:
if "%confirmacion%"=="BORRAR" (
echo.
echo Eliminando contenedores y volumenes...
docker compose down -v
echo.
echo Entorno eliminado con volumenes.
) else (
echo.
echo Operacion cancelada. No se ha borrado nada.
)
pause
goto fin
:destruir
cls
echo ATENCION: esta opcion borrara contenedores, volumenes e imagenes locales.
echo Esto eliminara los datos de MySQL y obligara a reconstruir la imagen PHP.
echo.
set /p confirmacion=Escribe DESTRUIR para confirmar:
if "%confirmacion%"=="DESTRUIR" (
echo.
echo Eliminando contenedores, volumenes e imagenes locales...
docker compose down -v --rmi local
echo.
echo Entorno destruido.
) else (
echo.
echo Operacion cancelada. No se ha borrado nada.
)
pause
goto fin
:ver
cls
echo Mostrando contenedores DEV...
echo.
docker ps -a --filter "name=DEV_"
echo.
pause
goto menu
:cancelar
cls
echo Operacion cancelada.
pause
goto fin
:fin
cls
echo ==============================================
echo PROCESO FINALIZADO
echo ==============================================
echo.














![[Reto] - Dockerizar app JEE (Tomcat 10 + MySQL) 4b9bc3d2-8253-4715-adf6-d5b1eed959d3](https://laaventuradeaprender.com/wp-content/uploads/2026/02/4b9bc3d2-8253-4715-adf6-d5b1eed959d3-150x150.png)