Docker容器应用可视化-X11方式

一、概述

  Docker容器可以提供一个轻量级且独立的运行环境,通常被用于运行后台服务单元,但仍然会存在需要UI界面显示的场景,以下提供了采用X11方式实现的Docker容器中的应用图形界面可视化方案。
  X11是一个用于图形窗口环境的标准协议,用于在不同的操作系统上实现图形用户界面。它是在1970年代末和1980年代初由麻省理工学院(MIT)开发的。X11提供了一种机制,使应用程序能够通过网络在不同的计算机上显示图形界面。它提供了许多功能,包括窗口管理、图形绘制、输入处理、事件处理等。X11由服务器和客户端组成。服务器负责运行应用程序并管理窗口、绘制图形等功能,而客户端则是在不同的计算机上运行的程序,它们可以通过网络连接到服务器并发送绘图和事件请求。当X11服务端跟客户端在同一终端中时,可以通过本地unix套接字的方式将显示数据从客户端传递给X11服务端;当X11服务端跟客户端在不同终端上时,则是使用tcp套接字的方式进行数据传输。

二、本地访问容器应用界面

  如果想在宿主机上去访问容器中的应用界面,可以通过容器与宿主机共享X11的unix套接字来实现,让容器中的应用将显示数据通过宿主机的unix套接字发送给X11服务端处理并绘制到屏幕上。具体操作步骤如下:

1、宿主机开放X server权限

xhost +

2、创建容器

使用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

3、启动容器中的应用界面

使用docker exec命令进入容器:

docker exec -it test-demo /bin/bash

使用gedit文本编辑器举例,为容器安装gedit程序并启动:

apt update
apt install gedit
gedit

成功在宿主机屏幕上显示gedit程序界面:

在这里插入图片描述

三、远程访问容器应用界面

  如果想在不同终端上访问远程终端容器中的应用界面,可以通过ssh直连容器的方式来实现。具体操作步骤如下:

1、创建容器

使用ubuntu镜像创建容器,使用 --net=host 参数设置容器网络模式为host模式,让容器与主机共享网络,确保同一网络下的其他终端能够通过ssh访问到容器:

docker run -itd --net=host --name test-demo ubuntu

2、容器环境安装

进入容器中:

docker exec -it test-demo /bin/bash

安装ssh:

apt update
apt install ssh

安装gedit:

apt install gedit

3、修改ssh配置文件

进入到/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 

4、ssh访问容器应用

假设容器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转发的效果,还能够灵活变更,具体步骤如下:

(1)启动X Server监听tcp

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 选项。

在这里插入图片描述

(2)开放X server权限
xhost +
(3)ssh访问容器

假设容器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环境变量,就可以很容易指定当前容器使用的屏幕是哪个。

四、常见问题

1、运行容器中的应用程序,提示 "No protocol specified"错误。

"No protocol specified"是一个X11转发错误。它表示在远程主机上找不到有效的显示协议。 通常这个错误都是因为没有解除对本地X服务器上连接客户端的访问限制导致,在本地输入 xhost + 命令来解决访问权限不足问题。

2、运行容器中的QT程序时,提示类似以下错误:

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

附录

  1. Docker运行GUI软件的方法
  2. Docker实践
  3. Docker运行带UI界面的应用,并将它的界面投射到你的Windows电脑
### 创建带GUI的Shell脚本 为了在Docker容器内部创建并运行带有图形用户界面(GUI)的应用程序,可以通过特定配置使GUI应用显示到主机系统的显示器上。这涉及到几个方面的工作: #### 配置X11转发 对于Linux系统来说,最常用的方法是利用X Window System (X11),它允许应用程序在一个机器上运行而在另一个机器上展示窗口。为此,在启动容器时需设置环境变量`DISPLAY`指向宿主机,并挂载必要的Unix socket文件以便通信。 ```bash docker run -it --rm \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ my_gui_app_image ``` 此命令片段设置了DISPLAY环境变量并将/tmp/.X11-unix目录映射到了容器内[^3]。 #### 编写Shell脚本来启动GUI应用 下面是一个简单的例子,展示了如何编写一个用于启动GNOME Calculator(计算器)作为示例GUI应用的shell脚本: ```bash #!/bin/bash # Ensure the script exits on any error inside it. set -e echo "Starting GUI application..." if [[ "$DISPLAY" == "" ]]; then echo "Error: No display specified." exit 1 fi gnome-calculator & wait $! ``` 保存上述代码至名为`start-gui-app.sh`的文件中,并确保给予可执行权限: ```bash chmod +x start-gui-app.sh ``` 然后可以在构建Dockerfile时COPY这个脚本进去,并将其设为ENTRYPOINT或CMD指令的一部分来自动执行。 #### 构建支持GUI的Docker镜像 为了让容器内的GUI应用正常工作,还需要基于包含所需桌面库的基础镜像来创建自定义镜像。例如,可以从Ubuntu官方仓库获取预安装了基本Xorg依赖项的版本。 ```dockerfile FROM ubuntu:latest RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ gnome-calculator \ xvfb \ fluxbox \ xterm \ wget \ curl \ git \ vim \ sudo \ software-properties-common \ build-essential \ python3-pip \ libgl1-mesa-dev \ mesa-utils \ ffmpeg \ vnc4server \ tigervnc-standalone-server \ xfce4 \ xfce4-goodies \ tightvncserver \ openssh-server \ firefox-esr \ && rm -rf /var/lib/apt/lists/* WORKDIR /root/ COPY ./start-gui-app.sh . ENV DISPLAY=:0.0 CMD ["./start-gui-app.sh"] ``` 这段Dockerfile不仅包含了之前提到的shell脚本,还增加了许多其他软件包以增强用户体验和支持更多类型的GUI应用。注意这里也指定了默认使用的屏幕号(`DISPLAY=:0.0`)。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值