The session focuses on running Docker inside VZ containers:
* what makes our use case different from others — we have to control how Docker accesses to the resources of host system
* devicemapper graphdriver and proxy graphdriver
* how to pass a mount point made on host system to container namespace
https://linuxplumbersconf.org/2015/ocw/proposals/3351
2. Docker proxy graphdriver
VZ container docker proxy daemon
devicemapper
graphdriver
dm-thin
dm-thin pool
data metadata
ioctl-s, mkfs, mount
/var/lib/docker/proxy/devmapper/mnt/dm-thin
Docker container
$ docker run … $ docker –d –s proxy …
unix socket
Editor's Notes
1. Hi! My name is Maxim Patlasov, I'm working for Parallels, my report will deal with Docker support in VZ containers.
2. A few months ago we started to work on adding Docker support to VZ containers --
in the other words we'd like to allow people to run Docker deamon and Docker client inside containers
3. Docker is getting increasingly more and more popular, and openvz/virtuozzo is the leader among
hosting providers, so there is high demand on Docker support now: people who buy virtual environments from
hosters would like to run Docker, and also, people want to deploy kubernetes in ovz clusters.
4. In this report I'd like to share our experience of running Docker in VZ containers, but most of
concerns are relevant to any other OS-level container solution as well.
5. The issues we encountered fall roughly in two categories:
things related to nested namespaces, cgroups and systemd and
things related to docker storage -- so-called docker graphdrivers
6. The first category deals with the questions like:
- how to virtualize cgroups properly
- how to avoid a mess in systemd-to-systemd communications
- is it OK to allow container users to create and mount cgroups
7. The second category deals with docker graphdrivers -- the way how docker keeps and organize run-time storage for container files.
Graphdriver API consists of methods like Create/Remove/Get/Put where Create creates brand-new space for container and Get returns
a mount-point referring to this space. Docker comes with a bunch of different graphdrivers, but the only suitable one for RHEL6-
and RHEL7-based distros is so-called device-mapper graphdriver.
8. But enabling devicemapper graphdriver in container as-is is very dangerous because it requires access to a couple of
block-devices, permissions to issue ioctls on /dev/mapper/control, format and mount a filesystem (ext4 by default) on top
of dm-thin device.
9. The solution we developed looks like this:
<picture>
Let's implement new graphdriver -- "proxy" graphdriver as we called it -- who will transparently pass those Create/Remove/Get/Put calls
to a proxy-daemon running on host system. The daemon will perform all those dangerous operations on behalf of its client -- and its
client in this model is the docker daemon running inside container. It's important that now all dangerous operations come from trusted
source -- container users cannot modify or bypass the proxy-daemon. So, no risk of compromising the whole system by incorrect operation
issued my malicious or buggy container user.
10. I published a skeletion of this solution a couple of mounts ago, but full-fledged implementaton took a while because I decide to
make it usable not only for VZ containers, but for Docker development containers as well. A few days ago I completed it and made
a pull-request:
<picture>
11. Soon after that Brian Goff -- an active Docker contributer -- pointed me to his pull request:
<picture>
12. The idea is rougly the same and the implementations is similar, but I must admit his one is much smarter.
There are currently two types of Docker plugins in existance: network drivers and volume drivers. Brian Goff
suggest third type: graphdriver plugins. This will allow anyone to implement and run any custom graphdriver as
process separate from ordinary docker daemon.
13. This Brian's implementation mostly suits for our needs. The only thing it lacks is "Init" handler.
Brian believes it's fine to fully initilize graphdriver on startup and this startup must happen before
in-contaiener docker-daemon startup.
And I argue, that we cannot predict exact storage-options that container user will want to specify in
course of docker-daemon startup. So, it's absolutely natural to postpone Init up to the moment
user starts docker daemon. But then, client part of proxy graphdriver must send Init command to
the graphdriver daemon.
And for some reasons Brian disagree. I'd like to encourage everyone who is initerested to loop in
and help to find a soolutoion for this small issue suitable both for Dockder guys and for people
interested in Docker in OS-level containers.