Build your own container using less than 100 lines of Go

So I stumbled upon this article from 2016: [](

It basically shows how by using a few relativity simple Linux syscalls you can run a process in a basic container. While I'm aware that this is not directly related to Docker, I found it quite interesting, and while this is obviously very minimal it does open your eyes a bit for what happens behind the scenes when you run a container.

Thought you folks will appreciate it.

6 thoughts on “Build your own container using less than 100 lines of Go”

  1. This is the Manual page that essentially let me understand what “containers” (or “jails” in BSD) are made of:

    The command `netns` for instance is used to manage network namespaces, which effectively gives you an independent network stack down to the kernel. Rinse and repeat for all 7 types of namespaces and you’ve got a “container”! (cgroups being a matter of quotas + security in terms of load + isolation within the host resources).

    You have to remember that deep down in Linux, the filesystem *is* the system (see this page, eg. the `/proc`, `/run`, `/var`, `/dev` folders). Everything, every variable is somewhere in some file. Try to `cat /proc/cupinfo` for instance, you get you CPU specs and *current* clock, it’s a different value every time you run it; likewise `/dev` is populated at boot with all hardware devices and does represent direct mountpoints for these in the fs, including the “sink” `/dev/null` when you just want to throw things away — or generate zeros as input).

    So from a base (“natively” booted) Linux fs, a container is pretty much just a “fork” of that base OS, that base filesystem (remember too that you can symlink or mount anything anywhere… including RAM space, thus ‘RAM drives’ for that matter, which helps modern computers run fast). The ‘magic’ on Linux is that such functions are now baked in the kernel, so it’s just there waiting to be used.

    The Go implementation in that article seems like a fairly straightforward implementation of a basic container, as you can see in this line

    Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS

    basically just creating new UTS, PID, NS types of namespaces here.

    As far as I understand it, Docker is basically a giant wrapper on all these features, to make them easily usable without requiring technical knowledge of these things (only about whatever you want to run in one such container).

    For those interested in network shenanigans, this series of 8 posts goes incredibly deep and contains troves of very digestible information: (it goes into VLANS and all sorts of fun things)

    You quickly realize that, the way Linux is built, you could pretty much create and run a whole infrastructure (ie. machines and networks) on a single physical host, without even requiring VMs or wrappers like Docker. You can do it all with bash, basically. It’s honestly mind-blowing and impressive. Implement it as systemd services and you’ve potentially got a custom IS built from scratch.

  2. Ok, if you find it interesting, then you folks might find the [Containers]( category on my blog interesting too. I usually try to explain the containerization tech in a nutshell (not in terms of number of words per article, but rather in terms of how many abstraction layers I’m trying to peel). For instance in this article I tried to show that [containers are simply isolated and restricted Linux processes]( and no image with a full-fledged OS distribution is really required to spin up a container. Or in my most recent article I was unveiling the networking part and tried to explain that the [containers networking is nothing more than a combination of well-known Linux network facilities ](

    There is indeed no magic behind any particular bit of this tech. But the emerged end-product is truly magical.


Leave a Comment