Ubuntu

Docker 容器內 Ubuntu 上的 D-Bus

  • April 29, 2021

我正在建構一個 Docker 映像,用於執行一堆使用 D-Bus 相互通信的後台程序。我將圖像基於 Ubuntu Bionic。該系統已經在原生 Debian 9 上執行。

我需要做什麼才能使 D-Bus 在容器內工作?我通過Google搜尋找到了一些想法,但網際網路上的大多數問題都是關於在容器和主機之間使用 D-Bus,而我只需要連接容器內執行的程序。到目前為止,我最成功的嘗試都失敗了,錯誤消息提示缺少與 X11 相關的東西,這是真的,因為此時我根本沒有安裝 X11。

我將在容器內執行並連接到的 D-Bus 服務範例:

#!/usr/bin/env python

import gobject
import dbus
import dbus.service
import dbus.mainloop.glib
import sys

service_name = "com.testservice"
object_path = "/testservice"
interface_name = service_name

class SomeObject(dbus.service.Object):

   def __init__(self, bus, object_path):
       dbus.service.Object.__init__(self, bus, object_path)
   
   @dbus.service.method(service_name, in_signature='', out_signature='')
   def Exit(self):
       mainloop.quit()


if __name__ == '__main__':
   dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

   session_bus = dbus.SessionBus()
   name = dbus.service.BusName(service_name, session_bus)
   object = SomeObject(session_bus, object_path)

   mainloop = gobject.MainLoop()
   mainloop.run()

目前,嘗試啟動該服務會給出以下輸出:

Traceback (most recent call last):
 File "/hostwork/dbus-test.py", line 35, in <module>
   session_bus = dbus.SessionBus()
 File "/usr/lib/python2.7/dist-packages/dbus/_dbus.py", line 211, in __new__
   mainloop=mainloop)
 File "/usr/lib/python2.7/dist-packages/dbus/_dbus.py", line 100, in __new__
   bus = BusConnection.__new__(subclass, bus_type, mainloop=mainloop)
 File "/usr/lib/python2.7/dist-packages/dbus/bus.py", line 122, in __new__
   bus = cls._new_for_bus(address_or_type, mainloop=mainloop)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11

我自己找到了解決方案:

在我的 Dockerfile 中,我安裝了包 dbus,但沒有與 X11 相關。我還安裝了我的軟體的所有依賴項,包括我在問題中共享的 Python 腳本的依賴項。

在我的 Dockerfile 中,我有以下幾行:

COPY start.sh /usr/local/bin
RUN chmod +x /usr/local/bin/start.sh
ENTRYPOINT ["/bin/bash", "/usr/local/bin/start.sh"]

start.sh 的內容是這樣的:

#!/usr/bin/env bash

export DBUS_SESSION_BUS_ADDRESS=`dbus-daemon --fork --config-file=/usr/share/dbus-1/session.conf --print-address`

exec bash

這樣,執行容器會給我一個適當設置 DBUS_SESSION_BUS_ADDRESS 的 shell。我可以執行測試腳本後台並說

dbus-send --print-reply --session --dest=com.testservice /testservice com.testservice.Exit

殺死它。

引用自:https://unix.stackexchange.com/questions/646934