Skip to main content
DVWA provides official Docker images that simplify deployment and ensure consistent environments across different systems.

Prerequisites

Before starting, ensure you have Docker and Docker Compose installed.

Required Software

  • Docker - Container runtime
  • Docker Compose - Multi-container orchestration

Installation Check

Verify your installation:
docker version
docker compose version
```text

Expected output:

```text
>>> docker version
Client:
 [..]
 Version:           23.0.5
 [..]

Server: Docker Desktop 4.19.0 (106363)
 Engine:
  [..]
  Version:          23.0.5
  [..]

>>> docker compose version
Docker Compose version v2.17.3

Install Docker

Download from docker.com for:
  • Windows
  • macOS
  • Linux
Docker Desktop includes both Docker and Docker Compose.
DVWA supports the latest Docker release. Older versions from package managers may work but are supported on a best-effort basis.

Quick Start

Get DVWA running in four simple steps.
1

Clone the repository

git clone https://github.com/digininja/DVWA.git
cd DVWA
```bash
</Step>

<Step title="Start the containers">
```bash
docker compose up -d
The -d flag runs containers in detached mode (background).
2

Access DVWA

Open your browser and navigate to:
    http://localhost:4280
3

Complete setup

  1. Click “Create / Reset Database”
  2. Log in with default credentials:
    • Username: admin
    • Password: password
DVWA is now running in Docker!

Docker Compose Configuration

DVWA uses a compose.yml file to define services, networks, and volumes.

Complete Configuration

From compose.yml:
volumes:
  dvwa:

networks:
  dvwa:

services:
  dvwa:
    build: .
    image: ghcr.io/digininja/dvwa:latest
    # Change `always` to `build` to build from local source
    pull_policy: always
    environment:
      - DB_SERVER=db
    depends_on:
      - db
    # Uncomment the next 2 lines to serve local source
    # volumes:
    #   - ./:/var/www/html
    networks:
      - dvwa
    ports:
      - 127.0.0.1:4280:80
    restart: unless-stopped

  db:
    image: docker.io/library/mariadb:10
    environment:
      - MYSQL_ROOT_PASSWORD=dvwa
      - MYSQL_DATABASE=dvwa
      - MYSQL_USER=dvwa
      - MYSQL_PASSWORD=p@ssw0rd
    volumes:
      - dvwa:/var/lib/mysql
    networks:
      - dvwa
    restart: unless-stopped
```bash

### Architecture Overview

DVWA runs as two connected services:

<CardGroup cols={2}>
  <Card title="dvwa" icon="globe">
    Apache web server running PHP application
  </Card>
  <Card title="db" icon="database">
    MariaDB 10 database server
  </Card>
</CardGroup>

Both services:
- Share a private `dvwa` network
- Persist data in the `dvwa` volume
- Restart automatically unless manually stopped

## Port Configuration

By default, DVWA is accessible on port **4280**.

### Default Port Binding

```yaml
ports:
  - 127.0.0.1:4280:80
This maps:
  • Host: 127.0.0.1:4280 (your machine)
  • Container: port 80 (inside container)
DVWA uses port 4280 instead of 80 to avoid conflicts with existing web servers and to support rootless container engines.

Why Not Port 80?

  1. Conflict avoidance - Port 80 may already be in use
  2. Rootless containers - Ports below 1024 require privileges
  3. Security - Reduces risk of accidental exposure

Change the Port

To use a different port, edit compose.yml:
ports:
  - 127.0.0.1:8806:80  # Now accessible at localhost:8806
```bash

Restart the containers:

```bash
docker compose down
docker compose up -d
Access DVWA at: http://localhost:8806

Expose to Local Network

By default, DVWA only listens on 127.0.0.1 (localhost). To make it accessible on your local network:
ports:
  - 4280:80  # Listens on all interfaces
```text

Or bind to a specific IP:

```yaml
ports:
  - 192.168.1.100:4280:80  # Only accessible from this IP
Only expose DVWA on a local network in controlled environments like workshops or isolated lab networks. Never expose it to the internet.

Environment Variables

Configure DVWA behavior using environment variables.

DVWA Service Variables

dvwa:
  environment:
    - DB_SERVER=db
    - DEFAULT_SECURITY_LEVEL=low
    - DEFAULT_LOCALE=en
    - RECAPTCHA_PUBLIC_KEY=your_key_here
    - RECAPTCHA_PRIVATE_KEY=your_key_here
```bash

#### Available Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `DB_SERVER` | `db` | Database hostname |
| `DB_DATABASE` | `dvwa` | Database name |
| `DB_USER` | `dvwa` | Database username |
| `DB_PASSWORD` | `p@ssw0rd` | Database password |
| `DB_PORT` | `3306` | Database port |
| `DEFAULT_SECURITY_LEVEL` | `impossible` | Initial security level |
| `DEFAULT_LOCALE` | `en` | Interface language |
| `DISABLE_AUTHENTICATION` | `false` | Disable login requirement |
| `RECAPTCHA_PUBLIC_KEY` | _(empty)_ | reCAPTCHA public key |
| `RECAPTCHA_PRIVATE_KEY` | _(empty)_ | reCAPTCHA private key |
| `SQLI_DB` | `mysql` | SQLi lab database backend |

### Database Service Variables

```yaml
db:
  environment:
    - MYSQL_ROOT_PASSWORD=dvwa
    - MYSQL_DATABASE=dvwa
    - MYSQL_USER=dvwa
    - MYSQL_PASSWORD=p@ssw0rd

MariaDB Variables

VariableValueDescription
MYSQL_ROOT_PASSWORDdvwaRoot user password
MYSQL_DATABASEdvwaAuto-created database
MYSQL_USERdvwaAuto-created user
MYSQL_PASSWORDp@ssw0rdUser password

Example: Start at Low Security

dvwa:
  environment:
    - DB_SERVER=db
    - DEFAULT_SECURITY_LEVEL=low
```bash

## Volume Mapping for Development

Developers can mount local files into the container for live editing.

### Enable Local Development

Uncomment the volume mount in `compose.yml`:

```yaml
dvwa:
  volumes:
    - ./:/var/www/html  # Mount current directory

Setup Steps

1

Copy configuration file

cp config/config.inc.php.dist config/config.inc.php
```bash
</Step>

<Step title="Enable volume mount">
Edit `compose.yml` and uncomment the volumes section.
</Step>

<Step title="Restart containers">
```bash
docker compose down
docker compose up -d

Benefits

  • Live editing - Changes reflect immediately
  • No rebuilds - Skip image rebuilding
  • Faster development - Instant feedback
  • Local debugging - Use your favorite tools
This mode is perfect for contributing to DVWA or testing custom modifications.

Local Build vs Pulling Images

DVWA can either pull prebuilt images or build from local source.

Pull Prebuilt Images (Default)

pull_policy: always
```bash

- **Faster** - No build time
- **Consistent** - Official tested images
- **Automatic updates** - Latest commits from master branch
- **Recommended for** - Most users

Images are automatically built from the `master` branch and published to:
[GitHub Container Registry](https://github.com/digininja/DVWA/pkgs/container/dvwa)

### Build from Local Source

Change the pull policy:

```yaml
pull_policy: build
Then rebuild:
docker compose up -d --build
```bash

- **Customizable** - Modify source code
- **Development** - Test local changes
- **Offline** - No internet required after first build
- **Recommended for** - Developers and contributors

### Image Information

View available images:
```bash
docker images | grep dvwa
Pull latest image manually:
docker pull ghcr.io/digininja/dvwa:latest
```bash

## Docker Management Commands

Common commands for managing DVWA containers.

### Start Services

```bash
# Start in background
docker compose up -d

# Start with logs visible
docker compose up

# Rebuild and start
docker compose up -d --build

Stop Services

# Stop containers (keeps data)
docker compose stop

# Stop and remove containers (keeps data)
docker compose down

# Stop and remove everything including volumes (deletes data)
docker compose down -v
```bash

### View Logs

```bash
# All services
docker compose logs

# Follow logs in real-time
docker compose logs -f

# Specific service
docker compose logs dvwa
docker compose logs db

# Export logs to file
docker compose logs > dvwa.log

Container Status

# List running containers
docker compose ps

# Detailed container info
docker compose ps -a
```bash

### Execute Commands in Container

```bash
# Open shell in DVWA container
docker compose exec dvwa bash

# Open MySQL shell in database
docker compose exec db mysql -u dvwa -pp@ssw0rd dvwa

# Run a single command
docker compose exec dvwa ls -la /var/www/html

Reset Everything

