189 8069 5689

LXC容器如何以本地方式运行XServer

LXC容器如何以本地方式运行X Server,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

“专业、务实、高效、创新、把客户的事当成自己的事”是我们每一个人一直以来坚持追求的企业文化。 成都创新互联是您可以信赖的网站建设服务商、专业的互联网服务提供商! 专注于网站制作、网站建设、软件开发、设计服务业务。我们始终坚持以客户需求为导向,结合用户体验与视觉传达,提供有针对性的项目解决方案,提供专业性的建议,创新互联建站将不断地超越自我,追逐市场,引领市场!

容器要运行X桌面环境可通过ssh,xdmcp远程方式,此时容器是X Client,容器是无需安装X Server.
容器中以本地方式运行X Server,介绍的内容是容器运行X在宿主的桌面窗口之上,容器以本地方式登录桌面环境,即界面上类似VirtualBox的方式.

实验环境  : debian 11

主机名                shell提示符
-----------------------------------------------
宿主 :  debian       root@debian:/#
容器 :  vm1          root@vm1:/#

一.简单步骤
1.宿主
1)安装Xephyr
root@debian:/# apt-get install xserver-xephyr

2)安装容器工具LXC
root@debian:/# apt-get install lxc

3)创建容器
root@debian:/# lxc-create -t debian -n vm1

创建了以debian为模版的容器,其根目录是/var/lib/lxc/vm1/rootfs/

这一制作容器的根的过程耗费较长时间,如果已有了容器,此步骤可省略.

4)进入容器
启动容器
root@debian:/# lxc-start -n vm1 -F

或者仅仅为了容器安装软件包,用chroot容器的根即可
root@debian:/# chroot /var/lib/lxc/vm1/rootfs/

2.容器
进入容器后

1)容器也需安装Xephyr
root@vm1:/# apt-get install xserver-xephyr

2)安装窗口管理器
root@vm1:/# apt-get install jwm

3)安装登录管理器
root@vm1:/# apt-get install xdm

4)配置xdm
将容器/etc/X11/xdm/Xservers中即在宿主/var/lib/lxc/vm1/rootfs/etc/X11/xdm/Xservers中
:0 local /usr/bin/X :0 vt7 -nolisten tcp
一行修改为
:30 local /usr/bin/Xephyr :30

修改后的行首尾:30是显示号.你可选择其它数字,但首尾显示号设置要一致,并尽量避开宿主常用显示号,特别避开0和1显示号.

5)退出容器
如是lxc-start容器的,则
root@vm1:/# poweroff

如是chroot容器的根,则
root@vm1:/# exit

3.再配置容器
回到宿主,编辑/var/lib/lxc/vm1/config文件,加上容器启动自动只读mount宿主的X Server套接字所在目录,添加下面一行
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,ro,optional,create=dir

上面配置一行相当于在宿主手动运行命令 mount -o ro --bind /tmp/.X11-unix /var/lib/lxc/vm1/rootfs/tmp/.X11-unix

说明:
1)如果步骤1是chroot根,本步骤可在步骤2之前进行,因为chroot根仅仅切换根环境,chroot根的系统不会进行系统启动操作.

2)如果步骤1是lxc-start进入容器,因为容器是一个虚拟操作系统,容器系统启动时其操作系统会进行一系列开机初始化操作,容器poweroff正常关闭时也会进行清理操作.
经测试,有的发行版会在启动时删除/tmp下的临时文件,有的发行版会在关闭时删除/tmp下的临时文件,有的发行版根本不删除/tmp下的临时文件.
因此,如果不是只读而是可读写mount宿主的/tmp/.X11-unix目录给容器,可能会造成删除了宿主的/tmp/.X11-unix,后续的实验就无法进行,除非重启宿主主机.

总之,本步骤最好等到步骤2.容器安装软件包配置完毕后才进行,并且只读mount(为什么只读也没多大问题?见后面分析).

