我正在尝试在docker(debian)中构建CI/CD管道。其中一个步骤使用第三方python应用程序,该应用程序在某个时候加载一些GUI库。如果我在我的系统上运行同样的命令,不会出现任何窗口,也不需要用户交互。该应用程序似乎是完美的快乐运行在命令行只。
但是,如果我尝试在docker容器中运行它,我会得到这个错误
Unable to access the X Display, is $DISPLAY set properly?
我试着(但失败了)设置X显示器。但即使我这样做了,它也帮不了我,因为整个过程的dockerizing点是在无头服务器上运行它。
有没有一种方法可以在docker镜像上附加一个假的显示,这样应用程序就可以正确加载了?或者至少在我的本地机器上模拟相同的情况,这样我就可以单步执行python代码并找到问题所在?
1条答案
按热度按时间bcs8qyzn1#
解决方案
在docker内部运行,将docker容器连接到主机显示器,得到GUI输出。
应用程序需要请求Xserver来显示其GUI元素。还有一个为安全设计的授权系统,我们稍后会讨论。
在我们的例子中,由于容器使用host的硬件,因此不需要为Container配置Xserver。我们所需要的就是使我们的容器能够与主机Xserver对话。
前面提到,联系Xserver需要授权,这个授权系统叫做xauth。xauth通常将会话cookie存储在 /home/username/.Xauthority 文件中(通常但不总是)。
*检查当前使用的Cookie
输出看起来像这样,
*如果Xauthority不在通常的位置,请检查使用的是哪个权限文件
如果未使用标准文件,则输出将类似于下图,
我们需要把这两样东西放进集装箱
*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 .
时配置容器文件
Build命令
使用构建好的镜像运行Container
宾果!
**免责声明:**音频将无法工作,这需要更多的工作要做。