Ethical Hacking #docker#penetration-testing#hacking-lab

How to Build a Docker-Based Hacking Lab

Complete guide to creating a Docker-based penetration testing lab with vulnerable apps and tools.

10 min read

Introduction

Building a personal hacking lab is essential for learning penetration testing skills safely and legally. Docker containerization makes this dramatically easier by eliminating complex VM management. This guide walks you through creating a fully-functional Docker-based lab with vulnerable applications, security tools, and multiple testing environments—all on a single machine.

Why Docker for Your Hacking Lab?

Advantages Over Virtual Machines

AspectDockerVirtual Machines
Start timeSecondsMinutes
Storage50-200 MB per container5-30 GB per VM
ManagementSingle file (docker-compose)Multiple VM files
Resource efficiencyLightweightHeavy overhead
NetworkingEasy container networkingPort forwarding complexity

What You’ll Build

Docker Hacking Lab
├── Vulnerable Web Apps (DVWA, WebGoat)
├── Database Targets (MySQL, PostgreSQL)
├── Network Services (FTP, SSH, SMB)
├── Analysis Tools (Metasploit, Nessus)
└── Monitoring (ELK Stack for logging)

Prerequisites

System Requirements

  • RAM: 8GB minimum (16GB+ recommended)
  • Storage: 50GB free disk space
  • CPU: Dual-core minimum (quad-core recommended)
  • OS: Linux (Ubuntu 20.04+), macOS, or Windows 10/11 Pro

Install Docker and Docker Compose

Ubuntu/Debian:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
newgrp docker

Verify installation:

docker --version
docker-compose --version

Building Your First Vulnerable App Container

Create a Simple Vulnerable Web Server

Create a project directory:

mkdir ~/hacking-lab
cd ~/hacking-lab

Create a Dockerfile:

FROM python:3.9-slim
WORKDIR /app
RUN pip install flask
COPY vulnerable_app.py .
EXPOSE 5000
CMD ["python", "vulnerable_app.py"]

Create vulnerable_app.py:

from flask import Flask, request

app = Flask(__name__)

@app.route('/search')
def search():
    query = request.args.get('q', '')
    # Vulnerable to SQL injection
    return f"<h1>Results for: {query}</h1>"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Build and run:

docker build -t vulnerable-app .
docker run -p 5000:5000 vulnerable-app

Access at http://localhost:5000/search?q=test.

Docker Compose: Multi-Container Lab

Create a Complete Lab Environment

Create docker-compose.yml:

version: '3.8'

services:
  # Vulnerable Web Application
  dvwa:
    image: vulnerables/web-dvwa
    ports:
      - "80:80"
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=dvwa
    networks:
      - lab-network

  # MySQL Database
  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=dvwa
    networks:
      - lab-network

  # WebGoat (OWASP)
  webgoat:
    image: webgoat/latest
    ports:
      - "8080:8080"
    networks:
      - lab-network

  # Juice Shop (OWASP)
  juiceshop:
    image: bkimminich/juice-shop
    ports:
      - "3000:3000"
    networks:
      - lab-network

  # Metasploitable3 (Linux)
  metasploitable:
    image: tleemiller/metasploitable3-linux
    ports:
      - "22:22"
      - "23:23"
      - "21:21"
      - "3306:3306"
    networks:
      - lab-network

  # Kali Linux for attacking
  attacker:
    image: kalilinux/kali-rolling
    stdin_open: true
    tty: true
    networks:
      - lab-network

networks:
  lab-network:
    driver: bridge

Deploy the Lab

docker-compose up -d

Check running containers:

docker-compose ps

Access Services

  • DVWA: http://localhost
  • WebGoat: http://localhost:8080
  • Juice Shop: http://localhost:3000
  • MySQL: localhost:3306
  • Metasploitable SSH: ssh root@localhost:2222

Adding Custom Vulnerable Applications

Include DVWA (Damn Vulnerable Web Application)

Already in our compose file above. Default credentials:

  • Username: admin
  • Password: password

Add WebGoat for Guided Learning

WebGoat provides structured lessons:

webgoat:
  image: webgoat/latest
  ports:
    - "8080:8080"
  environment:
    - JAVA_OPTS=-Dspring.profiles.active=docker
  networks:
    - lab-network

Add Vulnerable Node App

nodegoat:
  image: vulnerapp/nodegoat
  ports:
    - "4000:4000"
  networks:
    - lab-network

Setting Up Testing Tools in Containers

Burp Suite in Docker

Create a Dockerfile for Burp proxy:

FROM ubuntu:20.04
RUN apt-get update && apt-get install -y \
    curl \
    openjdk-11-jdk
