容易上手的LXD容器和虚拟X server
Linux有容器技术LXC,LXD对LXC进行了封装。与Docker类似,但LXC容器比Docker容器完整,且不像Docker是一次性容器设计运行结束后即销毁实例。使用LXD操作容器,体验介于Docker与虚拟机之间。(其实LXD不只提供封装LXC容器的功能,还提供封装虚拟机)
开始使用LXD——初始设置
-
从自己的发行版仓库安装LXD。LXD与Docker一样有一个守护进程
lxd,因此有sudo systemctl enable/disable/start/stop lxd如果用
systemctl停止lxd时,仍有正在运行的容器,那些容器不会被停止。所以应该先停止所有容器,再systemctl stoplxd是守护进程,而平时操作LXD则是用lxc命令(此lxc非属于LXC容器,是LXD的客户端的意思) -
安装LXD后自动创建
lxd用户组,我们手动把自己的日常用户添加进这个组里:usermod -aG lxd <username> -
添加清华LXC镜像(下文都用这个
tuna-images源):lxc remote add tuna-images https://mirrors.tuna.tsinghua.edu.cn/lxc-images/ --protocol=simplestreams --public若想在连接镜像时使用代理:
lxc config set core.proxy_http http://ip:port lxc config set core.proxy_https http://ip:port lxc config set core.proxy_ignore_hosts image-server.local -
/etc/subuid和/etc/subgid都写1000:1000000:65536 root:1000000:65536 lxd:1000000:65536让容器进程运行时,宿主看到的容器进程所属UID以一百万算起 (外一百万=内0)。且容器的
rootfs/下的文件在宿主机看来UID、GID也都是一样map过的。这种叫非特权容器,比特权容器安全。 -
初始化LXD。运行
sudo lxd init交互问答式的。
- 其中有一个项让我们选择储存方式,我们自用选最简单的
dir方式就可以,简单实用(这样容器内文件可以直接访问/var/lib/lxd/storage-pools/default/containers/容器名/rootfs/查看修改)。
- 其中有一个项让我们选择储存方式,我们自用选最简单的
-
(可选)缓存与自动刷新相关设置
lxc config set images.remote_cache_expiry 30 lxc config set images.auto_update_interval 24 lxc config set images.auto_update_cached false -
重启
-
若宿主机有防火墙,可能需要手动把
lxdbr0加入白名单,以使容器能够联网和与宿主机网络通信
使用LXD的常用操作
-
查看网络源目前可下载的镜像
lxc image list tuna-images: -
查看本地已缓存镜像
lxc image list local: -
下载镜像到本地缓存
lxc image copy ubuntu:14.04 local:
-
使用镜像创建并运行容器
lxc launch tuna-images:发布版/版本/架构 容器名(
发布版/版本/架构也可以用它的一串十六进制数字id替代表示) -
运行或停止容器
lxc start 容器名 lxc stop [-f] 容器名 -
获得容器的bash shell
lxc exec 容器名 bash上面这个是non-login shell。它支持stdin传入,如:
cat 宿主机上的某shell脚本 | lxc exec 容器名 bash -(可选)在容器内,用
passwd设置root密码。内账户有密码后,可登录容器获得login shell:lxc console 容器名 -
挂载主机路径到容器
lxc 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。若使用的这个的
shift=true挂载,最好在容器里创建一个普通用户来操作:mkdir /home/me echo "me:x:1000:100:me:/home/me:/bin/bash" >> /etc/passwd su -l me其实,容器内,使用容器内的root或普通用户都不重要,只不过,有挂载的情况下,如果容器内是root创建的文件,转到宿主机内也成了归属于root,这有时就不方便于我们操作。
-
查看挂载
lxc config device show <容器名> -
手动带UID、GID map的挂载
前面说到,以非特权方式运行容器,UID、GID是map过的。如果内核不支持shiftfs,可以考虑一些workaround方案,用其他方式来做map(选其中一个):
-
bindfs:
bindfs -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
apt-get install xvfbXvfb -ac :3 [-listen tcp] [-screen 0 1280x1024x24 ](它可能不会有任何输出)
-
Xdummy
- 第一种情况:需要编译
apt-get install x11vnc xserver-xorg-video-dummy gccXdummy -installXdummy是一个脚本,这一步实际上是用cc编译一个.so出来,准备结合LD_PRELOAD运行X server。Xdummy也可以调用X。启动:
Xdummy :3 [-listen tcp]若报错 dlsym No such file ,则在上一步编译时,加一个环境变量
CFLAGS="-ldl"-
第二种情况:不需要编译
这种情况下可以没有
Xdummy这个脚本文件。创建
/tmp/dummy.conf写入:Section "Monitor" Identifier "Monitor0" HorizSync 28.0-80.0 VertRefresh 48.0-75.0 # https://arachnoid.com/modelines/ # 1920x1080 @ 60.00 Hz (GTF) hsync: 67.08 kHz; pclk: 172.80 MHz # Modeline "1920x1080_60.00" 172.80 1920 2040 2248 2576 1080 1081 1084 1118 -HSync +Vsync Modeline "1280x720_60.00" 74.50 1280 1344 1472 1664 720 723 728 748 -hsync +vsync EndSection Section "Device" Identifier "Card0" Driver "dummy" VideoRam 256000 EndSection Section "Screen" DefaultDepth 24 Identifier "Screen0" Device "Card0" Monitor "Monitor0" SubSection "Display" Depth 24 Modes "1280x720_60.00" EndSubSection EndSection然后运行:
X -config /tmp/dummy.conf :3 -listen tcp
启动了虚拟的X server在:3后,就可以
env DISPLAY=:3 某GUI程序
也可以把Xvfb运行在宿主机上。这样要在容器内设定
export DISPLAY=宿主机IP:3如果X server与client(client即那些GUI程序)不是运行在一个系统上的,虚拟X server那边则需要执行:
xhost +<另一系统的IP>
通过shell对虚拟X server操作和截图
apt-get install xdotool xwd scrot x11vnc
其中:
-
xdotool,模拟键盘和鼠标动作
-
x11vnc,VNC服务器,把X server内容和操作提供给VNC客户端
-
scrot,截图工具(推荐)
-
xwd,截图工具(不推荐)
模拟鼠标操作
容器内运行xdotool
env DISPLAY=:3 xdotool getmouselocation
env DISPLAY=:3 xdotool mousemove <x> <y>
env DISPLAY=:3 xdotool click 1 # (1是左键)
VNC
容器内运行VNC服务
x11vnc -display :3 -N -forever -shared -reopen [-passwd 123456] -desktop 1
宿主机可用Remmina连接容器IP:5903(因为容器内用了:3这个DISPLAY,所以默认的x11vnc服务端口是5903),密码为上面设置的123456
注意在Redmina中挥动鼠标可能会使截图中的鼠标隐藏。用xdotool mousemove可恢复
截图
在容器内运行CLI截图工具。
xwd(不推荐):
xwd -display :3 -root -out /media/share-from-host/shot.xwd
(主机中或容器中) convert shot.xwd shot.png
上面的convert是ImageMagick的命令
scrot(推荐):
env DISPLAY=:3 scrot /media/share-from-host/shot.png -p # (-p : 截图包括鼠标)
(如果在CI中,截图后要上传artifacts)
也可以运行simplescreenrecorder或ffmpeg等对虚拟X server录屏(录屏工具与虚拟X server要运行在同一系统上)。
关注一下
📺 Bilibili 收集有趣科技 和发布原创视频 | 🖥️ Github 有用的和没用的开源项目代码
玩而后赏
子曰,玩而予赏,善莫大焉?
又曰,玩而不赏,良心安焉?
写作不易,感谢支持!
虽然,小小玩意,不足挂齿;
亦是,卅年老刀,献丑于此。
其实,多赏非求,少许亦可。
进者,参观主页,玩物更多。
未联系作者获得同意前,不可转载
转载必须附上源地址,并连我博客上的宣传内容一并转载

浙公网安备 33010602011771号