MKOSI-How-To(三)

我想指定构建的发行版的版本和镜像站!

虽然对Arch用户可能没有意义,但是你可以通过[Distribution]段内的Release=配置项来指定使用的版本号:

1
2
3
[Distribution]
Distribution=debian
Release=forky

而对于Arch这类滚动发行版,你也可以使用Snapshot=配置项来指定使用某一天的快照来构建高度可复现的镜像:

1
2
3
[Distribution]
Distribution=arch
Snapshot=20250927

要使用镜像站,你只需要设置Mirror=

1
2
3
[Distribution]
Distribution=arch
Mirror=http://mirrors.ustc.edu.cn/archlinux/

我的Root用户没有密码 / Shell不对 / 系统语言不对!

这些本质上都是同一个问题。如前所说,在我们构建镜像时,systemd-firstboot会被触发,对镜像内进行初始化。你可以手动为systemd-firstboot提供参数,这样镜像的具体初始化细节就由你控制了。可配置的参数有这些,它们都位于[Content]段:

  • MachineID=:设置镜像内的机器ID,默认为random,你也可以使用mkosi.machine-id文件保存。
  • Locale=:镜像内的语言。
  • Keymap=:镜像内的Keymap。
  • Hostname=:设置镜像内的默认主机名。
  • RootShell=:Root用户的默认Shell。
  • RootPassword=:设置镜像内Root用户的默认密码,你也可以使用mkosi.rootpw文件保存密码,这个文件还可以是一个可以执行的Shell脚本,使用其输出作为密码。。

我还想添加我自己的文件 / 执行我自己的特殊初始化逻辑!

这完全是可以做到的。如前面所说,MKOSI为镜像构建过程中提供了多种挂钩点。我们只需要创建对应的脚本或文件,便可以在对应的时刻执行操作。

对于添加文件,我们有这些选择:

  • mkosi.sandbox/SandboxTrees=指定的目录:在开始构建前,往构建的沙盒环境中添加的文件。在设计上,这是为了让我们添加自己的包管理器配置,从而配置自定义的镜像源。例如,Debian的自定义镜像源可以放在mkosi.sandbox/etc/apt/sources.list
  • BaseTrees=指定的目录:在构建时使用的基础根文件系统(Base Files),默认情况下,MKOSI会使用内部的逻辑获取Base Files,除非你相当确定需要自己定制这一部分极早期的逻辑,否则不要轻易尝试提供,这很可能会导致你的镜像无法构建。
  • mkosi.skeleton/SkeletonTrees=指定的目录:在构建时,安装软件包之前先拷贝到镜像中的文件。
  • mkosi.extra/ExtraTrees=指定的目录:在构建时,安装软件包之后再拷贝到镜像中的文件。
  • RemoveFiles=:在构建时,安装软件包之后删除镜像内的文件。

对于自定义逻辑,我们可以使用钩子脚本,所有这些钩子脚本,默认情况下都是在宿主系统环境执行的,添加.chroot后缀可以使它们在镜像环境内执行:

  • mkosi.postinst[.chroot]:在安装软件包之后,执行systemd-firstboot等初始化操作之前执行。
  • mkosi.finalize[.chroot]:在执行systemd-firstboot等初始化操作之后执行。
  • mkosi.postoutput:不支持.chroot后缀,在镜像产品已经导出后执行。

脚本内还有一大批可以使用的环境变量,它们保存了可能用到的大部分路径,例如:

  • $ARCHITECTURE:镜像的架构。
  • $DISTRIBUTION:镜像的发行版。
  • $BUILDROOT:当前正在构建的镜像的根目录。
  • $SRCDIR:启动mkosi的路径。
  • $OUTPUTDIR:镜像构建产物的保存目录。

你可以在这里找到具体列表:MKOSI文档

构建真慢,没有缓存功能吗?

有的!而且你还可以选择性配置两种缓存:

  • 包管理器缓存:在构建时使用-i选项,或是在配置中指定Incremental=yes配置项,然后创建mkosi.cache/目录,或是在配置中指定CacheDirectory=配置项即可。
  • 镜像本身的缓存:创建mkosi.pkgcache/目录,或是在配置中指定PackageCacheDirectory=配置项即可。

我想要一个可以启动的VM镜像

对于一个VM来说,你通常会希望使用一个裸磁盘镜像(Raw Disk Image,虽然你完全可以通过virtiofsd直接使用目录作为根文件系统),而且希望这个镜像中包含ESP分区和必要的引导程序。

转换为MKOSI的语言,即为以下这些配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[Distribution]
Distribution=arch

[Output]
# 构建一个Raw Disk镜像
Format=disk

[Content]
# 可引导镜像
Bootable=yes
Packages=systemd
bash
coreutils
util-linux
# 你需要这些额外的软件包以构建可引导镜像
# 引导程序,Arch的systemd-boot已经包含在systemd包内了
# 如果是其他发行版,你需要明确安装
#systemd-boot
# Linux内核
linux

接着,你就可以使用Qemu直接启动这个镜像进行Debug了:

1
mkosi vm