在 Docker 容器中运行 Qt GUI

Azi*_*uth 12 c++ qt docker

因此,我有一个基于 Qt5 的 C++ GUI,我想从 Docker 容器内运行它。

当我尝试开始时

docker run --rm -it my_image
Run Code Online (Sandbox Code Playgroud)

这会导致错误输出

qt.qpa.xcb: could not connect to display localhost:10.0
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
Run Code Online (Sandbox Code Playgroud)

所以我寻找如何做到这一点。我在 docker 容器中找到了 GUI Qt 应用程序,并基于此调用它

QT_GRAPHICSSYSTEM="native" docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix my_image
Run Code Online (Sandbox Code Playgroud)

这导致了同样的错误。

然后我发现可以在 Docker 容器中运行 GUI 应用程序吗?
那里接受的答案似乎特定于某些应用程序,例如 Firefox?
进一步向下滚动,我得到了一个解决方案,告诉我设置X11UseLocalhost no然后sshd_config调用它

docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/") my_image
Run Code Online (Sandbox Code Playgroud)

这会产生上述错误的轻微变化:

qt.qpa.xcb: could not connect to display 127.0.1.1:13.0
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
Run Code Online (Sandbox Code Playgroud)

根据另一个答案,我添加ENV DISPLAY :0到我的 Dockerfile 中并使用

xhost +
XSOCK=/tmp/.X11-unix/X0
docker run -v $XSOCK:$XSOCK my_image
Run Code Online (Sandbox Code Playgroud)

这次,我的错误的第一行是qt.qpa.xcb: could not connect to display :0

然后我尝试了另一个答案,补充道

RUN export uid=0 gid=0 && \
    mkdir -p /home/developer && \
    echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
    echo "developer:x:${uid}:" >> /etc/group && \
    mkdir /etc/sudoers.d/ && \
    echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
    chmod 0440 /etc/sudoers.d/developer && \
    chown ${uid}:${gid} -R /home/developer
Run Code Online (Sandbox Code Playgroud)

到我的 Dockerfile 并调用docker run -ti --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix my_image,再次出现同样的错误。

我还尝试了http://wiki.ros.org/docker/Tutorials/GUI中描述的几种方法,同样的错误。


难道我做错了什么?请注意,我正在通过 SSH 在远程计算机上工作,当然打开了 X11 转发(并且该应用程序在 Docker 之外运行得很好)。另请注意,我编写的是客户端-服务器-应用程序,服务器部分不需要 GUI 元素,但共享大部分源代码,在其容器中工作得很好。

我希望有一个不需要我更改系统的解决方案,因为我使用 Docker 的首要原因是让我的应用程序的用户能够轻松运行它。

phi*_*hag 5

您有多个相互覆盖的错误。首先,确保您安装了正确的库。如果你的 docker 镜像是基于 debian 的,它通常看起来像一行

RUN apt-get update && \
    apt-get install -y libqt5gui5 && \
    rm -rf /var/lib/apt/lists/*
ENV QT_DEBUG_PLUGINS=1
Run Code Online (Sandbox Code Playgroud)

注意环境变量QT_DEBUG_PLUGINS。这将使输出更有帮助并引用任何缺失的库。在现在非常详细的输出中,查找如下内容:

Cannot load library /usr/local/lib/python3.9/site-packages/PySide2/Qt/plugins/platforms/libqxcb.so: (libxcb-icccm.so.4: cannot open shared object file: No such file or directory)

加粗部分为缺失的库文件;您可以使用您的发行版的包管理器(例如在 debian 上)找到它所在的包dpkg -S libxcb-iccm.so.4

接下来,像这样启动 docker(可以是一行,为清楚起见分开):

docker run \
  -e "DISPLAY=$DISPLAY" \
  -v "$HOME/.Xauthority:/root/.Xauthority:ro" \
  --network host \
   YOUR_APP_HERE
Run Code Online (Sandbox Code Playgroud)

确保替换/root为来宾用户的主目录。

高级图形(例如游戏、3D 建模等)也可能需要/dev安装-v /dev:/dev. 请注意,这将为来宾提供对硬盘的根访问权限,因此您可能希望以更细粒度的方式复制/重新创建设备。