4.运行
在宿主以普通用户linlin登录桌面环境,打开模拟终端,运行以下命令.

1)宿主
1.1)普通用户运行下面命令
linlin@debian:~$ ls /tmp/.X11-unix/
X0
X0表示存在显示号0

运行Xephyr并新建显示号1
linlin@debian:~$ Xephyr :1
可见弹出一个图形界面,相当于一个屏幕,所以Xephyr也是一个X Client.为方便说明记作[Xephyr :1]

linlin@debian:~$ ls /tmp/.X11-unix/
X0  X1
已可见到两个显示号0和1

切换到root用户
linlin@debian:~$ su

1.2)root用户启动容器
root@debian:/# lxc-start -n vm1 -F

2)容器
进入容器后,在模拟终端即为容器的控制台下,以root用户登录
GNU/Linux vm1 console
vm1 login: root
密码:

2.1)
root@vm1:/# ls /tmp/.X11-unix/
X0  X1
同样在容器也可见到两个显示号0和1,但这两个是宿主创建的

查看显示号环境变量

root@vm1:/# export | grep DISPLAY
root@vm1:/#

为空

启动登录管理器
root@vm1:/# DISPLAY=:1 xdm

2.2)
已成功在宿主的[Xephyr :1]生成容器的[Xephyr :30.0]并弹出xdm登录对话框图形界面,可以登录进入桌面系统.在容器里是可见到有X0、X1、X30等显示号.
在xdm登录对话框以root用户登录容器桌面,打开容器桌面的模拟终端,查看环境变量
root@vm1:/# export | grep DISPLAY
declare -x DISPLAY=":30.0"
root@vm1:/#
已是显示号30

至此,容器已经成功以本地方式运行X Server、以本地方式登录桌面环境.
但本文仍需手工输入Xephyr、xdm命令,还没能解决能一启动容器就自动弹出xdm登录对话框.

二.安全问题

因宿主共享/tmp/.X11-unix给容器,所以存在安全隐患,因此上面的容器运行X不要应用在生产环境中.

三.详尽解析
1.X Window
X Window 是一Client/Server模式,客户和服务器既可本地也可远程,X 客户和服务器的本地进程间通信是通过unix域进行.X Server启动时会在/tmp/.X11-unix目录下创建X0、X1、X2 ...之类的unix域套接字文件.

2.Xephyr
Xephyr也是一个X Server,但是它运行在一个存在的X Server里面.Xephyr既是一个普通的GUI程序又是一个X Server,常用于xdmcp远程桌面连接.

例如:远程主机192.168.1.2安装有支持xdmcp的会话登录管理器(如xdm,需配置启用xdmcp)
当前本地机器在控制台tty7运行着X Window桌面环境,要远程桌面连接远程主机,有两种方式:

方式1:传统的方式
键,登录进入控制台tty1命令行,执行X -query 192.168.1.2 :1
上面命令没指定控制台,会自动选择控制台tty8来运行着第二个X,显示号为1  
键,便切换到控制台tty8,并弹出有远程支持xdmcp的登录窗口,就可远程登录了
早期的X Server需在root根用户下执行,现代X Server已可在非根用户下运行

方式2:Xephyr
在控制台tty7的X Window桌面环境里,打开模拟终端,执行Xephyr -query 192.168.1.2 :1
便在当前桌面环境里打开了图形界面窗口Xephyr,嵌套运行着远程主机桌面环境

本文的实验目的是在容器中以本地方式运行X,而常规的容器配置对设备的访问是受限的,在容器里运行标准的X Server会失败.而Xephyr作为X Client,只要容器里普通的X Client能运行成功,那容器里Xephyr便能运行成功.下面实验试图探出一条容器本地运行X之路.

3.命名空间
LXC容器是操作系统级的虚拟化,用于隔离了系统中的各种资源是命名空间,主要有:pid、uts、mount、net、IPC.

