Recently I learnt a bit about Docker while using it on a project. I read large parts of a well written book called “Docker Deep Dive” by Nigel Poulton, and some other articles. Here are my notes about some key highlights of Docker.
- Docker is built on top of a Linux kernel feature called “namespaces”. Namespaces provide a process (or a set of processes) its own isolated view of the resources made available by the operating system — hardware, networking features, which other processes and users are using the system etc. Namespaces are a resource-efficient and quick way to spawn highly isolated sets of processes within the same operating system instance.
- Linux started implementing the system calls related to namespaces around 2008. User namespaces were made available in 2012, which were necessary for the “container” feature. In fact, the Docker Deep Dive book points out that a Docker container is just an “organized collection of namespaces”.
- There is a short conference video from 2013, where the app which went on to become today’s Docker is first demoed publicly:
- Conventionally, Virtual Machine software like VMWare or VirtualBox partition (or virtualize) the hardware that an operating system runs on, and each OS instance running on a machine thinks it is the only one. But all Docker containers use the same instance of the underlying OS/kernel (this does mean that the isolation and security are only as good as what the OS can enforce).
- MacOS doesn’t implement the namespaces kernel APIs. The Mac version of Docker software includes a small Linux VM inside of which the actual Docker containers are spawned.
- You can poke around the namespaces feature on any modern Linux system by using commands like unshare, lsns, nsenter. For example, the below command runs the “whoami” command in a new, isolated user namespace, and hence returns “nobody”:
$ sudo unshare --user whoami
- There are articles like “Containers in a few lines of code” which explore this in greater depth
- Docker uses a library called libcontainer which is written in Go, to implement its namespace based features
- The architecture of Docker has changed over time, as its needs changed. At present, the Docker command talks to a local dockerd process over a HTTP API. dockerd calls upon the above mentioned libcontainer library via a command line wrapper called “runc”. dockerd also has lots of functionality related to Docker config files, downloading Docker images from online registries and so on.
- There are a few GUI wrappers for Docker that let you inspect and manage the running containers on a system. This blog post provides a comparison. I myself am yet to try any of these.
You can read more about Linux namespaces and its basis for Docker in these articles: