Introducción
Ya tienes Docker instalado, sabes lanzar contenedores, meterles una shell y borrarlos sin dejar rastro. Ahora vamos a lo que interesa de verdad: levantar aplicaciones diseñadas para que las rompas.
DVWA (Damn Vulnerable Web Application) es el campo de entrenamiento por excelencia para pentesters web. Trae de serie vulnerabilidades clásicas: SQL Injection, XSS reflejado y almacenado, Command Injection, CSRF, File Upload, File Inclusion… Todo lo que necesitas para practicar las técnicas que luego aplicarás en entornos reales.
Pero DVWA no es solo un servidor web. Necesita también una base de datos MySQL. Aquí es donde Docker Compose brilla: te permite definir y levantar múltiples contenedores que trabajan juntos como un solo servicio.
En este post desplegarás DVWA funcional en menos de dos minutos. Y cuando acabes de machacarlo, un solo comando lo reseteará todo a estado virgen.
¿Por qué Docker Compose y no docker run a pelo?
DVWA necesita dos servicios hablando entre sí:
- Servidor web (Apache + PHP + código DVWA)
- Base de datos (MySQL o MariaDB)
Con docker run tendrías que lanzar dos contenedores separados, conectarlos a la misma red manualmente, pasar credenciales por variables de entorno… Un coñazo.
Docker Compose te permite escribir un archivo docker-compose.yml donde declaras ambos servicios, sus puertos, contraseñas, volúmenes y redes internas. Luego levantas todo con docker compose up -d y te olvidas.
Es infraestructura como código: el archivo YAML describe tu laboratorio y puedes versionarlo, compartirlo o reconstruirlo en cualquier máquina.
1. Crear el directorio del proyecto
Primero, crea una carpeta para tu laboratorio de DVWA y métete dentro:
mkdir ~/lab-dvwa && cd ~/lab-dvwaBashTodo lo que necesitas vivirá aquí.
2. El archivo docker-compose.yml
Crea el archivo con tu editor favorito:
nano docker-compose.ymlBashCopia y pega esto:
services:
web:
image: vulnerables/web-dvwa
container_name: dvwa_web
ports:
- "8080:80"
environment:
- DB_SERVER=db
- DB_USER=dvwa
- DB_PASSWORD=p@ssw0rd
- DB_NAME=dvwa
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: mysql:8.0
container_name: dvwa_db
environment:
- MYSQL_ROOT_PASSWORD=rootpass
- MYSQL_DATABASE=dvwa
- MYSQL_USER=dvwa
- MYSQL_PASSWORD=p@ssw0rd
volumes:
- dvwa_db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
interval: 5s
timeout: 5s
retries: 10
restart: unless-stopped
volumes:
dvwa_db_data:BashVamos a destripar esto línea a línea, porque entenderlo es la diferencia entre usar recetas de internet y saber lo que haces.
3. Entendiendo el archivo
Servicio web (DVWA)
| Línea | Qué significa |
|---|---|
| image: vulnerables/web-dvwa | Imagen oficial de DVWA mantenida por la comunidad. Contiene Apache, PHP y el código vulnerable. |
| container_name: dvwa_web | Nombre legible para referirnos a este contenedor. |
| ports: – «8080:80» | Mapea el puerto 80 del contenedor al 8080 de tu máquina. Accederás con http://localhost:8080. |
| environment: | Variables de entorno que DVWA usa para conectarse a la base de datos. |
| DB_SERVER=db | db es el nombre del servicio de base de datos. Docker Compose resuelve automáticamente los nombres de servicio como nombres de host dentro de la red interna. |
| depends_on: db: condition: service_healthy | No arranca DVWA hasta que MySQL esté listo y aceptando conexiones. Sin esto, DVWA intentaría conectar antes de que la DB esté operativa y fallaría. |
restart: unless-stopped | Si el contenedor se para por un error, se reinicia automáticamente. Si lo paras tú manualmente (docker compose stop), se queda parado. |
Servicio db (MySQL)
| Línea | Qué significa |
|---|---|
| image: mysql:8.0 | MySQL 8.0 oficial. |
| container_name: dvwa_db | Nombre legible. |
| MYSQL_ROOT_PASSWORD: rootpass | Contraseña del usuario root de MySQL. |
| MYSQL_DATABASE: dvwa | Crea automáticamente la base de datos dvwa al iniciar. |
MYSQL_USER: dvwa y MYSQL_PASSWORD: p@ssw0rd | Crea un usuario dvwa con esa contraseña y le da permisos sobre la BD dvwa. |
| volumes: – dvwa_db_data:/var/lib/mysql | Persiste los datos de MySQL en un volumen con nombre. Si borras el contenedor, los datos sobreviven en el volumen. |
| healthcheck: | Comprueba cada 5 segundos si MySQL está listo (usando mysqladmin ping). Hasta 10 intentos. |
Volumen dvwa_db_data
Declarado al final del archivo. Docker lo gestiona automáticamente. Los datos de la base de datos sobreviven aunque borres y recrees los contenedores. Si quieres empezar desde cero de verdad, tendrás que borrar también el volumen (luego te cuento cómo).
4. Levantar DVWA
Desde el directorio donde está el docker-compose.yml:
docker compose up -dBashVerás algo como:
[+] Running 3/3
✔ Volume "lab-dvwa_dvwa_db_data" Created
✔ Container dvwa_db Started
✔ Container dvwa_web StartedBashEsto ha hecho en segundos:
- Descargar las imágenes si no las tenías (mysql:8.0 y vulnerables/web-dvwa).
- Crear el volumen para la base de datos.
- Arrancar MySQL y esperar a que esté healthy.
- Arrancar DVWA.
Comprueba que todo está corriendo:
docker compose psBashVerás algo como esto:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
dvwa_db mysql:8.0 "docker-entrypoint.s…" db About a minute ago Up About a minute (healthy) 3306/tcp, 33060/tcp
dvwa_web vulnerables/web-dvwa "/main.sh" web About a minute ago Up 56 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcpBashDeberías ver ambos servicios con estado Up (o healthy en el caso de MySQL).
5. Configurar DVWA
Abre tu navegador y ve a http://localhost:8080.
Verás la pantalla de login de DVWA.

Las credenciales por defecto son:
- Usuario: admin
- Contraseña: password
Al hacer login, DVWA te llevará automáticamente a la página de Setup / Reset DB.
Haz clic en Create / Reset Database.

Esto crea las tablas necesarias dentro de la base de datos MySQL que ya está corriendo en el contenedor dvwa_db. Si todo sale bien, verás un montón de mensajes y serás redirigido al login de nuevo.
Ahora inicia sesión otra vez con admin / password y ya estarás dentro del panel principal de DVWA.
6. Primeras pruebas (para abrir boca)
En el menú lateral izquierdo tienes todas las vulnerabilidades disponibles. Por defecto DVWA arranca con nivel de seguridad low (el más fácil). Para comprobarlo:
- Ve a DVWA Security en el menú.
- Comprueba que el nivel esta en low.
- Si no lo está, cambialo y dale a Submit.
Conforme mejores, subirás el nivel a medium o high.
Prueba rápida en Command Injection (menú lateral):
- Introduce 127.0.0.1 en la caja y pulsa Submit. Verás el resultado de un ping.
- Ahora introduce 127.0.0.1; ls -la. Si ves el listado del directorio, has conseguido ejecutar comandos en el servidor. Enhorabuena, acabas de hacer tu primer command injection.



Deja una respuesta