unix域是当作为进程间通信IPC,但却是网络编程接口socket下协议族的其中一种.而IPC命名空间好像只有System V IPC和POSIX message queues命名空间化.所以本人无法断定unix域是IPC命名空间化了还是网络命名空间化了.

下面分别单独对mount命名空间、网络命名空间、IPC命名空间进行实验,每个实验只涉及单个命名空间,不涉及叠加其它命名空间.
1)mount命名空间
有两种方式可达到mount命名空间化,也即切换根.
方式1:pivot_root
这是LXC容器是使用的方式

方式2:chroot
这是很传统的方式,下面实验用此方式

实验目的:chroot根下(即容器根/var/lib/lxc/vm1/rootfs/)运行图形界面,用X Client程序xlogo测试.

用普通用户linlin登录桌面环境,打开模拟终端su切换到根用户.

首先在宿主chroot根
root@debian:/# chroot /var/lib/lxc/vm1/rootfs/

在chroot根下,查看环境变量DISPLAY,当前Xorg的显示号0
root@vm1:/# export | grep DISPLAY
declare -x DISPLAY=":0.0"

然后有两种方式可实现运行图形界面
1.1)方式1:获得Xorg授权  
通常X Client要访问X Server(通常指桌面窗口意义上的Xorg),需获得XAUTHORITY认证授权,即使在本地.

1.1.1)在chroot根下
运行X Client程序,出现无法打开显示号的错误
root@vm1:/# xlogo
Error: Can't open display: :0.0

查看环境变量XAUTHORITY,可见chroot时继承linlin用户的环境变量
root@vm1:/# export | grep XAUTHORITY
declare -x XAUTHORITY="/home/linlin/.Xauthority"

重设环境变量XAUTHORITY
root@vm1:/# export XAUTHORITY="/root/.Xauthority"
root@vm1:/# export | grep XAUTHORITY
declare -x XAUTHORITY="/root/.Xauthority"

1.1.2)回到宿主,复制当前登录用户的认证授权文件到chroot根的root用户目录下
root@debian:/# cp /home/linlin/.Xauthority /var/lib/lxc/vm1/rootfs/root/

1.1.3)回到chroot根,运行X Client程序,已成功在当前登录用户桌面窗口打开图形界面
root@vm1:/# xlogo

1.2)方式2:Xephyr免认证
1.2.1)在chroot根下
为实验目的先删除chroot根认证授权文件
root@vm1:/# rm /root/.Xauthority

运行X Client程序,出现'无法打开显示'错误,说明没有获得Xorg授权
root@vm1:/# xlogo
No protocol specified
xlogo: 无法打开显示:

1.2.2)回到宿主
安装X认证工具xauth
root@debian:/# apt-get install xauth

运行Xephyr,指定显示号1,不能与Xorg的显示号冲突.这时的[Xephyr :1]既是一个普通的X Client程序又充当一个X Server,默认免认证
linlin@debian:~$ Xephyr :1

查看有哪些X Server在运行
linlin@debian:~$ ps -ef |grep X
root       674   634  1 13:19 tty7     00:01:37 /usr/lib/xorg/Xorg :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch
linlin    3216  3211  0 15:33 pts/2    00:00:00 Xephyr :1

查看认证详情,可见只有显示号0需认证,没有显示号1
linlin@debian:~$ xauth list
Using authority file /home/linlin/.Xauthority
debian/unix:0  MIT-MAGIC-COOKIE-1  e27be218c83f36a1cbab935912c70ce2

查看网络服务监听
root@debian:/# netstat -lp |grep X
Active UNIX domain sockets (only servers)
unix  2      [ ACC ]     STREAM     LISTENING     18014    719/Xorg             @/tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING     85267    3537/Xephyr          @/tmp/.X11-unix/X1
unix  2      [ ACC ]     STREAM     LISTENING     18015    719/Xorg             /tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING     85268    3537/Xephyr          /tmp/.X11-unix/X1
root@debian:/home/linlin#

