一、概述
Docker容器可以提供一个轻量级且独立的运行环境,通常被用于运行后台服务单元,但仍然会存在需要UI界面显示的场景,以下提供了一种采用VNC方式实现的Docker容器中的应用图形界面可视化方案。VNC(Virtual Network Computing)是一种远程桌面协议,它允许用户通过网络远程访问和控制远程计算机的图形界面。VNC具有跨平台兼容性,可以在不同操作系统(如Windows、macOS和Linux)之间进行远程访问和控制。
二、具体实施流程
1、创建Docker容器
容器镜像使用的是ubuntu镜像,使用以下命令拉取ubuntu镜像:
docker pull ubuntu
创建容器,容器名为vncdemo,镜像名为ubuntu,使用 -p 参数指定端口映射,将宿主机的6080端口映射到容器的80端口上,将宿主机的5900端口映射到容器的5900端口上。
docker run -itd -p 6080:80 -p 5900:5900 --name vncdemo ubuntu
使用docker exec命令进入容器内部:
docker exec -it vncdemo /bin/bash
2、在容器安装Xvfb
Xvfb(X virtual framebuffer)是一个在内存中模拟X窗口系统的虚拟服务器。它主要被用于在没有图形硬件或无需显示器的服务器上运行图形应用程序或测试工具。Xvfb提供了一个虚拟的X服务器环境,它将图形界面的输出渲染到一块特殊的内存区域,而不是显示在物理显示设备上。这使得图形应用程序能够正常运行,而无需实际的显示设备。
在本实施方案中,使用Xvfb主要是为了让图形应用程序能够在没有实际显示设备的情况下也能够正常运行。通过使用以下命令,在容器中安装Xvfb:
apt update
apt install -y xvfb
3、在容器启动虚拟屏幕
使用Xvfb命令启动虚拟屏幕:
Xvfb :0 -screen 0 1280x960x24 -listen tcp -ac +extension GLX +extension RENDER &
其中,:0 指定了显示器号;使用 -screen 参数将屏幕分辨率设置为1280x960,颜色深度设置为24位;使用 -listen tcp 参数用来指定Xvfb监听tcp连接请求,能够接收来自其他设备的连接请求;使用 -ac 参数允许任何设备都可以连接到Xvfb服务器上;使用 +extension 参数加载GLX和RENDER这两个扩展模块,使Xvfb服务器支持更丰富的图形渲染和OpenGL功能。使用 & 表示在后台运行该命令。
然后将DISPLAY环境变量设置为 :0 ,设置完成后可以使用 echo $DISPLAY 命令来查看当前DISPLAY环境变量。
export DISPLAY=:0
4、在容器安装x11vnc
x11vnc是一个允许远程访问Linux系统的开源软件。它可以将X服务器上的图形界面转发到远程客户端,使得用户可以通过VNC协议远程控制Linux系统,实现远程桌面操作。
在本实施方案中,使用x11vnc主要是为了让用户可以通过VNC协议远程访问到容器中的Xvfb虚拟屏幕。使用以下命令进行安装:
apt install -y x11vnc
5、在容器启动X11vnc
使用x11vnc命令启动X11vnc服务:
x11vnc -display :0 -forever -shared -rfbport 5900 -passwd 123456 &
其中,使用 -display 参数指定要共享的X服务器显示器名称,默认为 :0 ;使用 -forever 参数表示在断开连接后仍然保持x11vnc运行;使用 -shared 参数表示允许多个客户端同时连接;使用 -rfbport 参数来指定VNC服务端口,默认为5900;使用 -passwd 参数指定访问密码为123456。
6、在容器安装novnc
noVNC是一个开源Web浏览器VNC客户端,采用 HTML 5 WebSockets, Canvas 和 JavaScript 实现,通过网页提供对远程计算机桌面的访问。用户只需在浏览器中输入noVNC的URL,并提供远程计算机的IP地址和端口号,即可连接到远程计算机并开始远程控制。noVNC还具有跨平台的特性,可以在各种操作系统和设备上运行,包括Windows、Linux、macOS、Android等。noVNC采用WebSockets实现,但是目前大多数VNC服务器都不支持 WebSockets,所以noVNC是不能直接连接 VNC 服务器的,需要一个代理来做WebSockets和TCP sockets 之间的转换。这个代理在noVNC的目录里,叫做websockify 。
在本实施方案中,使用novnc主要是为了让用户在通过VNC方式访问容器中的图形应用程序时,不需要安装VNC Viewer,只需要使用浏览器,输入相应的URL就可以进行远程访问。使用以下命令进行安装:
apt install -y novnc
7、在容器启动novnc服务
使用websockify命令,绑定80端口,将从localhost的5900端口(即x11vnc服务端口)接收到的VNC流量转发到novnc的Web界面,其中使用 --web 参数指定novnc的Web根目录。
websockify --web /usr/share/novnc 80 localhost:5900 &
8、在容器启动图形应用程序
在容器中启动一个带图形界面的应用程序,以下使用gedit为例,若容器中未安装gedit,则先使用以下命令进行安装:
apt install gedit
启动gedit:
gedit
若打开失败,且提示"cannot open display",请检查DISPLAY环境变量是否未设置,或设置错误,可以使用 echo $DISPLAY 查看变量值,使用 export DISPLAY=:0 重新设置环境变量,或者使用以下命令,在启动gedit时指定display:
DISPLAY=:0 gedit
9、通过浏览器访问
此时在宿主机上就可以通过浏览器远程访问到容器中的gedit程序,访问URL格式为 http://IP:端口号/vnc.html 。假设当前宿主机IP为192.168.12.72,容器网络模式为桥接模式,IP为172.17.0.2,则访问URL可以为:
//使用容器IP为172.17.0.2,端口号为容器80端口
http://172.17.0.2:80/vnc.html
//使用宿主机IP为192.168.12.72,端口号为本地6080端口
http://192.168.12.72:6080/vnc.html
//此时宿主机IP也可以使用127.0.0.1或localhost,端口号为本地6080端口
http://127.0.0.1:6080/vnc.html
http://localhost:6080/vnc.html
注1:在容器中使用websockify命令绑定的是容器中的80端口,由于启动容器时使用 -p 参数将宿主机的6080端口映射到了容器80端口上,因此在宿主机上使用浏览器进行访问时,若使用容器IP,则端口号使用的是容器的80端口,若使用宿主机IP,则端口号需要使用宿主机本地的6080端口。
注2:若想要在其他机器上使用浏览器远程访问到容器,则访问URL就只能使用 http://192.168.12.72:6080/vnc.html ,且需要确保它们在同一局域网中,能够互相ping通。
在浏览器输入访问URL后,就进入到了novnc访问界面:
点击连线按钮,提示输入密码:
此时输入在启动x11vnc时设置的密码123456,就能够访问到容器中的虚拟屏幕,可以看到gedit程序界面进行操作:
10、通过vncviewer访问
除了使用浏览器进行远程访问外,我们也可以直接使用VNC Viewer软件连接到容器中的x11vnc服务,对容器中的图形应用程序进行访问。有很多第三方VNC Viewer可供选择,以下使用 xtightvncviewer 举例进行说明,使用以下命令进行安装:
sudo apt install xtightvncviewer
使用 xtightvncviewer IP:PORT 命令连接容器vnc服务,其中 PORT 为5900,IP 为宿主机IP,若是使用 xtightvncviewer 在宿主机上访问容器,则IP可以使用容器IP或127.0.0.1;否则在其他机器上只能通过宿主机IP访问。
xtightvncviewer 192.168.12.72:5900
然后输入设置的vnc密码即可登录:
三、VNC Docker镜像
dorowu/ubuntu-desktop-lxde-vnc镜像是一个基于Ubuntu操作系统的Docker镜像,它预先安装了LXDE桌面环境和VNC服务器。通过使用这个镜像,可以快速创建一个包含LXDE桌面环境和VNC服务器的容器,使用浏览器远程访问容器中的lxde桌面界面。具体使用步骤如下:
1、拉取镜像
docker pull dorowu/ubuntu-desktop-lxde-vnc:latest
2、创建容器
docker run -d -p 6080:80 --name lxde-vnc dorowu/ubuntu-desktop-lxde-vnc
3、使用浏览器访问
此时若在宿主机上使用浏览器访问容器,则可以使用以下URL进行访问:
http://127.0.0.1:6080
由于未设置密码,输入URL后就进入到以下界面,能够远程操作容器中的lxde桌面。