Using systemd in Docker


Table of Contents


This is basically part 2 of my systemd hurdles during Ansible development on Windows. For part 1, please read Enabling systemd in WSL 2 on Windows 11 22H2 without Insider. After that, 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.


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


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.


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


# 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:

[[email protected] 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!