1.2.3)回到chroot根
运行xlogo,已成功在[Xephyr :1]上打开图形界面,不需认证
root@vm1:/# DISPLAY=:1 xlogo
上面xlogo命令前先指定了显示号1,当然也可先单独export显示号1再直接运行xlogo

查看chroot根是否有显示号套接字
root@vm1:/# ls /tmp/.X11-unix -a
root@vm1:/#
发现为空目录,并没有显示号套接字X0、X1、...
DISPLAY=:1的 1是指显示号1,等号和冒号之间空的应该是指使用本地unix域
如果环境变量是DISPLAY=127.0.0.1:1应该是指网络方式的显示号1

至于为什么chroot根环境不用读取显示号套接字文件就能与宿主Xephyr通信?在下面的网络命名空间化实验将体现出来.

1.2.4)回到宿主,关闭Xephyr程序

2)IPC命名空间
lxc-unshare命令可设置进入某个命名空间,参数"IPC"是进入IPC命名空间.lxc-unshare需在根用户下运行,在普通用户下运行会提示'Operation not permitted'错误.

2.1)
下面命令在宿主另开辟一个shell环境,并已IPC命名空间化了
root@debian:/# lxc-unshare -s "IPC" /bin/bash

在IPC命名空间化了的shell下运行程序
2.1.1)
root@debian:/# xlogo
也正常打开图形界面

2.1.2)查看网络服务监听
root@debian:/# netstat -lp |grep X
Active UNIX domain sockets (only servers)
unix  2      [ ACC ]     STREAM     LISTENING     18014    719/Xorg             @/tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING     18015    719/Xorg             /tmp/.X11-unix/X0
root@debian:/home/linlin#

'/tmp/.X11-unix/X0'应是指Xorg在/tmp/.X11-unix/X0套接字文件上监听,这是unix域传统方式.
'@/tmp/.X11-unix/X0'前面多了个@字符,这是linux特有的unix域抽象套接字(注意:API编程时不是用@符号来表示抽象套接字,具体可man 7 unix帮助).

man 7 unix 里说
Abstract sockets automatically disappear when all open references to the socket are closed.(当所有打开套接字的引用都关闭完毕,抽象套接字会自动消失)
The abstract socket namespace is a nonportable Linux extension.(不知这里的namespace是本文所关心的操作系统级虚拟化隔离各资源的命名空间概念还是另有其意?)

传统的unix域套接字关闭时,不会自动删除套接字文件,需手动删除.

2.1.3)退出IPC命名空间化了的shell
root@debian:/# exit

2.2)
将X0套接字文件改名为X0-bak
root@debian:/# mv /tmp/.X11-unix/X0 /tmp/.X11-unix/X0-bak
root@debian:/# ls /tmp/.X11-unix
X0-bak

开辟IPC命名空间化shell环境
root@debian:/# lxc-unshare -s "IPC" /bin/bash

在IPC命名空间化了的shell下运行程序
root@debian:/# xlogo
也正常打开图形界面

说明在IPC命名空间下并且即使没套接字文件,X 客户和服务器还能通信,但我不能确定unix域是否IPC命名空间化了.

退出IPC命名空间化了的shell
root@debian:/# exit

将X0-bak改回为X0
root@debian:/# mv /tmp/.X11-unix/X0-bak /tmp/.X11-unix/X0

3)网络命名空间
安装系统调用跟踪器strace
root@debian:/# apt-get install strace

root@debian:/# ls /tmp/.X11-unix
X0

3.1)
下面命令在宿主另开辟一个shell环境,并已网络命名空间化了
root@debian:/# lxc-unshare -s "NETWORK" /bin/bash

在网络命名空间化了的shell下运行程序
root@debian:/# ifconfig
为空
root@debian:/# ping 192.168.1.2
ping: connect: 网络不可达

