Docker运行带UI界面的应用,并将它的界面投射到你的Windows电脑

 

困难:Docker运行带UI界面的App

平时我们用Kubernetes或者Docker运行的App,都是后台类的,比如Web-Server,或者计算任务。App自己并不需要打开窗口,大都是接受请求,然后按要求进行计算,最后返回结果这样。

但是假设你要跑一个有UI界面的App时,比如常见的QT类应用,就会遇到报错:

docker run -it sshipway/xclock

Error: Can't open display:

搜索结果一般告诉你,这是由于DISPLAY变量没有设置。于是我们得了解下,DISPLAY变量的作用。

 

X11窗口显示规范

X11是一种操作系统UI界面的显示规范,最初是1984年麻省理工学院的研究,之后变成UNIX、类UNIX、以及OpenVMS等操作系统所一致适用的标准化软件工具包及显示架构的运作协议。

所以,目前各种App的界面,都是使用X11规范来显示图形化的。


其中X11协议,由X Server来实现,即你的App连上X Server服务器就行了(当然了,X Server也有权限控制,不是谁都可以“隔空投屏”的)。

具体参考:https://en.wikipedia.org/wiki/X_Window_System

 

所以Docker跑带界面的App报错,意思为:没有指定X Server在哪里

 

Linux系统中DISPLAY变量是干嘛的?

Linux/Unix类操作系统上,界面显示都使用X11规范。

DISPLAY变量是用来设置将图形显示到何处的。(即你的目标 X Server 在哪里)。

 如果你登录的Linux是带UI界面的,那么这个值一般为“:0.0

如果你登录的Linux没有UI的话,比如SSH到一台UbuntuVM里,那么这个值很可能就是空的。

 

DISPLAY 环境变量格式如下 host:NumA.NumB

 

host是指投射至哪台主机。如果为本机,则host为空。其他主机,则填对应ip

NumA

本机时,代表unix socket的路径, 如果为0, 则表示连接到/tmp/.X11-unix/X0 .

远端时,表示端口减去6000的值, 假设NumA0, 则表示连接到6000端口。

NumB:一般都是0

详情可以参考:https://zhuanlan.zhihu.com/p/93165237

 

容器App,投射界面至容器所在的Host

根据上面的背景知识。我们知道,想投射界面至本机Host上面,那么需要在容器里面将DISPLAY变量=HostDISPLAY变量”。同时,还要将unix socket文件,挂载到容器里面。


 即:docker run 参数里面要带上以下2个参数

-v /tmp/.X11-unix:/tmp/.X11-unix        #共享本地unix端口

-e DISPLAY=$DISPLAY                      #修改环境变量DISPLAY

 

同时,在主机上面,应该将 X Server的权限打开:

xhost +

这样,你的容器应该就可以启动了。

(由于我没有带界面的Linux系统,所实际效果暂无截图)

可参考:https://www.youtube.com/watch?v=cMsIT2otEjA

 

容器App,投射界面至你的Windows系统

想投射界面至远程Windows系统上面,一样的道理,首先咱们先在Windows上面安装 X11Server


 需要在容器里面将DISPLAY变量=“目标IP:0.0”。具体NumA是几,要看你自己的配置情况,一般情况是0。这样容器App,就会“隔空投屏”到你的Windows电脑上面了。

 

安装X11 Server

咱们的Windows主机上面要安装X Server软件,这里推荐2个:

1VcXsrv Windows X Server

https://sourceforge.net/projects/vcxsrv/files/vcxsrv/

 

最新版本的,安装有报错。最后我选了 vcxsrv-64.1.20.1.4.installer 这个版本是好用的。

一路默认就行,最后一步这里有2个地方小注意:

  • 权限控制,记得打钩。 即允许别人远程投屏。


  • 有些App自带的图像lib库太老,不认识X Server。(app启动报错:

libGL error: No matching fbConfigs or visuals found

libGL error: failed to load driver: swrast

这种情况,启动咱们的X Server时,需设置好兼容模式(即上图第2条)。所以我们可以给Windows系统加了条环境变量,如下图:


 

2MobaXterm

这个启动后,X Server默认就启动了。所以不需要太多配置。


Setting里面可以关注下权限等配置。

启动咱们的带UI的容器App

这里选择一个“时钟显示”的示例App

docker pull sshipway/xclock

docker run -e DISPLAY=10.173.103.40:0.0 -it  sshipway/xclock

其中IP地址,就是你的电脑

不出意外,你的Windows系统,会弹出一个窗口,如下:


恭喜,完成任务。

 

总结

Docker容器运行带UI界面的App的时候,需要在容器里面,指定DISPLAY变量。告诉容器系统,应该把界面投射至哪个目标X Server。

(完)