Skip to content
Go back

Understanding Docker

Published:  at  05:00 AM

In the end of this tutorial, you will be able to work with docker files effortlessly.

Intro

When I first started playing CTFs, I used to be given zip files, ie., challenge.zip.

And in that zip file I kept seeing either Dockerfile or sometimes both, Dockerfile and docker-compose.yml.

Recently, I played a UMDCTF, and there I was given ld-linux-x86-64.so.zip, a pwn challenge:

hafizfarhad.com@vm:~$ ls
ld-linux-x86-64.so.zip
hafizfarhad.com@vm:~$ unzip ld-linux-x86-64.so.zip
hafizfarhad.com@vm:~$ ls
Dockerfile  ld-linux-x86-64.so.2  libc.so.6  Makefile  offbyone  offbyone.c
hafizfarhad.com@vm:~$

When I unziped it, I could see a Dockerfile in it.

If you’re new to CTFs like me, these files might seem confusing.

Basically, 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.

Basics

Docker helps you create “containers” - like mini virtual machines that run specific applications. The beauty is that these containers work the same way on everyone’s computer.

In most of the challenges, you’ll typically see one or two main files:

Dockerfile - This file contains Instructions to build a single container

docker-compose.yml - The file contains Instructions to build multiple containers that work together

When to use which file? Always use docker-compose.yml file if given.

Commands

When I’m given these files in a CTF, here’s what I typically do:

If you haven’t installed docker, checkout the manual.

For challenges with a docker-compose.yml file:

# Build the containers (the --no-cache makes sure everything is fresh)
docker compose build --no-cache

# Start the containers in the background
docker compose up -d

# See all running containers
docker ps -a

# When you're done, shut everything down
docker compose down -v

Sometimes you will only be given Dockerfile. In that case:

# 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

Debugging

I’ve encountered various problems and learned useful commands along the way:

Always make sure to add sudo before commands, otherwise you might get “permission denied” errors.

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), while challenge-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.

Cleanup

When you want to cleanup everything, use these commands:

# Remove all Docker images
docker rmi -f $(docker images -q)

# Remove everything - containers, networks, volumes
docker system prune -af --volumes

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!

Additional Resources



Next Post
Understanding Git and Github