root@debian:/# xlogo
也正常打开图形界面

root@debian:/# netstat -lp |grep X
Active UNIX domain sockets (only servers)
为空
root@debian:/# netstat
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags       Type       State         I-Node   Path
为空
root@debian:/#

退出网络命名空间化了的shell
root@debian:/# exit

3.2)
将X0套接字文件改名为X0-bak
root@debian:/# mv /tmp/.X11-unix/X0 /tmp/.X11-unix/X0-bak
root@debian:/# ls /tmp/.X11-unix
X0-bak

root@debian:/# export
...
declare -x DISPLAY=":0.0"
...
declare -x XAUTHORITY="/home/linlin/.Xauthority"
...

3.2.1)不进行命名空间化
root@debian:/# xlogo
在这没网络命名空间化,即使没有套接字文件,也正常打开图形界面

3.2.2)xlogo进程网络命名空间化
root@debian:/# lxc-unshare -s "NETWORK" xlogo
xlogo: 无法打开显示:

3.2.3)
开辟网络命名空间化shell环境
root@debian:/# lxc-unshare -s "NETWORK" /bin/bash

在网络命名空间化了的shell下运行程序
root@debian:/# xlogo
xlogo: 无法打开显示:
在找不到显示号套接字文件及网络命名空间化后,已无法打开显示

第一次跟踪调试
root@debian:/# strace xlogo
...
connect(3, {sa_family=AF_UNIX, sun_path=@"/tmp/.X11-unix/X0"}, 20) = -1 ECONNREFUSED (拒绝连接)
...
connect(3, {sa_family=AF_UNIX, sun_path="/tmp/.X11-unix/X0"}, 110) = -1 ENOENT (没有那个文件或目录)
...
connect(3, {sa_family=AF_INET, sin_port=htons(6000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ENETUNREACH (网络不可达)
...
write(2, "Can't open display: :0.0", 24Can't open display: :0.0) = 24
...
root@debian:/#
跟踪结果依次尝试连接失败  sun_path=@"/tmp/.X11-unix/X0" --> sun_path="/tmp/.X11-unix/X0" --> sin_addr=inet_addr("127.0.0.1")
即  抽象套接字 --> 套接字文件 --> 网络

将X0-bak改回为X0,并再进行第二次跟踪调试
root@debian:/# mv /tmp/.X11-unix/X0-bak /tmp/.X11-unix/X0
root@debian:/# strace xlogo
...
connect(3, {sa_family=AF_UNIX, sun_path=@"/tmp/.X11-unix/X0"}, 20) = -1 ECONNREFUSED (拒绝连接)
...
connect(3, {sa_family=AF_UNIX, sun_path="/tmp/.X11-unix/X0"}, 110) = 0
getpeername(3, {sa_family=AF_UNIX, sun_path="/tmp/.X11-unix/X0"}, [124->20]) = 0
uname({sysname="Linux", nodename="debian", ...}) = 0
access("/home/linlin/.Xauthority", R_OK) = 0
openat(AT_FDCWD, "/home/linlin/.Xauthority", O_RDONLY) = 4
...
也正常打开图形界面,并且"/tmp/.X11-unix/X0"成功了,就不进行尝试"127.0.0.1"

根据两次跟踪调试结果:在网络命名空间下,sun_path=@"/tmp/.X11-unix/X0" 拒绝连接,应该说明unix域Abstract sockets有网络命名空间化.
但传统sun_path="/tmp/.X11-unix/X0"在网络命名空间下只要套接字文件存在就能正常连接,不知是否说明unix域套接字文件没网络命名空间化?

这个实验同时也说明了小节1)mount命名空间实验结果:虽然chroot根环境读不了宿主/tmp/.X11-unix/下套接字文件,但因没网络命名空间化,所以仍能通过抽象套接字和宿主X Server通信.

至此,基本能找出一条容器本地运行X之路.但对于unix域是否命名空间化、属于哪个命名空间问题,本人不才,还是没能完全明白unix域命名空间化的程度.

4.小结
下表列出各命名空间对unix域的(有无)影响

             套接字文件     抽象套接字
--------------------------------------------------------------
mount       有                 无
--------------------------------------------------------------
ipc            无                 无
--------------------------------------------------------------
net            无                有
--------------------------------------------------------------

5.LXC系统容器
容器可分为:
应用容器:对某个或一组进程按需单独或组合进行命名空间化(namespace)、控制组化(cgroup).
系统容器:虚拟为操作系统,需进行彻底的资源隔离,本文的LXC容器特指系统容器.

LXC容器叠加了mount、网络等多个命名空间.容器无法读取宿主显示号套接字,无法通过抽象unix域与宿主X Server通信,唯一方法只能将宿主的/tmp/.X11-unix目录通过mount --bind共享给容器根以便读取到显示号套接字.

1)宿主
运行Xephyr并新建显示号1
linlin@debian:~$ Xephyr :1

查看linlin用户uid
linlin@debian:~$ id
uid=1000(linlin) gid=1000(linlin) 组=1000(linlin)
linlin@debian:~$

只读共享宿主目录
root@debian:/# mount -o ro --bind /tmp/.X11-unix  /var/lib/lxc/vm1/rootfs/tmp/.X11-unix
或者容器系统不会删除/tmp下文件,可读写mount
root@debian:/# mount --bind /tmp/.X11-unix  /var/lib/lxc/vm1/rootfs/tmp/.X11-unix

启动容器
root@debian:/# lxc-start -n vm1 -F

2)容器
进入容器后

2.1)在模拟终端即为容器的控制台下,以root用户登录
GNU/Linux vm1 console
vm1 login: root
密码:

