The biggest barrier to actually practising web pen-testing is the friction of getting a vulnerable target running. Spin up a VM, install LAMP, copy DVWA in, configure the database, fight permissions, miss a step, start over. By the time you're actually attacking something it's 90 minutes later and your motivation is gone.

The Docker cyber lab solves that. docker compose up brings the whole environment online in under 30 seconds. docker compose down -v nukes it. The lab is reproducible, shareable, and lives entirely on its own bridge network so I can't accidentally point an exploit at the wider LAN.

30 S
COLD START
4
CONTAINERS
ISOLATED
PRIVATE BRIDGE
YAML
~80 LINES TOTAL

The compose file

# docker-compose.yml — the entire lab
networks:
  labnet:
    driver: bridge
    ipam:
      config: [{ subnet: 172.20.0.0/24 }]

services:
  kali:
    image: kalilinux/kali-rolling
    container_name: kali
    networks: { labnet: { ipv4_address: 172.20.0.10 } }
    cap_add: [ NET_ADMIN, NET_RAW ]
    tty: true; stdin_open: true
    volumes: [ ./loot:/loot ]

  dvwa:
    image: vulnerables/web-dvwa
    container_name: dvwa
    networks: { labnet: { ipv4_address: 172.20.0.20 } }

  juiceshop:
    image: bkimminich/juice-shop
    container_name: juiceshop
    networks: { labnet: { ipv4_address: 172.20.0.30 } }

  pihole:
    image: pihole/pihole
    container_name: pihole
    networks: { labnet: { ipv4_address: 172.20.0.40 } }
    environment: { TZ: Europe/London, WEBPASSWORD: labpass }

Why each container is in there

Kalithe attacker · burp, nmap, sqlmap, metasploit, hydra
DVWAclassic vulnerabilities · SQLi, XSS, CSRF, file upload, command inj
Juice Shopmodern OWASP top-10 · JWT, NoSQL, XXE, prototype pollution
Pi-holeDNS observability · see what attack tools resolve

DVWA covers the classics — the kind of vulnerability you find when you read SQL injection tutorials. Juice Shop is the modern flavour — JWT manipulation, NoSQL injection, prototype pollution, the bugs that show up in actual JavaScript/SPA codebases. Together they span what you actually see in the wild.

The isolated network is the point

The bridge network labnet has no route to the host. Containers can talk to each other, can't reach my LAN, can't reach the internet. This means I can run aggressive scans, fuzzers, exploit chains without worrying about collateral. If something escapes the target container, the worst it can do is hop to another container on the same isolated subnet.

why this matters

The first time I ran sqlmap with default settings against a "test" target on my home LAN, it found a vulnerability in my router's admin page. Default sqlmap is aggressive. Network isolation is not paranoia — it's the difference between a lab session and an outage.

The Kali container is the workstation

Kali boots into a TTY. docker exec -it kali bash drops me in. Tools live where I expect them. The ./loot volume mount means anything I save is persistent across restarts — wordlists I've generated, scan reports, JWTs I've cracked. The container itself is ephemeral; the loot dir is mine.

[ TYPICAL SESSION ]
  $ docker compose up -d
  $ docker exec -it kali bash
  # nmap -sV 172.20.0.0/24                  # what's alive?
  # nikto -h http://172.20.0.20             # DVWA recon
  # sqlmap -u "http://172.20.0.20/..."      # SQLi automation
  # ./juice-shop-tools/dump-jwt.sh          # JWT exfil
  $ docker compose down -v                  # done. clean again.
  

What it doesn't replace

The Docker lab is for web app and basic infra practice. It doesn't teach you Wi-Fi attacks (no radio), AD/Kerberos (need Windows containers + a domain), or kernel/binary exploitation (containers share the host kernel). For the things it covers — and that's 80% of what the average pen-test looks like — it's the fastest reset button I've ever set up.

Friction is the enemy of practice. Every minute of setup is a minute of motivation lost. The Docker lab is what made hands-on practice routine again — when the cost of starting is 30 seconds, you start.