RUN curl -o /burp.jar https://[burp-download-url]
EXPOSE 8081
CMD ["java", "-jar", "/burp.jar"]

Metasploit Framework Container

metasploit:
  image: metasploitframework/metasploit-framework
  ports:
    - "5432:5432"
  networks:
    - lab-network

Network Analysis with tcpdump

tcpdump:
  image: nicolaka/netshoot
  cap_add:
    - NET_ADMIN
  networks:
    - lab-network

Advanced Lab Networking

Custom Network Configuration

Create isolated networks for different scenarios:

docker network create attacking-network
docker network create target-network

Run containers on specific networks:

docker run --network attacking-network -it kalilinux/kali-rolling bash
docker run --network target-network vulnerables/web-dvwa

Internal Lab Communication

Containers on same network can communicate by hostname:

# Inside Kali container
ping dvwa
curl http://dvwa

Persistent Data and Volumes

Create Persistent Storage

services:
  dvwa:
    image: vulnerables/web-dvwa
    volumes:
      - dvwa_data:/var/lib/mysql
    networks:
      - lab-network

volumes:
  dvwa_data:
    driver: local

This preserves database content between restarts.

Mount Host Directories

services:
  attacker:
    image: kalilinux/kali-rolling
    volumes:
      - /home/user/payloads:/payloads
      - /home/user/results:/results
    networks:
      - lab-network

Complete Lab Workflow Example

Attack Scenario: SQL Injection

Step 1: Start lab

docker-compose up -d

Step 2: Access attacking container

docker-compose exec attacker bash
apt-get update && apt-get install -y sqlmap

Step 3: Scan target

sqlmap -u "http://dvwa/vulnerabilities/sqli/?id=1" \
  -D dvwa -T users --dump

Step 4: Save results

# Inside container
sqlmap -u "http://dvwa/vulnerabilities/sqli/?id=1" \
  --batch --dump-all > /results/sqli_dump.txt

Step 5: Review on host

cat ~/results/sqli_dump.txt

Logging and Monitoring Lab Activity

ELK Stack for Log Aggregation

elasticsearch:
  image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0
  environment:
    - discovery.type=single-node
  ports:
    - "9200:9200"
  networks:
    - lab-network

kibana:
  image: docker.elastic.co/kibana/kibana:8.0.0
  ports:
    - "5601:5601"
  networks:
    - lab-network

Docker Event Logging

Monitor all container activity:

docker events --filter 'type=container'

Container Health Checks

dvwa:
  image: vulnerables/web-dvwa
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost"]
    interval: 30s
    timeout: 10s
    retries: 3

Management and Maintenance

Common Docker Commands

View running containers:

docker-compose ps

Access container shell:

docker-compose exec dvwa bash

View logs:

docker-compose logs -f dvwa

Stop lab:

docker-compose stop

Restart lab:

docker-compose restart

Complete cleanup:

docker-compose down -v

Troubleshooting

Port Already in Use

# Find what's using the port
sudo lsof -i :80

# Kill process if needed
sudo kill -9 PID

Container Won’t Start

docker-compose logs dvwa

Check error message and verify resource availability.

Network Connectivity Issues

# Test from attacker container
docker-compose exec attacker ping dvwa

# Verify network exists
docker network ls
docker network inspect lab-network

Out of Disk Space

Clean up old images and containers:

docker system prune -a

Lab Best Practices

Documentation

Create a README for your lab:

# Hacking Lab
## Available Services
- DVWA: http://localhost
- WebGoat: http://localhost:8080
- Juice Shop: http://localhost:3000

## Credentials
- MySQL root:root
- DVWA admin:password

## Common Tasks

Regular Backups

Backup your compose configuration:

git init ~/hacking-lab
git add docker-compose.yml Dockerfile
git commit -m "Initial lab setup"

Version Control

Keep your custom Dockerfiles in version control for consistency across machines.

Resource Limits

Prevent runaway containers from consuming all resources:

dvwa:
  image: vulnerables/web-dvwa
  deploy:
    resources:
      limits:
        cpus: '0.5'
        memory: 512M

Conclusion

Docker transforms hacking lab setup from complex, time-consuming infrastructure work into simple, reproducible containerized environments. By mastering docker-compose, you can spin up realistic multi-tier vulnerable applications in minutes, test exploits, and tear down cleanly. This approach scales from simple learning labs to comprehensive enterprise simulation environments. Start with basic DVWA and MySQL, progress to multi-application labs, and continuously expand your testing capabilities as your skills grow.

#security-testing #hacking-lab #penetration-testing #docker