远程服务器或者docker运行GUI程序

目的:远程服务器或者docker运行GUI程序,可以不使用VNC等工具

MAC电脑安装XQuartz:
官网:https://www.xquartz.org/

window电脑安装:MobaXterm
官网:https://mobaxterm.mobatek.net/download-home-edition.html

通过SSH链接docker

  1. 启动docker容器
docker run -it -d -p local:docker 镜像 /bin/sh
  1. 登陆docker内
docker exec -it 容器名称 /bin/sh
apt update
apt install openssh-server
apt install vim

passwd   // 给root账号赋予密码

vim /etc/ssh/sshd_config
// 修改两个位置
/***
第一:把ssh 服务默认的22端口设置为与容器服务的端口一致,设置为启动过程中:dockerip,
因为我们运行容器的时候挂载的是内部的docker端口映射到宿主机的local端口,
所以需要和容器内部端口保持一致,

第二:将PermitRootLogin prohibit-password修改为PermitRootLogin yes,开启使用密码登录,设置完成后保存退出

第三:确定下X11Forwarding yes 是否为yes

*/

service ssh restart   // 重启ssh服务
  1. 链接docker测试
ssh -p docker端口 root@远程IP

-------------------------------现在SSH链接正常,下一步进行X11服务图形显示----------------

  1. docker 启动参数
FOLDER=/path/to/your/data/on/host        // 挂载的本地机器的目录,和docker的共享目录
docker run -it -e DISPLAY=host.docker.internal:0 -e "QT_X11_NO_MITSHM=1" \
    -v "/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    -v "$FOLDER:/data" 容器名称
  1. 执行顺序
1. XQuartz -> 偏好设置 -> 安全性 -> 勾选“允许从网络客户端连接” -> 退出程序;
2. 终端键入 xhost + ip(注意两者之间的空格)重新启动 XQuartz;为远程主机添加权限
或者xhost +为所有IP添加权限
3. ssh -XY root@0.0.0.0 -p 6100
4. netstat -an | grep -F 6100 查看

5. apt install x11-apps
6. 在 run 或 exec 容器时加入-e DISPLAY=host.docker.internal:0参数,比如我这里通过对一个现有的,已经安装过 xarclock 时钟小程序的容器 toyOS 执行docker exec -ite DISPLAY=host.docker.internal:0 toyOS /usr/bin/xarclock,就会在我的本地出现一个小时钟的GUI程序;

参数解释

如何让 Docker 中的 X Client 与宿主机的 X Server 实现交互
作为 X Client 的程序如果想与 X Server 进行交互,大致分为两种方式:

  • 在命令后加--display参数并指明相关的位置
  • 用户提前设置好环境变量 DISPLAY ,程序从该变量获得相关信息

这里我们采用第二种方式,故在启动容器时通过-e参数为其设置 DISPLAY 变量,现在的问题在于,如何解释变量的值 host.docker.internal:0 呢?
对于该变量中,冒号前面的部分,Docker 官方文档中有如下解释:

The host has a changing IP address (or none if you have no network
access). From 18.03 onwards our recommendation is to connect to the
special DNS name host.docker.internal, which resolves to the internal
IP address used by the host.

也就是说,这个值本质上是获得了宿主机的内部IP,为了验证这一点,可以通过ifconfig命令来查看宿主机实际的IP,并将 DISPLAY 的值换成 your_ip:0 ,可以发现和前面一样可以运行。之所以本次实验采用了前者,是因为要获取实际IP,第一是过程很麻烦,第二是设备要处于联网的状态下,而在文档的描述中可以看到 (or none if you have no network access) 这句话,也就是说,这种参数设置在无网络的条件下也可以正常运行。
那么 DISPLAY 的值就可以被解释为 your_ip:0 了,关于这个格式,其实它的完整形式为your_ip: display_number. screen_number,在本实验中其实可以写为 host.docker.internal:0.0display_numberscreen_number 均从0开始计数,前者表示一个输入流的标号(输入流包括显示器,键盘,鼠标等),后者表示输入流中某个具体的显示屏,因为很少有人使用多屏幕,所以 screen_number 多数情况下均为0,也就可以省略掉了。
而对于 display_number,X11 protocol 官方文档中有如下描述:

For TCP connections, displays on a given host are numbered starting
from 0, and the server for display N listens and accepts connections
on port 6000 + N.

也就是说,这个值实际上取决于宿主机上 X11 服务占用的端口,用端口号减掉6000即可,这就是上述命令中冒号后面的0的具体含义。为了验证这一点,可以使用 socat 工具运行 socat tcp-listen:6100,reuseaddr,fork tcp:localhost:6000 命令,将6100端口的消息转交给6000端口,这样按照上面的描述,DISPLAY 变量的值就可以为 host.docker.internal:100 ,替换后执行完整命令,可以发现一样能运行GUI测试程序。

:如果最终仍然无法显示,可以在docker内部执行,设置环境变量指定显示端口:
如果启动命令为:

docker run -it -d -p 6100:6100 -e DISPLAY=host.docker.internal:0 -e "QT_X11_NO_MITSHM=1" \
        -v "/tmp/.X11-unix:/tmp/.X11-unix:rw" \
        -v "$FOLDER:/data" kalibr /bin/sh
export DISPLAY=host.docker.internal:0  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值