I’ve always been fascinated by how things work “under the hood” — especially when it comes to tools we use every day in development. Docker is one of those tools. We all use docker run
or docker build
, but what actually happens when we run those commands? How does it isolate processes? What is a container really? I didn’t want a surface-level answer — I wanted to break it down and understand how Docker works at the system level.
That curiosity led me to build Mini Docker, a project where I reimplemented a minimal version of Docker in Go. The goal wasn’t to compete with Docker, of course, but to learn by doing. I focused specifically on what happens when you run a container — building my own version of docker run
from scratch.
This project gave me deep insights into how containers are built on top of Linux kernel features. I implemented key concepts like:
CLONE_NEWPID
, CLONE_NEWUTS
)chroot
and temporary root directoriesTo truly understand Docker, I also had to learn how its architecture works. The real Docker uses several components:
containerd
spawns a shim processIn my implementation, I focused on the very bottom of that stack — the part where the container process is created and isolated using syscalls. I built the logic for the container lifecycle: fetching an image, unpacking it, isolating the environment, and executing a binary inside it. In other words, I reimplemented a tiny slice of what runc
does.
In practice, my program:
alpine:latest
All the container logic is implemented in pure Go, and I’ve wrapped it with a small shell script to simplify execution. On macOS or Windows, I used Docker only to spin up a Linux environment so I could compile and test my code — the actual containerization is handled entirely by my own program, not by Docker itself.
I didn’t build this project just to write code — I built it to learn. Now I understand exactly how Docker works at a low level. I can explain why certain syscalls are needed, how image layers are structured and merged, and what really happens when a container starts. It’s helped me become a better system-level programmer, and gave me a deep respect for the elegance of containerization.