如何拥有一个云端的 linux 桌面系统

基于 Docker 和 VNC 搭建远程 linux 桌面系统

Posted by mingfer on June 17, 2019

当拥有一个云端服务器又没啥服务可以部署的时候,或许还可以将它作为一个远程的桌面系统使用。

前言

本文主要介绍如何构建一个在 Docker 中运行的桌面化的 CentOS7 实例,至于 Docker 位于云端还是位于本地主机上,可以根据需要自行决定。

这里我们分三个步骤完成远程桌面化 Linux 系统的搭建:

  • 运行 CentOS 容器并安装 GNOME 桌面
  • 搭建 VNC 服务器和配置 noVNC 代理
  • 完成环境配置,提交容器为镜像方便以后使用

正文

运行一个 CentOS 容器

首先我们需要通过 docker 拉取一个最新的 CentOS 镜像:

1
$ docker pull centos

启动一个 CentOS 实例:

1
$ docker run --name centos-gnome --privileged -p 5901:5901 -p 6080:6080 --ulimit memlock=-1 -td centos /usr/sbin/init

其中:

  • —name centos-gnome 用于指定容器名称。
  • --privileged 使容器具有真正的 root 权限。
  • -p 5901:5901 映射 VNC 服务器的端口到宿主机,如果在容器内部搭建了 VNC 代理可以不映射该端口。否则 VNC 客户端或 VNC 代理通过该端口访问容器桌面。
  • -p 6080:6080 映射 noVNC 代理的端口到宿主机,如果不在容器内部搭建 VNC 代理,该步骤可以忽略。
  • --ulimit memlock=-1 不限制 Docker 的最大内存锁定空间

安装 GNOME 桌面

通过容器名称进入容器中:

1
$ docker exec -it centos-gnome bash

查看可用的桌面系统:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ yum grouplist
Available Environment Groups:
   Minimal Install
   Compute Node
   Infrastructure Server
   File and Print Server
   Basic Web Server
   Virtualization Host
   Server with GUI
   GNOME Desktop
   KDE Plasma Workspaces
   Development and Creative Workstation
Available Groups:
   Compatibility Libraries
   Console Internet Tools
   Development Tools
   Graphical Administration Tools
   Legacy UNIX Compatibility
   Scientific Support
   Security Tools
   Smart Card Support
   System Administration Tools
   System Management
Done

这里我们选择安装 GNOME,当然有时候 GNOME 可能不是最好(比较重且耗费内存)的或者满足你需求的选择,此时可以根据需要安装其他桌面系统。

1
$ yum groupinstall -y "GNOME Desktop"

设置默认图形界面启动:

1
$ systemctl set-default graphical.target

安装 VNC 服务器

安装 VNC 服务器和网络工具:

1
$ yum install -y net-tools tigervnc-server tigervnc-server-module

拷贝一份配置模板文件:

1
$ cp /lib/systemd/system/[email protected] /lib/systemd/system/vncserver@:1.service

修改配置模板

1
$ vi /lib/systemd/system/vncserver@:1.service

将文件中的 Type=forking 改成 Type=simple;将 <USER> 改成 root

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target

[Service]
Type=forking

# Clean any existing files in /tmp/.X11-unix environment
ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
ExecStart=/usr/sbin/runuser -l <USER> -c "/usr/bin/vncserver %i"
PIDFile=/home/<USER>/.vnc/%H%i.pid
ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'

[Install]
WantedBy=multi-user.target

更改后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target

[Service]
Type=simple

# Clean any existing files in /tmp/.X11-unix environment
ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
ExecStart=/usr/sbin/runuser -l root -c "/usr/bin/vncserver %i"
PIDFile=/home/root/.vnc/%H%i.pid
ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'

[Install]
WantedBy=multi-user.target

配置访问密码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ vncserver

You will require a password to access your desktops.

Password:
Verify:
Would you like to enter a view-only password (y/n)? n
A view-only password is not used
xauth:  file /root/.Xauthority does not exist

New '81862eed5fab:1 ()' desktop is 81862eed5fab:1

Creating default startup script /root/.vnc/xstartup
Creating default config /root/.vnc/config
Starting applications specified in /root/.vnc/xstartup
Log file is /root/.vnc/81862eed5fab:1.log

退出容器,重启容器后重新进入:

1
2
3
$ exit
$ docker restart centos-gnome
$ docker exec --privileged -it centos-gnome bash

重新加载 systemctl,将 vncserver 设置为开机自启:

1
2
$ systemctl daemon-reload
$ systemctl start vncserver@:1.service && systemctl enable vncserver@:1.service

查看是否启动成功:

1
2
3
4
5
$ vncserver -list
TigerVNC server sessions:

X DISPLAY #	PROCESS ID
:1		2261

安装 noVNC 代理

建议在 Docker 的宿主机上安装 noVNC 代理而非在 Docker 容器内部安装。

首先去 GitHub 拉取 noVNC 的源代码:

1
2
3
$ cd
$ yum install -y git
$ git clone git://github.com/kanaka/noVNC

进入 noVNC 目录,启动 VNC 代理,第一次启动的时候会下载 websockify。其中 localhost:5901 是容器中 VNC 服务所在的地址。

1
$ ./utils/launch.sh --vnc localhost:5901

修改防火墙配置

开放 6080 端口,如果容器内没有代理用同样的方法开启 5901 端口:

1
2
$ firewall-cmd --zone=public --add-port=6080/tcp
$ firewall-cmd --reload

或者可以停止并禁用防火墙(不推荐):

1
2
3
4
#停止 firewalld 服务
$ systemctl stop firewalld
#禁用 firewalld 服务
$ systemctl mask firewalld

效果

访问:http://localhost:5901/vnc.html

image-20190617214637649

后记

当然这只是简单的将一个桌面系统装好了,后面还有更多需要探索的地方。比如:

  • 将容器打包成一个镜像:docker commit -m "centos desktop with gnome" -a mingfer 81862eed5fab centos-gnome

  • 将时区设置为上海 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  • 配置第三方源 yum -y install epel-release
  • 配置中文显示
  • etc.