Running systemd inside a docker container (arch linux)

Solution 1:

Here my master pice :D running systemd inside a docker container with ubuntu :D I Got Ubuntu working with systemd inside docker

GitHub Repo for my docker-systemd container

$ docker run -it --cap-add SYS_ADMIN -v /sys/fs/cgroup:/sys/fs/cgroup:ro dockerimages/docker-systemd

Output:

systemd 218 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT -GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID -ELFUTILS +KMOD -IDN)
Detected virtualization 'docker'.
Detected architecture 'x86-64'.

Welcome to Ubuntu Vivid Vervet (development branch)!

Set hostname to <502ec40509a5>.
[  OK  ] Created slice Root Slice.
[  OK  ] Created slice System Slice.
         Starting Emergency Shell...
[  OK  ] Started Emergency Shell.
Startup finished in 5ms.
Welcome to emergency mode! After logging in, type "journalctl -xb" to view
system logs, "systemctl reboot" to reboot, "systemctl default" or ^D to
try again to boot into default mode.
root@502ec40509a5:~# exit

Update 2020

First of all base/archlinux image is deprecated - you should use archlinux/base instead. Then, to run systemd totally unprivileged, number of things should be done:

  • provide a container= variable, so systemd won't try to do number of things it usually does booting a hardware machine
  • systemd actively uses cgroups, so bind mount /sys/fs/cgroup file system from a host
  • bind mounting /sys/fs/fuse is not required but helps to avoid issues with fuse-dependent software
  • systemd thinks that using tmpfs everywhere is a good approach, but running unprivileged makes it impossible for it to mount tmpfs where ever it wants, so pre-mount tmpfs to /tmp, /run and /run/lock
  • as the last bit you need to specify sysinit.target as default unit to boot instead of multi-user.target or whatever, as you really do not want to start graphical things inside a container

The resulting command line is

docker run \
  --entrypoint=/usr/lib/systemd/systemd \
  --env container=docker \
  --mount type=bind,source=/sys/fs/cgroup,target=/sys/fs/cgroup \
  --mount type=bind,source=/sys/fs/fuse,target=/sys/fs/fuse \
  --mount type=tmpfs,destination=/tmp \
  --mount type=tmpfs,destination=/run \
  --mount type=tmpfs,destination=/run/lock \
    archlinux/base --log-level=info --unit=sysinit.target

If we are talking about running particular service there like ntpd from your example you will need to add

--cap-add=SYS_TIME

otherwise ntpd will fail with permission deny as nobody wants a container to set system time by default.

Solution 2:

To run systemd in a Docker container, the host system must also run systemd. This means you cannot use Ubuntu < 16.04 as the host.


Solution 3:

Currently systemd does not run correctly within a docker container, due to a whole set of reasons, i.e. the lack of the correct privileges. You can read up on that in a variety of github issues on the docker project like running systemd inside docker arch container hangs or segfaults and related issues regarding init/process monitoring. (I would like to link more issues here, but I can't as I apparently don't have enough reputation).

As you can see, this is a topic that is currently being worked on and a few patches have been merged already to improve behavior, so that we can expect this to work quite soon.

Apparently some developers already managed to get it to run on fedora systems, as they have documented in their blog.