Ubuntu
Docker 容器內 Ubuntu 上的 D-Bus
我正在建構一個 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
殺死它。