工作电脑用的系统是 Debian Sid(当前代号 trixie, Debian 13),工作内容中经常需要构建 BSP,厂商提供的构建要求通常为指定版本的 Ubuntu,如果不想换掉系统或者使用 Docker,可以考虑使用 LXC 创建指定版本的 Ubuntu 用于构建。

Debian 使用 LXC 可以参考官方Wiki,虽然 LXC VM 分为 Unprivileged 和 Privileged,前者隔离对主机更为安全,但是局限很多。在 BSP 构建中通常需要进行 mount 等操作,所以我们需要使用 Privileged VM。

安装和配置

安装 LXC:

1
sudo apt install lxc

容器默认使用主机共享网络。我们需要修改默认 apparmor 配置,在文件 /etc/lxc/default.conf

1
2
3
4
5
6
7
8
# /etc/lxc/default.conf
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up

# 修改如下内容
lxc.apparmor.allow_nesting = 1
lxc.apparmor.profile = unconfined

创建使用 VM

创建一个 ubuntu focal 的 VM,名称为 ubuntu-focal

1
2
# -n 指定名称(name) -t 指定模板(template) -r 指定 发行版(release)
sudo lxc-create -n ubuntu-focal -t ubuntu -- -r focal

检查当前存在的 VM:

1
2
3
4
sudo lxc-ls -f
# 以下为输出示例
# NAME         STATE   AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED 
# ubuntu-focal STOPPED 0         -      -    -    false        

配置 ubuntu-focal,定义一些本地挂载,以及允许 mount 等一些操作,修改该 VM 的配置 /var/lib/lxc/ubuntu-focal/config

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 添加以下内容到 /var/lib/lxc/ubuntu-focal/config 文件中

# allow  mount loop
lxc.apparmor.profile = unconfined 
lxc.cgroup2.devices.allow = b 7:* rwm
lxc.cgroup2.devices.allow = c 10:237 rwm

# 定义本地挂载点,将本地 /home/some_user/some_dir 自动挂载到 ubuntu-focal 的 /mnt 下
# 注意 lxc.mount.entry VM 中挂载点不使用 `/` 前缀
lxc.mount.entry = /home/some_user/some_dir   mnt     none    bind,create=file        0       0

# 挂载 loop 设备
lxc.mount.entry = /dev/loop0    dev/loop0       none    bind,create=file        0       0
lxc.mount.entry = /dev/loop1    dev/loop1       none    bind,create=file        0       0
lxc.mount.entry = /dev/loop2    dev/loop2       none    bind,create=file        0       0
lxc.mount.entry = /dev/loop3    dev/loop3       none    bind,create=file        0       0
lxc.mount.entry = /dev/loop4    dev/loop4       none    bind,create=file        0       0
lxc.mount.entry = /dev/loop5    dev/loop5       none    bind,create=file        0       0
lxc.mount.entry = /dev/loop-control     dev/loop-control        none    bind,create=file        0       0

启动 VM:

1
2
3
4
5
6
7
8
# 启动 ubuntu-focal
sudo lxc-start ubuntu-focal

# 查看当前运行的 VM 和 IP
sudo lxc-ls -f 
# 以下为输出
# NAME         STATE   AUTOSTART GROUPS IPV4       IPV6 UNPRIVILEGED 
# ubuntu-focal RUNNING 0         -      10.0.3.179 -    false     

现在可以通过 ssh ubuntu@10.0.3.179 进入 VM 进行操作了。 不需要使用时可以用命令 sudo lxc-stop ubuntu-focal 关掉 VM。

疑难问题

  1. 在构建 BSP 中提示 binfmt_misc 权限问题,请检查 VM 的配置中 lxc.apparmor.profile 字段,是否为 unconfined

  2. 在构建 BSP 中提示 mount -o loop 权限问题,请检查 VM 配置中 与上一章节示例中的有关 allow mount loop 相关的配置。

小结

使用 LXC 而不是 Docker 源于个人选择和使用场景,相对来说,支持同 VM 多进程的 LXC 更为适合用于构建 BSP 的 VM 工具, 而 Docker 则适合部署使用。