Fixing 'Failed to get D-Bus connection: Operation not permitted' in Docker

intermediate🐧 Linux2026-07-27| Docker containers running Linux distributions (Ubuntu, CentOS, Debian, RHEL) that use systemd as an init system.

Error Message

Failed to get D-Bus connection: Operation not permitted
#systemd#dbus#docker#container#systemctl

The ProblemYou try to run systemctl start nginx or systemctl status ssh inside a Docker container. Instead of the service starting, you're hit with this infamous error:

Failed to get D-Bus connection: Operation not permitted

Docker containers are designed to be lightweight and isolated. By default, they lack the permissions to talk to the host's D-Bus or manage system services. Systemd expects to be the first process (PID 1). It also requires direct access to the host's control groups (cgroups), which Docker restricts for security.

Why this happens at 2 AMStandard images like ubuntu:22.04 or centos:7 don't start an init system by default. When you run docker run -it ubuntu /bin/bash, the bash shell becomes PID 1. Systemd isn't even running in the background. When systemctl tries to find the systemd daemon via D-Bus, it hits a wall. The container simply doesn't have the privileges to talk to the host's bus, so the operation fails.

Solution 1: The Privileged Flag and Cgroup MountingSometimes you must run systemd, perhaps for testing Ansible playbooks or legacy apps. The fastest fix is granting the container extended privileges and mounting the host's cgroup file system. This effectively gives the container "root-like" access to the host hardware.

Step-by-step:- Stop and remove your current container.- Launch a new one using the --privileged flag.- Mount /sys/fs/cgroup as a read-only volume.For a CentOS 7 image, the command looks like this:

docker run -d \ 
  --name my-container \ 
  --privileged \ 
  -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ 
  centos:7 /usr/sbin/init

Note: You must use /usr/sbin/init as the starting command. This kicks off the systemd process as PID 1 inside the container.

Solution 2: Using a Specialized Systemd Image (Recommended)Vanilla base images are a headache to configure for systemd. Instead, use community-maintained images pre-configured for this exact purpose. The jrei images are the industry standard here. They handle the complex handshake between Docker and systemd automatically.

For Ubuntu:```

docker run -d \ --name systemd-ubuntu \ --privileged \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ jrei/systemd-ubuntu


### For CentOS:```
docker run -d \ 
  --name systemd-centos \ 
  --privileged \ 
  -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ 
  jrei/systemd-centos

Access the container after it starts:

docker exec -it systemd-ubuntu bash

Run systemctl status. You should see a functional service tree instead of an error.

Solution 3: The Dockerfile ApproachBuilding a custom image? You need to install systemd and clean up unnecessary units that might fail in a virtualized environment. Here is a proven snippet for Ubuntu 22.04:

FROM ubuntu:22.04

ENV container docker
RUN apt-get update && apt-get install -y systemd systemd-sysv && apt-get clean

# Strip down systemd to run inside a container
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
    systemd-tmpfiles-setup.service ] || rm -f $i; done); \
    rm -f /lib/systemd/system/multi-user.target.wants/*;\
    rm -f /etc/systemd/system/*.wants/*;\
    rm -f /lib/systemd/system/local-fs.target.wants/*; \
    rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
    rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
    rm -f /lib/systemd/system/basic.target.wants/*;\
    rm -f /lib/systemd/system/anaconda.target.wants/*;

VOLUME [ "/sys/fs/cgroup" ]
CMD ["/lib/systemd/systemd"]

Verification: How to confirm the fixOnce the container is running, run two quick checks. First, verify systemd is PID 1:

ps -p 1 -o comm=

It should return systemd or init. Next, check the system status:

systemctl status

If you see the standard systemd status tree, you've successfully bypassed the D-Bus restriction.

Important Security WarningThe --privileged flag is a sledgehammer. It breaks the container sandbox and lets processes inside the container potentially interfere with your host system. Avoid this configuration for any public-facing production environment. It is strictly for local development or controlled CI/CD testing.

Pro Tip: Do you really need systemd?Docker best practices suggest running one process per container. Instead of using systemctl start nginx, run the service binary directly in the foreground. This keeps your image small—often saving 100MB+ in disk space—and significantly more secure.

  • For Nginx: CMD ["nginx", "-g", "daemon off;"]- For Apache: CMD ["apache2ctl", "-D", "FOREGROUND"]By skipping systemd, you avoid the D-Bus headache entirely and follow the cloud-native way.

Related Error Notes