How to Properly Run systemd Inside an Arch Linux Docker Container: A Complete Guide


2 views

Running systemd inside Docker containers has been a persistent challenge for developers working with systemd-dependent applications. The fundamental issue stems from how Docker containers differ from full virtual machines in their initialization process.

Before attempting to run systemd, ensure your environment meets these requirements:

# Verify Docker version
docker --version

# Check for necessary kernel features
grep -E 'cgroup|systemd' /proc/filesystems

Here's the proper way to launch an Arch Linux container with systemd:

docker run -it --name arch-systemd \
  --privileged \
  --tmpfs /run \
  --tmpfs /tmp \
  -v /sys/fs/cgroup:/sys/fs/cgroup:rw \
  archlinux /sbin/init

Several critical adjustments make this work:

  • --privileged flag provides necessary permissions
  • tmpfs mounts for /run and /tmp prevent permission issues
  • Read-write cgroup mount (not read-only) is essential
  • /sbin/init as the entrypoint launches systemd properly

For simpler use cases, consider this Python-based alternative:

# Dockerfile snippet
RUN pacman -Sy --noconfirm python && \
    curl -L https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl.py \
    -o /usr/bin/systemctl

If you encounter problems, check these diagnostics:

# Inside the container:
journalctl -b
systemctl status
ls -la /sys/fs/cgroup

Running systemd in containers adds overhead. For production environments, consider:

  • Disabling unnecessary systemd services
  • Using --cpuset-cpus to limit CPU allocation
  • Implementing resource constraints with --memory

When using privileged containers:

# Create a dedicated systemd-nspawn container instead:
machinectl pull-tar https://example.com/archlinux.tar.xz arch
machinectl start arch

Running systemd inside a Docker container isn't straightforward because Docker containers aren't designed to run init systems by default. When you try to start systemd in an Arch Linux container, you'll typically encounter the error:

Trying to run as user instance, but the system has not been booted with systemd.

To properly run systemd, your container needs:

  • Privileged mode or specific capabilities
  • Proper cgroups mounting
  • Correct tmpfs mounts
  • DBus configuration

Here's a complete Docker command that works for Arch Linux:

docker run -it --rm --name arch-systemd \
  --privileged \
  -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
  -v /tmp:/tmp \
  --tmpfs /run \
  --tmpfs /run/lock \
  -e "container=docker" \
  archlinux /usr/lib/systemd/systemd

Let's examine each part:

--privileged

Gives the container access to all host devices and capabilities.

-v /sys/fs/cgroup:/sys/fs/cgroup:ro

Mounts the host's cgroups read-only into the container.

--tmpfs /run --tmpfs /run/lock

Creates temporary filesystems that systemd requires.

If you don't need full systemd functionality, consider using this Python script that mimics systemctl commands:

RUN curl https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl.py \
    -o /usr/bin/systemctl && chmod +x /usr/bin/systemctl

Problem: "Failed to create /init.scope control group"

Solution: Add --cgroupns=host to your docker run command

Problem: DBus errors

Solution: Add -v /run/dbus:/run/dbus to share the host's DBus

Here's a sample Dockerfile for an Arch Linux container with systemd:

FROM archlinux
RUN pacman -Syu --noconfirm systemd
RUN echo -e '#!/bin/sh\n/usr/lib/systemd/systemd' > /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

Running systemd in Docker requires privileged mode, which has security implications:

  • Consider using --cap-add instead of --privileged when possible
  • Isolate the container on its own network
  • Use read-only root filesystem when practical

Once your container is running, verify systemd is working:

docker exec -it arch-systemd systemctl status