SystemDocker
Getting Started w/ Docker and Systemd
SystemD?
So before anyone starts with all the Systemd hate I want to direct you to this comment by none other than Linus himself.
"I don't actually have any particularly strong opinions on systemd itself. I've had issues with some of the core developers that I think are much too cavalier about bugs and compatibility, and I think some of the design details are insane (I dislike the binary logs, for example), but those are details, not big issues."
So there. Get over yourselves. If you don't like systemd then write an alternative. Otherwise keep your trap shut and learn.
What is it?
Systemd was designed at Red Hat by Lennart Poettering and Kay Sievers. They wanted to get past the awfulness of the init daemon and create an improved framework for expressing service dependencies. In an interview w/ The CoreOS Team Lennart, who originally was a believer in upstart said:
When we looked closer at Upstart we eventually realized that its fundamental design was backwards – at least in our opinion. We thought a system manager should calculate the minimal amount of work to do during boot-up-
Since then, we have been developing systemd steadily, taking a lot of inspiration from the system managers of other operating systems, in particular Solaris' SMF framework, as well as MacOS X's launchd system. Originally systemd was supposed to be just an "init" system, i.e. just one process that is responsible for the most fundamental logic of starting up your Linux userspace. However, we eventually realized that we actually wanted to solve more than just this one problem, and began to rework and unify a larger part of how Linux userspace is brought up and maintained during runtime.
QuickStart
Systemd has two main components; Units, a configuration files that describe the process that you want to run, and Targets, or processes that all need to be run together at a certain point in the init cycle.
In Systemd services are defined using unit files which are normally located in /etc/systemd, /var/lib/systemd, /usr/lib/systemd, and /run/systemd. If you are still trying to connect this to the old SysV init then think of these directories like /etc/init.d and all of these .service files as init scripts. Each of the .service files defines all of the things that a service can do, dependencies it has, targets, etc. Interaction w/ these services is now handled through a utility called systemctl. For those of us who still remember Solaris this is sounding a lot like svcadm. Here are some examples of old style and new style service commands.
service <name> start systemctl start name.service
service <name> reload systemctl reload name.service
service --status-all systemctl list-units --type service --all
When you install docker you get the following systemd files.
/usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket
[Service]
Type=notify
ExecStart=/usr/bin/docker daemon -H fd://
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
/usr/lib/systemd/system/docker.socket
[Unit]
Description=Docker Socket for the API
PartOf=docker.service
[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
These two files define the default settings for the Docker service and Docker socket. In general we don't want to edit these default system files. We want them updated when we install a new version of Docker. So how do you modify the startup? There are two options here. First you can copy the service and socket files to /etc/systemd/system. This location overrides the default locations. Or you can use drop in directories. We prefer this method because it allows us to overwrite just the configuration we want to change.
Docker Drop In
Lets create our Docker drop in directory and configure Docker in accordance w/ the Docker Docs.
# sudo mkdir /etc/systemd/system/docker.service.d
Create the following files and save them as daemon.conf and proxy.conf.
/etc/systemd/system/docker.service.d/daemon.conf
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// -g /docker
[Service]
Environment="http_proxy=http://<proxy.server.com>:8000"\ "https_proxy=http://<proxy.server.com>:8000"
Notice the ExecStart lines in the first file. When modifying lists like that we first have to unset the list and then reset it. Here we are simply changing the graph location and setting up the proxy server, if you have one.
Now you can control Docker with systemctl. systemctl start docker.service
Note we can actually drop the .service extension and be left with just systemctl start docker
Default Containers
Other than the daemon one of the nice things to do with systemd is start your default containers. These can be things like logging, kv stores, or clustering like swarm. To give you an idea here is what it would look like to start a redis container at the multi-user target w/ systemd.
[Unit]
Description=Docker redis service
Author=Me
After=docker.service
[Service]
Restart=always
ExecStart=/usr/bin/docker start -a redis_server
ExecStop=/usr/bin/docker stop -t 2 redis_server
[Install]
WantedBy=multi-user.target
Gotchas
One of the biggest issues w/ using Systemd to manage docker containers is that it doesn't actually manage the container, rather it manages the docker client. This can create issues like the ones talked about Docker Issue 6791. Fortunately Darren Shepherd has built a great little utility called systemd-docker .
This is a wrapper for docker run so that you can sanely run Docker containers under systemd. The key thing that this wrapper does is move the container process from the cgroups setup by Docker to the service unit's cgroup. This handles a bunch of other quirks so please read through documentation to get an understanding of all the implications of running Docker under systemd.
Happy Hacking!