Building bootc base images without rpm-ostree compose #2101
Replies: 1 comment
Update: validated end-to-end on Fedora 42Following up with results from building and deploying this approach in production CI. What we builtA FROM-scratch Fedora 42 bootc base image using The transforms are the same ones documented in the PR description: toplevel symlinks, /var tmpfiles.d generation, nss-altfiles /usr/lib/passwd, dracut conf.d + initramfs, systemctl presets, bootupd metadata, rpmdb relocation, ostree prepare-root.conf. ValidationTested on GCP (n2-standard-8, Fedora 42, nested KVM) across 11 categories:
Findings
Re: cgwalters' review on PR #2100Understood that bootc shouldn't own these transforms. The Blog post with the full technical details: https://andrew.dunn.dev/writing/building-bootc-from-scratch/ |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Problem
Building bootc base images currently requires
rpm-ostree compose, which ties base image creation to the rpm-ostree ecosystem. This creates a chicken-and-egg problem: bootc aims to be the primary interface for bootable containers, but building the base images still requires rpm-ostree.Related: #215
Analysis: What does rpm-ostree compose actually do?
I analyzed the rpm-ostree compose pipeline (
composepost.rs) and the Fedora 42 bootc base image build system (gitlab.com/fedora/bootc/base-images) to identify exactly which transforms are needed.Key finding: The Fedora bootc images use
rpm-ostree compose rootfs(notcompose image). This produces a plain directory that gets packaged as a regular OCI image viaFROM scratch+COPY. The ostree commit happens at deployment time, not build time.I inspected the official
quay.io/fedora/fedora-bootc:42image filesystem and mapped every deviation from a plaindnf --installrootto the transform that caused it. The results:Plus config injection: prepare-root.conf, kernel install.conf, dnf5 config, useradd HOME fixup, bootc install config, bootupd metadata.
Two transforms from the original rpm-ostree analysis turned out to be unnecessary: the
/etc -> /usr/etcrename (handled at deploy time by ostree-prepare-root) and SELinuxfile_contexts.subs_distfixups (the selinux-policy RPM already includes all ostree-specific entries like/usr/etc /etc).Implementation
I implemented these transforms as
bootc container finalize-rootfsandbootc container post-chroot-cleanupsubcommands. PR: #2100The
bootc containernamespace already has precedent for build-time write operations (ukify,export), and its documented purpose is "Operations which can be executed as part of a container build" -- so this seemed like the natural home.The workflow:
Test Results
Built a Fedora 42 bootc base image using this workflow (no rpm-ostree at any point). Tested on a GCP VM with nested virtualization for KVM.
Build
Boot (QEMU + KVM)
bootc status output from the booted image
ostree admin status
Boot log -- ostree prepare-root and switch-root sequence
Filesystem comparison: tool-built image vs official quay.io/fedora/fedora-bootc:42
Toplevel symlinks are identical between both images. The differences are:
Findings along the way
Questions
bootc container finalize-rootfsthe right place for this? Or should it be a separate tool? Thebootc containernamespace seemed natural given the existingukifyandexportprecedents.All reactions