Using systemd in Docker

     

Table of Contents

Preamble

This is basically part 3 of my systemd hurdles during Ansible development on Windows. Now you should have a shell with operable systemd on Windows. If you’re on Linux, you should have systemd by default, so all is well so far.

So now the obvious next step is to make systemd usable in Docker, right? So what does systemd require to be usable in a container?

  • The host be booted with systemd, obviously.
  • The container having systemd installed.
  • The default CMD be set to the systemd executable.
  • A bunch of sysfs and tmpfs bind mounts be set.
  • The container be started as privileged.
  • Since CMD’ing into systemd gives you a login prompt where you can’t login (since there’s no credentials set to begin with), you need to start the container with docker run --detach, then perform the actual commands via docker exec where you don’t need to login.

Images

All those steps, that’s a pain in the arse, right? So that’s exactly why I made a bunch of Dockerfiles:

noobient/ansible-systemd

I was also kind enough to publish the built images to Docker Hub:

bviktor @ Docker Hub

So now you can just:

docker pull bviktor/ansible-systemd-fedora:37

Right? Well, almost.

Containers

Like I said, these need to be started in a specific way. Assuming you wanna run a Fedora 37 container:

platform="fedora:37"

# Fire up the container
CONT_ID=$(docker run --rm -v $(pwd):/repo -v /sys/fs/cgroup:/sys/fs/cgroup:ro --tmpfs /tmp --tmpfs /run --privileged --detach "bviktor/ansible-systemd-${platform}")

# Enter the container
docker exec -it "${CONT_ID}" bash

# Once done, stop the container
docker stop "${CONT_ID}"

So now you can finally do all the systemd stuff:

[root@01776b8afbda system]# systemctl status crond
● crond.service - Command Scheduler
     Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; preset: enabled)
     Active: active (running) since Sun 2023-03-12 22:08:29 UTC; 1min 5s ago
   Main PID: 41 (crond)
      Tasks: 1 (limit: 19138)
     Memory: 968.0K
     CGroup: /docker/01776b8afbdadc191ea99683ee60973bf7033765bd19df8b86e7531b6d11f99e/system.slice/crond.service
             └─41 /usr/sbin/crond -n

Aaand that’s it. Now you have systemd. Next time we’ll find out why this will all break in WSL when you try to use something tricky like firewalld, and also how to fix it. Stay tuned!