root@vm1:/# DISPLAY=:1 xlogo
也正常打开图形界面

试图在显示号0上运行
root@vm1:/# xlogo
No protocol specified
xlogo: 无法打开显示:
运行失败,原因显示号0是宿主的Xorg显示号,Xorg需认证授权,即使从宿主简单地复制.Xauthority到容器的../root/.Xauthority也不行.
而在小节1)mount命名空间实验里从宿主简单地复制.Xauthority到chroot根的../root/.Xauthority能成功,而容器却不行,这与.Xauthority文件里含主机名信息有关(可xauth list查看),
简单的chroot根不会改变根环境的主机名,而容器是可以另外一个主机名.
然而,是可以往宿主.Xauthority添加授权某主机认证信息,至于如何往宿主和容器两端注入授权信息,本人没实验过,不表.

另:在容器里是可以创建显示号0的套接字文件,在宿主和容器共享的/tmp/.X11-unix之下,这会覆盖掉宿主显示号0套接字文件,至于会出现什么后果,不再实验,不表.
也因此,第一章节第4)小节设置容器的xdm配置文件就不要指定显示号0.

2.2)以普通用户登录
GNU/Linux vm1 console
vm1 login: linlin
密码:

linlin@vm1:~$ id
uid=1000(linlin) gid=1000(linlin) 组=1000(linlin)
linlin@vm1:~$
这里的容器用户uid同宿主linlin用户的uid,都为1000

linlin@vm1:~$ DISPLAY=:1 xlogo
正常同root

linlin@vm1:~$ DISPLAY=:0 xlogo
也正常在显示号0上运行.
说明:宿主上是以用户linlin登录桌面,容器也同样创建了linlin用户,两者的用户uid号相同.本人猜想容器进程对宿主来说等同宿主其它普通进程,容器运行的xlogo进程用户uid就是当前宿主登录桌面用户uid相同,所以无需X认证.

2.3)要完整的运行容器本地X,容器会以不同的用户登录,所以不能仅仅凭相同uid在显示号0上运行

