容易上手的LXD容器和虚拟X server
Overview
Linux有容器技术LXC,LXD对LXC进行了封装。与Docker类似,但LXC容器比Docker容器完整,且不像Docker是一次性容器设计运行结束后即销毁实例。使用LXD操作容器,体验介于Docker与虚拟机之间。(其实LXD不只提供封装LXC容器的功能,还提供封装虚拟机)
开始使用LXD——初始设置
-
从自己的发行版仓库安装LXD。LXD与Docker一样有一个守护进程
lxd
,因此有1sudo systemctl enable/disable/start/stop lxd
如果用
systemctl
停止lxd时,仍有正在运行的容器,那些容器不会被停止。所以应该先停止所有容器,再systemctl stop
lxd
是守护进程,而平时操作LXD则是用lxc
命令(此lxc非属于LXC容器,是LXD的客户端的意思) -
安装LXD后自动创建
lxd
用户组,我们手动把自己的日常用户添加进这个组里:1usermod -aG lxd <username>
-
添加清华LXC镜像(下文都用这个
tuna-images
源):1lxc remote add tuna-images https://mirrors.tuna.tsinghua.edu.cn/lxc-images/ --protocol=simplestreams --public
若想在连接镜像时使用代理:
1lxc config set core.proxy_http http://ip:port 2lxc config set core.proxy_https http://ip:port 3lxc config set core.proxy_ignore_hosts image-server.local
-
/etc/subuid
和/etc/subgid
都写11000:1000000:65536 2root:1000000:65536 3lxd:1000000:65536
让容器进程运行时,宿主看到的容器进程所属UID以一百万算起 (外一百万=内0)。且容器的
rootfs/
下的文件在宿主机看来UID、GID也都是一样map过的。这种叫非特权容器,比特权容器安全。 -
初始化LXD。运行
1sudo lxd init
交互问答式的。
- 其中有一个项让我们选择储存方式,我们自用选最简单的
dir
方式就可以,简单实用(这样容器内文件可以直接访问/var/lib/lxd/storage-pools/default/containers/容器名/rootfs/
查看修改)。
- 其中有一个项让我们选择储存方式,我们自用选最简单的
-
(可选)缓存与自动刷新相关设置
1lxc config set images.remote_cache_expiry 30 2lxc config set images.auto_update_interval 24 3lxc config set images.auto_update_cached false
-
重启
-
若宿主机有防火墙,可能需要手动把
lxdbr0
加入白名单,以使容器能够联网和与宿主机网络通信
使用LXD的常用操作
-
查看网络源目前可下载的镜像
1lxc image list tuna-images:
-
查看本地已缓存镜像
1lxc image list local:
-
下载镜像到本地缓存
1 lxc image copy ubuntu:14.04 local:
-
使用镜像创建并运行容器
1lxc launch tuna-images:发布版/版本/架构 容器名
(
发布版/版本/架构
也可以用它的一串十六进制数字id替代表示) -
运行或停止容器
1lxc start 容器名 2 3lxc stop [-f] 容器名
-
获得容器的bash shell
1lxc exec 容器名 bash
上面这个是non-login shell。它支持stdin传入,如:
1cat 宿主机上的某shell脚本 | lxc exec 容器名 bash -
(可选)在容器内,用
passwd
设置root密码。内账户有密码后,可登录容器获得login shell:1lxc console 容器名
-
挂载主机路径到容器
1lxc config|profile device add <容器名|profile名> share-from-host(设备名) disk source=/tmp/share-to-lxd/ path=/media/share-from-host [shift=true]
shift=true
启用指非特权容器需要的UID、GID map。这个要求内核支持shiftfs。若无,非特权容器中看到的宿主机共享进去的文件都是
nobody:nobody
的,而主机中看到的容器内创建的文件都是1000000:1000000
。 -
查看挂载
1lxc config device show <容器名>
-
手动带UID、GID map的挂载
前面说到,以非特权方式运行容器,UID、GID是map过的。如果内核不支持shiftfs,可以考虑一些workaround方案,用其他方式来做map(选其中一个):
-
bindfs:
1bindfs -u 1000000 -g 1000000 --create-for-user=1000 --create-for-group=1000 /something-on-host /tmp/share-to-lxd/subdir
(注意:这样mount中套mount,有时有看不见的可能,有时要先启动容器,进入了share文件夹,再从主机中bindfs)
-
fuse-overlayfs
-
虚拟X server
容器镜像一般都不会带有GUI相关内容的,若想在容器内运行GUI程序,除了安装相应的包外,还需要一个X server。可以把宿主机的X server共享给容器用,但这需要处理好X授权,且安全性低些。可以在容器内运行虚拟的X server,可以通过截图、VNC、录屏方式查看和操作这个虚拟X server,这些方法在CI自动化测试时也有用。
虚拟的X server有:
- Xvfb
- Xdummy
Xdummy更晩出现,声称比Xvfb功能更多。选择其中的一个使用
启动虚拟X server
二个中选一
-
Xvfb
1apt-get install xvfb
1Xvfb -ac :3 [-listen tcp] [-screen 0 1280x1024x24 ]
(它可能不会有任何输出)
-
Xdummy
- 第一种情况:需要编译
1apt-get install x11vnc xserver-xorg-video-dummy gcc
1Xdummy -install
Xdummy
是一个脚本,这一步实际上是用cc
编译一个.so
出来,准备结合LD_PRELOAD
运行X server。Xdummy
也可以调用X
。启动:
1Xdummy :3 [-listen tcp]
若报错 dlsym No such file ,则在上一步编译时,加一个环境变量
CFLAGS="-ldl"
-
第二种情况:不需要编译
这种情况下可以没有
Xdummy
这个脚本文件。创建
/tmp/dummy.conf
写入:1Section "Monitor" 2 Identifier "Monitor0" 3 HorizSync 28.0-80.0 4 VertRefresh 48.0-75.0 5 # https://arachnoid.com/modelines/ 6 # 1920x1080 @ 60.00 Hz (GTF) hsync: 67.08 kHz; pclk: 172.80 MHz 7 # Modeline "1920x1080_60.00" 172.80 1920 2040 2248 2576 1080 1081 1084 1118 -HSync +Vsync 8 Modeline "1280x720_60.00" 74.50 1280 1344 1472 1664 720 723 728 748 -hsync +vsync 9EndSection 10 11Section "Device" 12 Identifier "Card0" 13 Driver "dummy" 14 VideoRam 256000 15EndSection 16 17Section "Screen" 18 DefaultDepth 24 19 Identifier "Screen0" 20 Device "Card0" 21 Monitor "Monitor0" 22 SubSection "Display" 23 Depth 24 24 Modes "1280x720_60.00" 25 EndSubSection 26EndSection
然后运行:
1X -config /tmp/dummy.conf :3 -listen tcp
启动了虚拟的X server在:3
后,就可以
1env DISPLAY=:3 某GUI程序
也可以把Xvfb运行在宿主机上。这样要在容器内设定
export DISPLAY=宿主机IP:3
如果X server与client(client即那些GUI程序)不是运行在一个系统上的,虚拟X server那边则需要执行:
1xhost +<另一系统的IP>
通过shell对虚拟X server操作和截图
1apt-get install xdotool xwd scrot x11vnc
其中:
-
xdotool,模拟键盘和鼠标动作
-
x11vnc,VNC服务器,把X server内容和操作提供给VNC客户端
-
scrot,截图工具(推荐)
-
xwd,截图工具(不推荐)
模拟鼠标操作
容器内运行xdotool
1env DISPLAY=:3 xdotool getmouselocation
2env DISPLAY=:3 xdotool mousemove <x> <y>
3env DISPLAY=:3 xdotool click 1 # (1是左键)
VNC
容器内运行VNC服务
1x11vnc -display :3 -N -forever -shared -reopen [-passwd 123456] -desktop 1
宿主机可用Remmina连接容器IP:5903
(因为容器内用了:3
这个DISPLAY,所以默认的x11vnc服务端口是5903),密码为上面设置的123456
注意在Redmina中挥动鼠标可能会使截图中的鼠标隐藏。用xdotool mousemove可恢复
截图
在容器内运行CLI截图工具。
xwd(不推荐):
1xwd -display :3 -root -out /media/share-from-host/shot.xwd
2
3(主机中或容器中) convert shot.xwd shot.png
上面的convert是ImageMagick的命令
scrot(推荐):
1env DISPLAY=:3 scrot /media/share-from-host/shot.png -p # (-p : 截图包括鼠标)
(如果在CI中,截图后要上传artifacts)
也可以运行simplescreenrecorder或ffmpeg等对虚拟X server录屏(录屏工具与虚拟X server要运行在同一系统上)。
All articles are original (except for those specially claimed) and copyrighted. Copying without permission is forbidden.
打赏作者
写作不易,感谢支持! 扫个码吧~