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:傳統的方式
按<ctrl><alt><f1>鍵,登錄進入控制臺tty1命令行,執行X -query 192.168.1.2 :1
上面命令沒指定控制臺,會自動選擇控制臺tty8來運行著第二個X,顯示號為1
按<ctrl><alt><f8>鍵,便切換到控制臺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的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。