moby: Running systemctl in container fails with "Failed to get D-Bus connection"

I searched Issues and while I found other bugs that seemed similar, I couldn’t tell if they were exactly the same as this so I apologize if this is a repeat.

After following the steps on this blog to setup docker on Fedora, when you run systemctl you get an error about failing to connect to dbus.

bash-4.2# systemctl list-units
Failed to get D-Bus connection: No connection to service manager.

Docker version: docker-io-0.6.3-3.devicemapper.fc19.x86_64 OS: Fedora 19 (Schrödinger’s Cat)

About this issue

  • Original URL
  • State: closed
  • Created 11 years ago
  • Reactions: 12
  • Comments: 57 (19 by maintainers)

Most upvoted comments

systemd needs SYS_ADMIN, and if seccomp filtering is available, this needs to be disabled, or overridden with a custom profile. Try;

docker run -it \
  --security-opt seccomp=unconfined \
  --cap-add=SYS_ADMIN \
  -e "container=docker" \
  -v /sys/fs/cgroup:/sys/fs/cgroup \
  centos:7 /usr/sbin/init

edit: current versions of docker should not longer need to have seccomp disabled, so the example below should work;

docker run -it \
  --cap-add=SYS_ADMIN \
  -e "container=docker" \
  -v /sys/fs/cgroup:/sys/fs/cgroup \
  centos:7 /usr/sbin/init

@sunshineo (and other people commenting here) if you do not specify exactly, from scratch, exactly what steps you did, no one is going to be able to help you. It matters exactly what Docker commands you use to start the image, what Docker version you use, what you type after that, how you log in, and exactly which images you use. systemd does work fine in a properly configured container, on a properly configured system, but the exact detail matters. If you cannot get it to work, I recommend using an image that does not use systemd as it is much easier.

try running container with --privileged=true

docker run -d --privileged-true --name=contname image-name 

Folks, this is really frustrating but I suggest for now to run the command line listed :

# /usr/bin/mongod --quiet --config /etc/mongod.conf

this should start the system properly and manually 😉

@durgaswaroop Try with docker exec command to bypass the username and password prompt:

eg: #Run a container docker run -it -e "container=docker" --privileged=true -d --security-opt seccomp:unconfined --cap-add=SYS_ADMIN -v /sys/fs/cgroup:/sys/fs/cgroup:ro local_redis bash -c "/usr/sbin/init"

#Exec bash to get shell docker exec -it [ContainerID] /bin/bash

Please checkout for more info: https://github.com/kheshav/dockerSystemctl

@alanwilter containers are not VM’s; generally a container should have a single responsibility (and have a single main process). Think of containers as a mechanism to sandbox a process; each process gets its own sandbox (“container”), and you combine those sandboxes to build up your application.

The instructions you’re trying to follow assume that rabbitmq is installed on a full machine / VM where multiple processes are in the same sandbox (“the host”), in which case you need an init system to handle those processes.

If you install in a container, and don’t install multiple things in that container, there’s no need to have an init-system (in some exceptional cases you may need a minimal init to “reap” stray child processes; this can be handled by docker through the --init option on docker run or by configuring it on the daemon).

For rabbitmq; you may want to consider using the official rabbitmq image from Docker Hub, which is configured according to best practices for running in a container. If you want to build your own image, you can still use it as a reference/example; https://github.com/docker-library/rabbitmq/blob/f57f88450660d1daaf195e30d05d746279faab40/3.7/debian/Dockerfile

If you do have to install multiple things in a container (think twice, as you’d be doing away with a lot of the advantages and security that containers provide), and if you want to use systemd as an init system (in many cases a more lightweight init may be sufficient, because systemd does a lot), systemd must be the container’s main process (“PID1”), not bash

@trinitronx I’d be very careful running with those options;

  • privileged:true is equivalent to --cap-add ALL, disabling selinux, and (iirc) disabling seccomp profiles. Effectively, the container does not provide any protection, and root inside the container can take over the host
  • --cap-add ALL also allows root inside the container to take control of the host
  • Because you already added --cap-add ALL, adding SYS_ADMIN, NET_ADMIN, NET_BIND_SERVICE, and NET_BROADCAST does nothing (these are already part of ALL)

Got this error when using kitchen-docker to test systemd services on debian & ubuntu images.

To fix it, I used the following .kitchen.docker.local.yml:

## If you want to use one of the kitchen-docker* drivers...
## You should symlink this file to: .kitchen.local.yml
## Hint: Make sure you have kitchen-docker and kitchen-docker-api gems installed
## Then set DOCKER_HOST=tcp://my-docker-host.example.com:4243
---
## driver name: docker is for portertech/kitchen-docker
driver:
  name: docker
## driver_plugin: docker is for adnichols/kitchen-docker-api

driver_config:
#  hostname: kitchen
#  use_sudo: true
  socket: <%= ENV['DOCKER_HOST'] %>
  privileged: true
  provision_command:
    - echo "SSHD_OPTS='-o UseDNS=no -o UsePAM=no -o PasswordAuthentication=yes -o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid'" > /etc/default/ssh
  run_command: /sbin/init
  cap_add:
    - ALL
    - SYS_ADMIN
    - NET_ADMIN
    - NET_BIND_SERVICE
    - NET_BROADCAST

platforms:
- name: debian-8.1
- name: ubuntu-16.04

Tests then ran in test-kitchen with a SystemD enabled container with:

export KITCHEN_LOCAL_YAML=.kitchen.docker.local.yml
kitchen test

To fix DBus & default SystemD target for other services which depended on DBus, I had to add:

  provision_command:
    - apt-get -y install dbus
    - echo "SSHD_OPTS='-o UseDNS=no -o UsePAM=no -o PasswordAuthentication=yes -o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid'" > /etc/default/ssh
    - ln -s /lib/systemd/system/systemd-logind.service /etc/systemd/system/multi-user.target.wants/systemd-logind.service
    - mkdir /etc/systemd/system/sockets.target.wants/
    - ln -s /lib/systemd/system/dbus.socket /etc/systemd/system/sockets.target.wants/dbus.socket
    - systemctl set-default multi-user.target

Instead of running the underyling apachectl commands directly, one could also use a tool to read the *.service where that line is present anyway. That’s what the initial implementation of my systemctl.py script did.

Later it was expanded to even cover the case for running as an /sbin/init replacement. So there is no need for --priviledge mode or cgroups mapping, all the systemctl commands work without access to a systemd daemon. Have a look at the docker-systemctl-replacement for more details.

For anyone else who comes here from search results: there’s an Ubuntu-derived image meant for running systemd.

How did you start the container exactly? It looks like you started an “application container”, as opposed to a “machine container”. An “application container” just runs a specific process (or group of processes); essentially it just runs what you need. A “machine container” will run a full init, possibly with ssh, syslog, etc. If you start an application container, it doesn’t have a real init process, and since systemctl talks to the init process… you get the idea 😃