MKOSI-How-To(三)
我想指定构建的发行版的版本和镜像站!
虽然对Arch用户可能没有意义,但是你可以通过[Distribution]段内的Release=配置项来指定使用的版本号:
1 | [Distribution] |
而对于Arch这类滚动发行版,你也可以使用Snapshot=配置项来指定使用某一天的快照来构建高度可复现的镜像:
1 | [Distribution] |
要使用镜像站,你只需要设置Mirror=:
1 | [Distribution] |
我的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 | [Distribution] |
接着,你就可以使用Qemu直接启动这个镜像进行Debug了:
1 | mkosi vm |