# Complete reset (deletes all data)
docker compose down -v
docker compose up -d

# Then navigate to setup page and recreate database
```bash

## Auto-Start Behavior

By default, DVWA automatically starts when Docker runs.

### Restart Policy

```yaml
restart: unless-stopped
This means:
  • ✅ Starts on system boot
  • ✅ Restarts after crashes
  • ✅ Restarts after Docker daemon restart
  • ❌ Does NOT restart after manual stop

Disable Auto-Start

To prevent automatic startup, remove or comment out the restart policy:
# restart: unless-stopped
```bash

Or stop containers manually:

```bash
docker compose stop

Manual Start

Start DVWA only when needed:
docker compose start
```bash

## Docker Troubleshooting

Common issues and solutions for Docker deployments.

### Viewing Logs

**Docker Desktop:**

1. Open Docker Desktop application
2. Navigate to "Containers" tab
3. Find `dvwa` project
4. Click on container name to view logs

**Command Line:**

```bash
docker compose logs -f

Port Already in Use

Error:
Error starting userland proxy: listen tcp4 0.0.0.0:4280: bind: address already in use
Solutions:
  1. Check what’s using the port:
    sudo lsof -i :4280
    

2. Change DVWA port in `compose.yml`:
   ```yaml
   ports:
     - 127.0.0.1:8080:80

Database Connection Failed

Error in DVWA setup page:
Database Error: Connection refused
Solutions:
  1. Verify database container is running:
    docker compose ps
    

2. Check database logs:
   ```bash
   docker compose logs db
  1. Ensure DB_SERVER=db in environment variables
  2. Restart containers:
    docker compose restart
    

### MariaDB Won't Start

Error in logs:
[Warn] [Entrypoint]: /sys/fs/cgroup/memory.pressure not writable

**Solution:**

Add volume mount to `compose.yml`:

```yaml
db:
  volumes:
    - dvwa:/var/lib/mysql
    - /sys/fs/cgroup/memory.pressure:/sys/fs/cgroup/memory.pressure
This is typically a memory constraint issue on the host. Consider:
  • Upgrading to a larger instance (cloud hosting)
  • Increasing Docker memory limits (Docker Desktop)

Containers Exit Immediately

Check logs for errors:
docker compose logs
```bash

Common causes:
- Database initialization failure
- Permission issues
- Port conflicts

### File Permission Issues

With volume mounts, you may encounter permission errors.

**Solution:**

Fix ownership:
```bash
sudo chown -R www-data:www-data hackable/uploads/
sudo chmod -R 755 hackable/uploads/
Or run from within container:
docker compose exec dvwa chown -R www-data:www-data /var/www/html/hackable/uploads/
```bash

### Complete Reset

If nothing else works:

```bash
# Stop and remove everything
docker compose down -v

# Remove images
docker rmi ghcr.io/digininja/dvwa:latest
docker rmi mariadb:10

# Clean Docker system
docker system prune -a

# Start fresh
docker compose up -d

Security Considerations

DVWA is intentionally vulnerable. Never expose it to the internet or untrusted networks.

Best Practices

  1. Localhost only - Keep the 127.0.0.1 binding
    ports:
      - 127.0.0.1:4280:80  # Safe
    

2. **Isolated networks** - Only use on:
   - Local machine
   - Isolated lab networks
   - NAT-mode virtual machines

3. **No production** - Never run alongside production services

4. **Regular cleanup** - Remove when not in use:
   ```bash
   docker compose down -v
  1. Firewall rules - Ensure Docker ports are not exposed externally

Network Isolation

DVWA creates an isolated Docker network:
networks:
  dvwa:
```bash

This ensures:
- DVWA and database can communicate
- Other containers cannot access DVWA network
- Network traffic is isolated

## Next Steps

<CardGroup cols={2}>
  <Card title="Configure DVWA" icon="gear" href="/configuration/setup">
    Set up configuration file and options
  </Card>
  <Card title="Database Setup" icon="database" href="/configuration/database">
    Initialize the DVWA database
  </Card>
  <Card title="Start Testing" icon="flask" href="/vulnerabilities">
    Begin exploring vulnerabilities
  </Card>
  <Card title="Security Levels" icon="shield" href="/configuration/security-levels">
    Understand difficulty levels
  </Card>
</CardGroup>

Build docs developers (and LLMs) love