6.解决方案
终合上面实验,要使容器能运行X,可采取如下方案
宿主运行X Server(Xorg),宿主的Xephyr运行在X Server上;容器运行Xephyr,容器的Xephyr运行在宿主的Xephyr上,容器的X Client运行在容器的Xephyr上

即:

容器的X Client->容器的Xephyr->宿主的Xephyr->宿主X Server

7.其它
1)
xdm的很多配置文件开头好多空白行,让人误以为没东西,实际拉到后面是有内容的.
其它的登录管理器好像很死板,无法象xdm灵活.

注意:如果容器的xdm配置是指定显示号0
:0 local /usr/bin/Xephyr :0
则容器会新建的显示号0并覆盖掉共享目录下宿主显示号0,虽然宿主一般应用是没问题,但尽量避免.

2)
在显示号1上即宿主的[Xephyr :1]运行窗口管理器openbox,此步骤也可省略
linlin@debian:~$ DISPLAY=:1 openbox
加运行这个窗口管理器为了容器Xephyr界面可在[Xephyr :1]里移动,方便可多个容器Xephyr界面移动来移动去.
如一个宿主Xephyr只管理一个容器则不需此命令,有两个容器就运行两个宿主Xephyr([Xephyr :1]和[Xephyr :2]).
如有容器vm1和vm2,两个容器的桌面系统都在宿主的[Xephyr :1]上,如果宿主的[Xephyr :1]没窗口管理器,则后一个的vm2桌面系统固定位置覆盖了vm1.

3)容器上外网所需的DNS地址配置
容器安装软件需连上互联网,除非通过http代理服务器上外网可不需设置DNS地址,否则必须在/etc/resolv.conf配置好DNS地址.
通常在lxc-create创建容器过程中,就已复制宿主/etc/resolv.conf的内容到容器/etc/resolv.conf,无需手工配置.也正是因如此,往往容易忽略此细节.
例如lxc-create创建的容器的/etc/resolv.conf通常是普通文件并可能没采取dhcp动态获得DNS地址,宿主的/etc/resolv.conf往往是一指向network-manager的符号链接并动态获得DNS地址.
当家里的路由器IP地址改变时,容器就因DNS地址不正确而无法获得域名解析导致上外网失败.

例如在家里通过路由器(IP 192.168.1.1)上外网,通常的DNS地址配置如下:

root@vm1:/# cat /etc/resolv.conf
nameserver 192.168.1.1
root@vm1:/#

路由器作为DNS域名服务器,路由器里配置有上级外网电信互联网服务商的DNS IP地址或某搜索引擎公司的公共DNS 8.8.8.8,家里的主机就通过此逐级DNS而获得域名解析.

当然家里主机也可直接设置外网DNS IP地址,如:

root@vm1:/# cat /etc/resolv.conf
nameserver 8.8.8.8
root@vm1:/#

4)调整桌面环境显示尺寸
容器桌面环境显示尺寸较小(默认640x480).
如果是安装好完整的桌面环境,可通过桌面环境的工具重设分辨率,会保存,下次启动系统会按新的分辨率.
如果临时调整,可用xrandr命令

容器和宿主都安装X server工具
# apt-get install x11-xserver-utils

在容器里
root@vm1:/# xrandr -s 1024x768
容器的Xephyr虚桌面变大了,但宿主的Xephyr尺寸不变,导致窗口效果尺寸不变,导致容器里一些菜单看不到了.需调整宿主Xephyr的分辨率

回到宿主,调整宿主Xephyr的尺寸与容器一致
linlin@debian:~$ xrandr --display :1 -s 1024x768

或者一开始宿主就指定分辨率
linlin@debian:~$ Xephyr -screen 1024x768 :1

5)在容器外即在宿主直接运行容器里的命令,需在root用户下执行lxc-attach来运行容器命令
root@debian:/# lxc-attach -n vm1 -- env DISPLAY=:1   xdm -nodaemon &
说明:用env 设置容器里环境变量
xdm的参数-nodaemon表示非守护进程运行
加上&后台运行
这样xdm便在容器里运行,并打开xdm登录对话框

