저는 d-bus를 통해 통신하는 마스터와 슬레이브라는 두 개의 애플리케이션을 만들고 있습니다. 내 애플리케이션이 동일한 호스트에서 실행될 때 예상대로 작동합니다.
이제 슬레이브 애플리케이션을 도커 컨테이너로 이동하고 싶지만 호스트와 컨테이너 간에 d-bus 세션을 공유하는 데 문제가 있습니다. 이것은 내 Dockerfile입니다.
i386/ubuntu:16.04에서 볼륨/실행/사용자/1000/ ENV DBUS_SESSION_BUS_ADDRESS=unix:경로=/run/user/1000/bus apt-get 업데이트 실행 apt-get 업그레이드-y 실행 apt-get install -y dbus 실행 #RUN apt-get install -y libnotify-bin #RUN apt-get install -y dbus-x11 adduser -u 1000 myuser 실행 # dbus.conf /etc/dbus-1/session.d/ 복사 사용자 1000:1000 진입점 ["dbus-daemon", "--session", "--print-address"]
/run/user/1000/bus는 내 DBUS_SESSION_BUS_ADDRESS 변수의 값입니다.
나는 컨테이너를 만든다
docker create --mount type=bind,source=/run/user/1000/bus,target=/run/user/1000/bus mycontainer
/run/user/1000/bus는 컨테이너 내부에 표시되지만 컨테이너가 시작되면 주소를 인쇄합니다.
유닉스:추상=/tmp/dbus-iXrYzptYOX,guid=78a790f0f6a4387a39ac3d505da478a3내 애플리케이션이 통신할 수 없습니다.
컨테이너의 /etc/dbus-1/session.d/에 dbus.conf를 추가하고 덮어쓰면
<listen>unix:path=/run/user/1000/bus</listen>
"메시지 버스를 시작할 수 없습니다: '/run/user/1000/bus' 소켓을 바인딩할 수 없습니다: 주소가 이미 사용 중입니다."라는 메시지가 나타납니다.
docker 내에서 dbus-daemon을 시작해야 할지 잘 모르겠습니다.
어떻게 해야 하나요?
답변1
해결책을 찾았습니다. 이것은 내 Dockerfile입니다.
i386/ubuntu:16.04에서 apt-get 업데이트 실행 apt-get 업그레이드-y 실행 apt-get install -y dbus 실행 dbus.conf /etc/dbus-1/session.d/ 복사 ENTRYPOINT ["dbus-run-session", "slaveApp"]
그리고 내 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>
그리고 호스트 시스템에서 주소 변수를 설정합니다.
DBUS_SESSION_BUS_ADDRESS=tcp:host=${containerIp}, 포트=6667,family=ipv4 내보내기
내 주요 애플리케이션에서 연결을 시작합니다(Qt를 사용합니다).
QDBusConnection::connectToBus("tcp:host=${containerIp},port=6667", "qt_default_session_bus");
이제 마스터 애플리케이션은 슬레이브 애플리케이션에 메시지를 보낼 수 있습니다. 하지만 아직 슬레이브에서 마스터로 메시지를 보내려고 시도한 적은 없습니다.
답변은 다음 기사에서 가져왔습니다. https://stackoverflow.com/a/45487266/6509266
답변2
내가 하나 얻을 수 있어요컨테이너화다음 명령을 사용하여 호스트 DBus를 얻으려면 Spotify를 설치하십시오(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
DBUS_SESSION_BUS_ADDRESS
따라서 여기서 핵심은 컨테이너에 호스트 바인딩이 설치되어 있는지 확인하고 동일한 변수를 동일한 값으로 내보내는 것 같습니다 . 컨테이너에 DBus도 설치했는데 부팅 이미지가 없고 Spotify만 실행하고 있다는 점을 고려하면 그럴 필요는 없을 것 같습니다.
답변3
저는 액세스하려는 docker-compose.yml 서비스에 다음을 통합해야 했습니다.
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
(X11 비트가 필요한지 모르겠습니다. dbus 세션 버스 주소와 security_opt가 중요한 비트입니다.)
notify-send
저는 libnotify를 위해 이 작업을 하고 있습니다. 따라서 libnotify-bin 패키지(또는 시스템에 명령을 제공하는 패키지) 가 설치되어 있는지 확인해야 합니다.
그런 다음 하나를 만들고 작동 docker-compose up
하는지 확인하십시오 notify-send hello
!