背景
linux 系统中,对于窗口 GUI 应用,有大佬定义了 X11 规范,Xorg 是这个规范的一个实现。
X11 把窗口管理系统设计为一个 C / S 架构,app 作为 client 通过 unix socket 或者 tcp 链接到 server,这样就能显示窗口,当然也能反向接受键鼠的事件。
现在假设遇到一个 linux 上的 gui 软件,它在使用前需要进行安装和配置,如果把它打包成 docker 镜像,可以方便以后的使用,并且防止 linux 大版本更新带来的不兼容。
系统版本
Xubuntu 24.04
构建容器时的方案
适用于在构建容器时,需要在 gui 里进行一些配置时使用这个方法。
由于在构建容器时没法挂载本地目录,这里选择配置主机上的 xorg 服务器,开启 tcp 连接,主机通过 tcp 传递窗口数据。
修改 Xorg 配置
sudo nano /usr/bin/Xorg
里面的内容大概是这样
basedir=/usr/lib/xorg
if [-x "$basedir"/Xorg.wrap]; then
exec "$basedir"/Xorg.wrap "$@"
else
exec "$basedir"/Xorg "$@"
fi
在这两行的末尾添加 -listen tcp
让 Xorg 服务器监听 tcp
basedir=/usr/lib/xorg
if [-x "$basedir"/Xorg.wrap]; then
exec "$basedir"/Xorg.wrap "$@" -listen tcp
else
exec "$basedir"/Xorg "$@" -listen tcp
fi
关闭安全验证
允许任何 X11 客户端连接,不验证密码。
xhost +
构建 docker 镜像
示例 Dockerfile 程序
FROM ubuntu:24.04
# 安装一些 GUI 示例程序
RUN apt-get update && apt-get install -y \
x11-apps
# 设置 DISPLAY 环境变量
ARG DISPLAY
ENV DISPLAY=$DISPLAY
# xclock 会显示一个时钟,用它做测试
# 在构建时打开,模拟需要初始化设置的操作
RUN ["xclock"]
# xcalc 会显示一个计算器
# 在运行容器时候打开,模拟正常使用软件的操作
CMD ["xcalc"]
DISPLAY
环境变量指示了程序应该显示在哪,X11 规范里定死的。
像这样,传入宿主机的 ip 和屏幕编号,他就会用 tcp 连接屏幕。
注意不能用 localhost。
docker build . -t app --build-arg DISPLAY=1.1.1.99:0
构建时,xclock 窗口会弹出,把这个窗口关闭后构建才会继续。
运行容器时的方案
在镜像构建完成后,运行容器可以采用 unix socket 的方式把窗口数据从容器传到主机。
这样速度稍快,并且避免了修改 Xorg 的配置。
关闭安全验证
允许任何 X11 客户端连接,不验证密码。
xhost +
运行容器
docker run -it \
-e DISPLAY=:0.0 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
app
这样应该会弹出计算器。
DISPLAY
变量不写 ip 的话,它默认走 unix socket,也就是我们挂载的那个。这也是规范的一部分,就在这个位置、叫这个名。