A lot of practice CTF content ships as a Docker image specifically so you can run the vulnerable target locally, isolated from your real system, and reset it instantly if you break or crash it.
1. Installing Docker
Install Docker Desktop (Mac/Windows) or Docker Engine (Linux) from docker.com, then confirm it's working:
docker --version
docker run hello-world
2. Pulling and running a target
Most vulnerable-practice images are published on Docker Hub. Pull one and run it, mapping its internal port to one on your own machine:
docker pull vulnerables/web-dvwa
docker run -d -p 8080:80 vulnerables/web-dvwa
The target is now reachable at http://localhost:8080 — isolated inside the container, with nothing it does able to touch your actual filesystem.
3. Resetting instantly when something breaks
Practice challenges sometimes end up in a broken state after an exploit attempt (a crashed service, a corrupted database). Rather than debugging the container's internal state, just throw it away and start fresh:
docker rm -f $(docker ps -aq --filter ancestor=vulnerables/web-dvwa)
docker run -d -p 8080:80 vulnerables/web-dvwa
This is the actual point of containerizing practice targets — a clean restart costs seconds, not a system reinstall.
4. Building your own target from a Dockerfile
For a custom practice setup (your own deliberately vulnerable script, a specific library version with a known CVE), a minimal Dockerfile is usually enough:
FROM python:3.11-slim
COPY vulnerable_app.py /app/
WORKDIR /app
CMD ["python3", "vulnerable_app.py"]
Build and run it the same way: docker build -t my-target . && docker run -p 8080:8080 my-target.
Wrapping up
Once you're comfortable running targets this way, OverTheWire's Bandit wargame is a natural next step that needs no Docker at all — just SSH. Our Bandit Level 0 writeup covers getting started there, and how CTF scoring works if you're about to join a timed event for the first time.