赞
踩
Docker容器可以提供一个轻量级且独立的运行环境,通常被用于运行后台服务单元,但仍然会存在需要UI界面显示的场景,以下提供了采用X11方式实现的Docker容器中的应用图形界面可视化方案。
X11是一个用于图形窗口环境的标准协议,用于在不同的操作系统上实现图形用户界面。它是在1970年代末和1980年代初由麻省理工学院(MIT)开发的。X11提供了一种机制,使应用程序能够通过网络在不同的计算机上显示图形界面。它提供了许多功能,包括窗口管理、图形绘制、输入处理、事件处理等。X11由服务器和客户端组成。服务器负责运行应用程序并管理窗口、绘制图形等功能,而客户端则是在不同的计算机上运行的程序,它们可以通过网络连接到服务器并发送绘图和事件请求。当X11服务端跟客户端在同一终端中时,可以通过本地unix套接字的方式将显示数据从客户端传递给X11服务端;当X11服务端跟客户端在不同终端上时,则是使用tcp套接字的方式进行数据传输。
如果想在宿主机上去访问容器中的应用界面,可以通过容器与宿主机共享X11的unix套接字来实现,让容器中的应用将显示数据通过宿主机的unix套接字发送给X11服务端处理并绘制到屏幕上。具体操作步骤如下:
xhost +
使用ubuntu镜像创建容器,使用 -v 参数挂载宿主机的/tmp/.X11-unix目录,该目录中存放着unix套接字文件;使用 -e 参数设置容器的DISPLAY环境变量与宿主机一致。
docker run -itd -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY --name test-demo ubuntu
使用docker exec命令进入容器:
docker exec -it test-demo /bin/bash
使用gedit文本编辑器举例,为容器安装gedit程序并启动:
apt update
apt install gedit
gedit
成功在宿主机屏幕上显示gedit程序界面:
如果想在不同终端上访问远程终端容器中的应用界面,可以通过ssh直连容器的方式来实现。具体操作步骤如下:
使用ubuntu镜像创建容器,使用 --net=host 参数设置容器网络模式为host模式,让容器与主机共享网络,确保同一网络下的其他终端能够通过ssh访问到容器:
docker run -itd --net=host --name test-demo ubuntu
进入容器中:
docker exec -it test-demo /bin/bash
安装ssh:
apt update
apt install ssh
安装gedit:
apt install gedit
进入到/etc/ssh目录,将sshd_config文件进行备份:
cd /etc/ssh
cp sshd_config sshd_config.bak
使用追加的方式将以下内容添加到sshd_config文件中:
//将端口号设置为222,避免在宿主机安装了ssh的情况下发生冲突 echo "Port 222" >> /etc/ssh/sshd_config //关闭反向DNS查找,提高性能 echo "UseDNS no" >> /etc/ssh/sshd_config //设置使用IPv4网络进行通信 echo "AddressFamily inet" >> /etc/ssh/sshd_config //指定了用于记录sshd日志的syslog设施 echo "SyslogFacility AUTHPRIV" >> /etc/ssh/sshd_config //允许root登录 echo "PermitRootLogin yes" >> /etc/ssh/sshd_config //允许用户通过输入密码进行身份验证来登录SSH服务器 echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
重启ssh服务:
/etc/init.d/ssh restart
设置容器root密码(如123456):
passwd
假设容器IP为10.17.73.26,使用ssh命令登录容器,其中使用 -X 参数表示在远程主机上启用X11转发,允许在远程服务器上运行的图形应用程序将其显示窗口发送到本地X服务器进行显示;使用 -p 参数指定ssh连接端口为222:
ssh -X root@10.17.73.26 -p 222
然后使用gedit命令,成功将远程容器中的gedit应用界面显示在本地屏幕中:
此时输入 echo $DISPLAY 命令可以看到DISPLAY值如下
上述步骤ssh通过添加 -X 参数启用X11转发的功能来实现访问容器应用界面的功能,但应用界面实际上被限定显示在当前的主屏幕,无法随意更改,灵活性不足。因此我们可以自己通过手动配置Xserver的方式来实现X11转发的效果,还能够灵活变更,具体步骤如下:
LightDM,即:Light Display Manager,是一个全新的、轻量的Linux桌面的桌面显示管理器,LightDM 负责启动 X Server 和其它的 X 程序。而LightDM在启动X Server时,默认给X Server添加了-nolisten tcp 参数,这会导致无法通过tcp方式访问到远程X Server。
这时候需要使用vim去修改/etc/lightdm/lightdm.conf 文件,将 xserver-allow-tcp=false 一行前面的注释去掉,并且改为 xserver-allow-tcp=true。
修改完成后,保存退出,然后重启系统,或者使用 service lightdm restart 命令重启lightdm服务,使配置生效,然后再使用ps命令查看Xorg的执行选项,就发现这时候执行选项变成了 -listen tcp 选项。
xhost +
假设容器IP为10.17.73.26,访问终端IP为10.17.73.20,访问终端使用以下命令登录容器:
ssh root@10.17.73.26 -p 222
使用访问终端IP来设置容器中的DISPLAY环境变量:
export DISPLAY=10.17.73.20:0
然后使用gedit命令,就可以在访问终端屏幕上显示容器中的应用界面。通过上述方式,通过修改DISPLAY环境变量,就可以很容易指定当前容器使用的屏幕是哪个。
"No protocol specified"是一个X11转发错误。它表示在远程主机上找不到有效的显示协议。 通常这个错误都是因为没有解除对本地X服务器上连接客户端的访问限制导致,在本地输入 xhost + 命令来解决访问权限不足问题。
The X11 connection broke: No error (code 0)
XIO: fatal IO error 0 (Success) on X server ":0"
对于这个问题,可以参考以下链接:
https://unix.stackexchange.com/questions/700200/cutter-not-working-over-ssh-x11-forwarding
https://unix.stackexchange.com/questions/1437/what-does-libgl-always-indirect-1-actually-do
通过在容器中设置LIBGL_ALWAYS_INDIRECT环境变量为间接渲染来解决:
export LIBGL_ALWAYS_INDIRECT=1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。