Docker运行GUI程序

image

Linux 本身是没有图形化界面的,所谓的图形化界面系统只不过中 Linux 下的应用程序。这一点和 Windows 不一样。Windows 从 Windows 95 开始,图形界面就直接在系统内核中实现了,是操作系统不可或缺的一部分。Linux 的图形化界面,底层都是基于 X 协议。

X 协议由 X server 和 X client 组成:

举个例子,如果用户点击了鼠标左键,因为鼠标归 X server 管理,于是 X server 就捕捉到了鼠标点击这个动作,然后它将这个动作告诉 X client,因为 X client 负责程序逻辑,于是 X client 就根据程序预先设定的逻辑(例如画一个圆),告诉 X server 说:“请在鼠标点击的位置,画一个圆”。最后,X server 就响应 X client 的请求,在鼠标点击的位置,绘制并显示出一个圆。

image

这么绕,有啥意义呢?当然有!

许多时候 X server 和 X client 在同一台主机上,这看起来没什么。但是, X server 和 X client 完全可以运行在不同的机器上,只要彼此通过 X 协议通信即可。于是,我们就可以做一些“神奇”的事情,比如在本地显示 (X server),运行在服务器上的 GUI 程序 (X client)。这样的操作可以通过 SSH X11 Forwarding (转发) 来实现。

X11 中的 X 指的就是 X 协议,11 指的是采用 X 协议的第 11 个版本。

默认情况下,X11的服务端会监听本地的unix:0端口,而DISPLAY的默认值为:0,这实际上是unix:0的简写。因此如果在Linux的控制台启动一个图形程序,它就会出现在当前主机的显示屏幕中。

基于这个原理,将Docker中的GUI程序显示到外面,就是通过某种方式把X11的客户端的内容从容器里面传递出来。

安装 X server

brew install --cask xquartz
open -a XQuartz

在偏好设置中勾选“Allow connections from network clients”:

image

允许xhost接收:

/opt/X11/bin/xhost +

检验一下:

$ /opt/X11/bin/xhost
access control enabled, only authorized clients can connect

因为每个unix套接字实际上就是系统/tmp/.X11-unix目录下面依据套接字编号命名的一个特殊文件,所以可以让容器和主机共享X11的unix套接字,直接将数据发送出来。

Dockerfile

FROM ubuntu:14.04
RUN sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
RUN apt-get update && apt-get install -y x11-apps
CMD xclock
docker build -t xclock .
docker run -ti --rm --privileged \
    -e DISPLAY=docker.for.mac.localhost:0 \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    xclock

其中的-v /tmp/.X11-unix:/tmp/.X11-unix参数就是将主机上X11的unix套接字共享到了容器里面。运行后你就可以看到如下的图形界面:

image

如果容器在远程服务器上,可以使用SSH的X11-Forwarding功能将数据传输到本地,不过配置相对麻烦一些,这里仅给出思路:

[应用程序]->[X11客户端]->[SSH服务端]->[SSH客户端]->[X11服务端]->[显示屏幕]

posted @ 2021-01-01 12:06:29
评论加载中...
发表评论