6)可写成脚本,自动寻找未用的显示号,一次启动容器桌面
root@debian:/# lxc-info -s -n vm1 | grep RUNNING && for i in seq 99 ; do [ ! -e /tmp/.X11-unix/X$i ] && (Xephyr :$i &) && break ; done && lxc-attach -n vm1 -- env DISPLAY=:$i xdm -nodaemon &

说明:命令前面多加了判断容器是否处在运行状态RUNNING,因为不判断的话,假如容器处于冻结状态,lxc-attach执行就会处在假死状态.

7)容器只读mount宿主/tmp/.X11-unix,容器里启动的Xephyr只会创建抽象unix域,没能创建套接字文件,不过对本实验也足够了.
root@vm1:/# ls -l /tmp/.X11-unix
srwxrwxrwx 1 root   root   0 9月  17 07:48 X0
srwxrwxrwx 1 linlin linlin 0 9月  17 08:01 X1
root@vm1:/# netstat -lp |grep X
Active UNIX domain sockets (only servers)
unix  2      [ ACC ]     STREAM     LISTENING     28773    403/Xephyr           @/tmp/.X11-unix/X30
root@vm1:/#
X0和X1是宿主的显示号套接字文件.没见容器Xephyr创建X30套接字文件,只见X30抽象unix域.

类似的Xnest、x2goserver、xpra等是否会创建抽象unix域?没测试过.

8)容器只读mount宿主/tmp/.X11-unix,容器里使用SSH客户端
以本地方式登录容器桌面系统,打开模拟终端,运行命令
root@vm1:/# export | grep DISPLAY
declare -x DISPLAY=":30.0"
root@vm1:/#
可见环境变量显示号30

容器ssh远程连接debian机器
root@vm1:/# ssh -X linlin@debian
linlin@debian's password:

linlin@debian:~$ export | grep DISPLAY
declare -x DISPLAY="localhost:10.0"
linlin@debian:~$ xlogo
connect /tmp/.X11-unix/X30: No such file or directory
xlogo: 无法打开显示:
linlin@debian:~$
因容器没有X30套接字文件,运行图形界面失败,说明SSH客户端只连接套接字文件,而不连接抽象unix域

9)假如容器的系统不会删除/tmp下文件,可以读写mount
root@debian:/# mount --bind /tmp/.X11-unix  /var/lib/lxc/vm1/rootfs/tmp/.X11-unix
容器里启动的Xephyr创建抽象unix域,也创建了套接字文件.系统不删除/tmp下文件,但Xephyr进程正常退出会关闭其对应的显示号并删除套接字文件.因此容器显示号尽量避开宿主显示号.

10)
如果是容器/var/lib/lxc/vm1/config文件加自动mount,在宿主是见不到容器根/var/lib/lxc/vm1/rootfs/tmp/.X11-unix里的内容,不知mount命名空间mount参数选项哪里控制到?
root@debian:/# ls -l /var/lib/lxc/vm1/rootfs/tmp/.X11-unix
总用量 0 ,为空目录
root@debian:/#

如果是在宿主手动运行命令mount,在宿主是可见到挂载点/var/lib/lxc/vm1/rootfs/tmp/.X11-unix里有所共享目录的内容
root@debian:/# ls -l /var/lib/lxc/vm1/rootfs/tmp/.X11-unix
srwxrwxrwx 1 root   root   0 9月  17 07:48 X0
srwxrwxrwx 1 linlin linlin 0 9月  17 08:01 X1

看完上述内容,你们掌握LXC容器如何以本地方式运行X Server的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!


分享名称:LXC容器如何以本地方式运行XServer
地址分享:http://cdxtjz.cn/article/ipcpjd.html

其他资讯