如何在没有任何真实的显示的情况下在docker中运行GUI应用程序?

juud5qan  于 2023-06-21  发布在  Docker
关注(0)|答案(1)|浏览(149)

我正在尝试在docker(debian)中构建CI/CD管道。其中一个步骤使用第三方python应用程序,该应用程序在某个时候加载一些GUI库。如果我在我的系统上运行同样的命令,不会出现任何窗口,也不需要用户交互。该应用程序似乎是完美的快乐运行在命令行只。
但是,如果我尝试在docker容器中运行它,我会得到这个错误

Unable to access the X Display, is $DISPLAY set properly?

我试着(但失败了)设置X显示器。但即使我这样做了,它也帮不了我,因为整个过程的dockerizing点是在无头服务器上运行它。
有没有一种方法可以在docker镜像上附加一个假的显示,这样应用程序就可以正确加载了?或者至少在我的本地机器上模拟相同的情况,这样我就可以单步执行python代码并找到问题所在?

bcs8qyzn

bcs8qyzn1#

解决方案

在docker内部运行,将docker容器连接到主机显示器,得到GUI输出。

应用程序需要请求Xserver来显示其GUI元素。还有一个为安全设计的授权系统,我们稍后会讨论。
在我们的例子中,由于容器使用host的硬件,因此不需要为Container配置Xserver。我们所需要的就是使我们的容器能够与主机Xserver对话
前面提到,联系Xserver需要授权,这个授权系统叫做xauth。xauth通常将会话cookie存储在 /home/username/.Xauthority 文件中(通常但不总是)。

*检查当前使用的Cookie

xauth list

输出看起来像这样,

localhost.localdomain/unix:0  MIT-MAGIC-COOKIE-1  99aaccf2d83177ddf581e2989ebbcea1
#ffff##:0  MIT-MAGIC-COOKIE-1  99aaccf2d83177ddf581e2989ebbcea1

*如果Xauthority不在通常的位置,请检查使用的是哪个权限文件

xauth

如果未使用标准文件,则输出将类似于下图,

Using authority file /run/user/1000/xauth_Abcde

我们需要把这两样东西放进集装箱

*MIT-MAGIC-COOKIE-1-现在只将其视为协议或标识符。这对于每个会话都是恒定的。
*99 aaccf 2d 83177 ddf 581 e2989 ebbcea 1-这个32个字母的密钥是会话密钥,或者你想给它起的任何花哨的名字。每个会话的密钥都是唯一的。
现在要解决与显示相关的问题,我们需要做这五件事,

1.如果容器中尚未存在.Xauthority文件,则创建该文件
1.将会话密钥和协议添加到我们创建的.Xauthority文件中
1.将DISPLAY环境变量传递给容器
1.将主机Xserver套接字(通常位于 /tmp/.X11-unix)装载到容器
1.将网络类型设置为 * 主机 *(显示渲染所需)
这5个步骤将修复与显示相关的所有问题。

示例

该方法适用于任何GUI应用,本示例使用firefox GUI进行演示。

这五个步骤是如何按时间顺序处理的:
1.在容器文件RUN touch .Xauthority中完成
1.都作为环境变量传递
Containerfile ENV PROTOCOL=MIT-MAGIC-COOKIE-1中的协议集
会话密钥作为参数传递给podman run--env KEY=$(xauth list | sed '2,$d'| tr -d '\n' | tail -c 32) \(不能作为常量传递到容器文件中,因为它会更改会话)
然后通过CMD xauth add ${HOST}:0 $PROTOCOL $KEY从Containerfile添加到权限文件
1.作为参数传递给podman run--env DISPLAY \
1.作为参数传递给podman run--mount type=bind,source=/tmp/.X11-unix,target=/tmp/.X11-unix,readonly \
1.在构建映像podman build --network=host --tag guitest .时配置

容器文件

FROM debian:latest

ARG DEBIAN_FRONTEND=noninteractive

RUN apt update && apt upgrade
RUN apt install --no-install-recommends --yes firefox-esr pipewire pipewire-alsa pipewire-pulse ffmpeg xauth

ENV PROTOCOL=MIT-MAGIC-COOKIE-1

ENV HOME /home/def
ENV USER def

RUN useradd --create-home --home-dir ${HOME} -G audio,video ${USER} && chown -R ${USER}:${USER} ${HOME}

WORKDIR ${HOME}
USER ${USER}

RUN touch .Xauthority

CMD xauth add ${HOST}:0 $PROTOCOL $KEY && firefox

Build命令

podman build --network=host --tag guitest .

使用构建好的镜像运行Container

podman run -it --rm --name guiapp \
--env DISPLAY \
--env KEY=$(xauth list | sed '2,$d'| tr -d '\n' | tail -c 32) \
--mount type=bind,source=/tmp/.X11-unix,target=/tmp/.X11-unix,readonly \
guitest

宾果!

**免责声明:**音频将无法工作,这需要更多的工作要做。

相关问题