虽然Docker库里也有VncServer镜像,但是,一方面配置不是自己需要的,另一方面网上的Docker镜像安全性堪忧,很多镜像里面都有挖矿等恶意程序。因此,必须自己学会从零开始构建Docker镜像。
一、初始化容器
从最简的官方镜像ubuntu 22.04 开始构建
sudo docker run --name vncserver -p 5900:5901 -di ubuntu:22.04
–name vncserver 是将这个容器命名为 vncserver;-p 5900:5901 是把容器里的5901端口(后续会看到容器里的VncServer将监听5901端口)映射到宿主机的5900端口,因为5900端口是VNC的缺省端口,这样外部VNC客户端连接这个服务时就不用额外指定端口了;-d 是指容器进入后台运行;-i 是指保留交互状态,否则这个容器由于没有配置要运行的后台程序,一启动就会退出了,这个选项合并到-d就变成-di 了,当然也可以分开;ubuntu:22.04 指使用ubuntu 22.04 版本的镜像。
执行结果如下图:

输入sudo docker ps -a,可以查看当前容器状态

然后,登录到这个容器
sudo docker exec -it 88dc /bin/bash
-it 是指开一个虚拟终端并进入交互状态;88dc就是刚才容器的id,从前图可见这个id很长,但我们引用时可以随意位数,只要可以与本地其他容器区分开即可;/bin/bash 指进入后执行这个shell
二、增加用户
这个容器里目前只有root用户,但是root用户下执行许多程序会有莫名其妙的坑,与下面所要展示的步骤结果会有很多不同,然后你一通谷哥和度娘,也不明所以。还是先增加一个非root用户用于运行服务程序吧。
#先更新系统
apt update
#因为初始化的Ubuntu环境是一个极简系统,sudo也需要安装
apt install sudo
#修改root密码,主要是为了设定自己的密码,便于从其他用户转回root
#change root password
passwd
#增加用户run
adduser run
#将新建用户加入sudo组
usermod -aG sudo run
#后面将用新用户来执行指令
su run
三、安装配置GUI环境
Linux有多种GUI界面可选,Ubuntu常用的是gnome。为减少内存需求,还是安装一个轻量的xfce4
#安装xorg
sudo apt-get install xorg openbox
#安装xfce4
sudo apt install xfce4 xfce4-goodies
#安装GUI需要的字体
sudo apt install xfonts-100dpi
sudo apt install xfonts-75dpi
#安装终端
sudo apt-get install xfce4-terminal
#选择设定终端为xfce4-terminal
sudo update-alternatives --config x-terminal-emulator
#安装中文环境
sudo apt install locales
#设置语言环境,建议选择
#160. en_US.UTF-8 UTF-8, 491. zh_CN.GBK GBK,492. zh_CN.UTF-8 UTF-8
#缺省为zh_CN.UTF-8
sudo dpkg-reconfigure locales
#安装基本的中文字体
sudo apt install fonts-wqy-zenhei
#选为中文环境
echo "export LANG=zh_CN.UTF-8" >> ~/.bashrc
四、安装tightvncserver
Linux有多种VncServer ,选择较为常用的tightvncserver
#安装tightvncserver
sudo apt install tightvncserver
#设置VNC 口令
vncserver
vncserver -kill :1
#将 startxfce4加入vnc的配置文件xstart
echo "startxfce4 &" >> ~/.vnc/xstartup
上面指令中vncserver执行后,因是第一次执行,则会让你输入用于VNC客户端的登录密码,然后问你是否需要一个只能浏览的密码,这就不需要了,执行后效果如下图

上面的图示中,显示一个VncServer实例已经运行起来了,:1表示第一个,在监听5901端口。由于当前我们只是配置参数,并不要实际执行,因此紧接着就通过vncserver -kill :1 终止该实例了。为了让VncServer选择xfce4作为GUI界面,在VncServer的启动配置文件 ~/.vnc/xstartup 里,需要加入启动xfce4的指令startxfce4。
然后编写一个vncserver启停的脚本
#!/bin/sh
# /etc/init.d/vncserver
VNCUSER='run'
case "$1" in
start)
rm -r -f /tmp/.X11-unix
rm -r -f /tmp/.X1-lock
su $VNCUSER -c 'vncserver :1 -geometry 1600x900'
echo "Starting VNC Server for $VNCUSER"
;;
stop)
su $VNCUSER -c 'vncserver -kill :1'
echo "TightVNC Server stopped"
;;
*)
echo "Usage: /etc/init.d/vncserver {start|stop}"
exit 1
;;
esac
exit 0
这个脚本文件关键点有两处。一是,明确执行vncserver的用户,必须是非root用户,否则将无法正常运行。二是,上一次非正常退出vncserver服务会留下 /tmp/.X11-unix、 /tmp/.X1-lock两个文件,导致这次vncserver无法启动,因此启动前必须将这两个文件删除。
编辑完成后,把它存到 /etc/init.d/vncserver,然后更改文件属性使其可执行。
sudo chmod 755 /etc/init.d/vncserver
其实,这个脚本放哪里无所谓。我习惯于放到 /etc/init.d/下,目的想在系统启动时自动执行。但是,对于Docker容器而言,Linux下传统的自启动执行方式都无效了。
至此,vncserver就安装完成了,我们可以手动输入指令启动vncserver
sudo /etc/init.d/vncserver start
终端结果输出如下

然后,可以在宿主机上用Remmina 连接 127.0.0.1,欣赏劳动成果了。

五、配置容器,导出
作为容器,还得能自动启动vncserver。可以在根目录下建立一个start.sh脚本(要记得修改其文件属性为可执行),以便运行容器时,做为启动命令。
#!/bin/sh
/etc/init.d/vncserver start #启动服务
/bin/bash #保留一个终端,防止容器自动退出
现在,vncserver这个容器已经基本配置完成了。你可以在此基础上增加一些自己需要的程序或配置,如安装一个浏览器firefox等。建议使用firefox,安装配置相对简单。
我们需要将这个容器存下来,变成一个镜像,供其他地方的Docker使用。
sudo docker commit -m="VNCServer on Ubuntu 22.04" -a="itisme" 88dc vncserver:v1
-m 参数是这个镜像的解释文本;-a 是生成者名称,即你的名字;88dc是容器id;vncserver:v1是镜像名称以及版本。
使用 sudo docker images 可以看到我们刚生成的镜像vncserver

将这个镜像导出
sudo docker save -o vncserver.tar vncserver
在当前目录下,生成了一个文件vncserver.tar。将这个文件拷贝到需要的地方,然后导入
sudo docker import vncserver.tar vncserver:v1
执行时加上 start.sh
sudo docker run --name newi -it -d -p 5900:5901 -v 宿主机目录1:/home/run/Document -v 宿主机目录2:/home/run/Downloads vncserver:v1 /start.sh
不清楚为什么使用容器ubuntu22.04启动前不加–privileged=true,连接显示黑屏,加了正常
不加 –privileged=true 时黑屏的原因很可能是容器缺乏访问图形硬件、显示环境或内核能力的权限。
加上此参数后,容器获得了完全权限,问题得以解决。
为避免过度授权,推荐的做法是:
1、检查容器内图形程序的日志,确定具体缺少哪些资源。
2、根据需求配置设备挂载和环境变量,例如:
docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix ubuntu:22.04