Kudos to https://www.flickr.com/photos/bakokojp/12213874763

Containers are a lie

Michael Hausenblas
Microservices Practitioner Articles
3 min readOct 18, 2016

--

Well, sort of anyways.

Or, to be more precise: containers are a useful abstraction, just like TCP connections are. But they don’t exist, as such.

Woah, what do you mean? I’m using containers and I know they exist.

Well, not really. When you do, say:

docker run -d nginx:1.10

then really, there are no containers running on the host machine.

What you really did with above command is: you launched a process group on steroids, like so:

But, but, but … I was promised isolation! And being able to throttle resource consumption!

Glad you asked. So, I said initially containers are an abstraction: they are ‘made out of’ Linux namespaces and cgroups.

Now, most of the time you don’t really need to care about namespaces and cgroups. In fact, some argue that the beauty and the current hype around containers stem from the fact that the abstraction is so well done. The UX is so great that often you don’t (have to) look further. All you care is that you can tell your container orchestration system of choice (such as DC/OS or Kubernetes) to run a certain container image and you’re done.

But every now and then there are cases where you need to or want to open the box and look inside, be it for educational purposes or because you’re in trouble and need to understand what’s wrong with your container.

Now, myself being in above mentioned situations rather often, I got fed up manually cat-ing and ls-ing my way through /proc, where all the relevant information is available, and trying to keep track how things fit together.

That’s why I wrote cinf, a simple command line tool to inspect namespaces and cgroups. With cinf you can have a look at what’s going on under the hood (and since it’s written in Go, should be simple to install and extend, should you wish to):

$ sudo cinf

NAMESPACE TYPE NPROCS USER OUSER

4026531840 mnt 96 0 0
4026531836 pid 97 0 0
4026532194 uts 2 0 0
4026532295 ipc 1 0 0
4026532198 net 2 0 0
4026532294 uts 1 0 0
4026531838 uts 97 0 0
4026532196 pid 2 0 0
4026531856 mnt 1 0 0
4026532296 pid 1 0 0
4026532298 net 1 0 0
4026531839 ipc 97 0 0
4026531956 net 97 0 0
4026531837 user 100 0 0
4026532193 mnt 2 0 0
4026532195 ipc 2 0 0
4026532293 mnt 1 0 0

Above you see a couple of namespaces active—within the six supported types: Mount, UTS, IPC, PID, Network, and User—and also that most of the processes are in one cluster and only a few (our Docker container) make up a second cluster. We can also dig deeper, looking at a specific namespace (4026532194 in this case):

Now you see the cgroups in use by the container we launched.

OK, that was it. Hope it was as a useful discourse and maybe, one day, you find yourself in a situation where you need to see for yourself how the sausage is made and then you know there’s a tool for it ;)

--

--