8

I'm creating two apps, master and slave, which communicate over d-bus. My apps work as expected when being run on the same host.
Now I want to move slave app to docker container and I'm having problem sharing d-bus session between host and container. Here's my Dockerfile:

FROM i386/ubuntu:16.04

VOLUME /run/user/1000/
ENV DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y dbus

#RUN apt-get install -y libnotify-bin
#RUN apt-get install -y dbus-x11

RUN adduser -u 1000 myuser

#COPY dbus.conf /etc/dbus-1/session.d/

USER 1000:1000
ENTRYPOINT ["dbus-daemon", "--session", "--print-address"]

/run/user/1000/bus is the value of my DBUS_SESSION_BUS_ADDRESS variable.

And i create container with

 docker create --mount type=bind,source=/run/user/1000/bus,target=/run/user/1000/bus mycontainer

/run/user/1000/bus is visible from within the container but when the container is started it prints the address

unix:abstract=/tmp/dbus-iXrYzptYOX,guid=78a790f0f6a4387a39ac3d505da478a3
and my apps cannot communicate.

If i add my dbus.conf to /etc/dbus-1/session.d/ in container and override

 <listen>unix:path=/run/user/1000/bus</listen> 
I get the message 'Failed to start message bus: Failed to bind socket "/run/user/1000/bus": Address already in use'

I'm not sure whether I'm even supposed to be starting dbus-daemon inside docker.
How can I make this work?

3 Answers 3

6

I've found a solution. Here's my Dockerfile:

FROM i386/ubuntu:16.04

RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y dbus

COPY dbus.conf /etc/dbus-1/session.d/

ENTRYPOINT ["dbus-run-session", "slaveApp"]

And my dbus.conf:

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
    "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">

<busconfig>
    <listen>tcp:host=localhost,bind=*,port=6667,family=ipv4</listen>
    <listen>unix:tmpdir=/tmp</listen>
    <auth>ANONYMOUS</auth>
    <allow_anonymous/>
</busconfig>

And set the address variable on host:

export DBUS_SESSION_BUS_ADDRESS=tcp:host=${containerIp},port=6667,family=ipv4

In my master app I initiate a connection (I used Qt):

 QDBusConnection::connectToBus("tcp:host=${containerIp},port=6667", "qt_default_session_bus"); 

The master app can now send messages to slave app. I haven't tried to send messages from slave to master, though.

The answer is taken from this post: https://stackoverflow.com/a/45487266/6509266

1

I was able to get a containerised installation of Spotify to grab the host DBus with the following (on Ubuntu)

pkexec systemd-nspawn \
  --setenv=DISPLAY=unix$DISPLAY \
  --setenv=PULSE_SERVER=unix:/run/user/1000/pulse/native \
  --setenv=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
  --bind-ro /tmp/.X11-unix \
  --bind /run/user/1000 \
  --bind-ro /run/user/1000/bus \
  --bind /dev/snd \
  -u spotify \
  -M spotify \
  spotify

So it seems that the key here is to make sure you have bind-mounted the host DBUS_SESSION_BUS_ADDRESS into the container and exported the same variable with the same value there. I have DBus installed on the container as well, but given that I am not booting the image but just running Spotify, I presume it is not required.

1

For me, I needed to merge the following into to the docker-compose.yml service that I wanted to give access to:

    environment:
      - DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
      - DISPLAY=:0

    security_opt:
      - apparmor:unconfined

    volumes:
      - /run/user/1000/bus:/run/user/1000/bus
      - /tmp/.X11-unix:/tmp/.X11-unix

(I don't know whether the X11 bits were needed - the dbus session bus address and security_opt was the important bit)

I was doing this for libnotify - so I needed to make sure the libnotify-bin package was installed (or whatever gives you the notify-send command on your system)

Then do a docker-compose up and check whether notify-send hello works!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .