When I first started playing CTFs, I kept seeing these Dockerfile
and docker-compose.yml
files in challenges. If you’re new to CTFs, these files might seem confusing, but they’re actually there to help you.
Simply put, these files let you recreate the exact same environment that’s running on the challenge server. This means you can test your exploits locally before trying them on the actual challenge server.
Docker Basics
Docker creates “containers” - like mini virtual machines that run specific applications. The beauty is that these containers work the same way on everyone’s computer.
You’ll typically see two main files:
Dockerfile - Instructions to build a single container
docker-compose.yml - Instructions for multiple containers that work together
Commands
When I’m given these files in a CTF, here’s what I typically do:
For challenges with a docker-compose.yml file:
# Build the containers (the --no-cache makes sure everything is fresh)
sudo docker-compose build --no-cache
# Start the containers in the background
sudo docker-compose up -d
# See all running containers
sudo docker ps -a
# When you're done, shut everything down
sudo docker-compose down -v
For challenges with only a Dockerfile:
# Build the container
docker build -t challenge-name .
# Run the container (maps port 8080 on your computer to port 80 in the container)
docker run -d -p 8080:80 --name challenge-name-container challenge-name
# Stop the container when done
docker stop challenge-name-container
# Remove the container
docker rm challenge-name-container
When things get messy, I use these cleanup commands:
# Remove all Docker images
docker rmi -f $(docker images -q)
# Remove everything - containers, networks, volumes
docker system prune -af --volumes
Basically docker-compose.yml
is the go-to tool when you need to run multiple containers that work together.
I’ve encountered various problems and learned useful commands along the way:
If you get “permission denied” errors, add sudo
before commands.
If a port is already in use, change the port mapping:
docker run -d -p 9090:80 --name challenge-name-container challenge-name
To see container logs:
docker logs challenge-name-container
To find a container’s IP address:
docker inspect challenge-name-container | grep IPAddress
challenge-name
is the Docker image (template), whilechallenge-name-container
is the running instance created from that image. You can create multiple different containers from the same image, each with its own settings.
Wrapping Up
Being able to run challenges locally helps you test ideas quickly without worrying about challenge server timeouts or bans. As you get familiar with these commands, you’ll start to see patterns in how challenges are set up, which can give you hints about where vulnerabilities might be hiding.
Happy hacking!