Container image based ISOs
This is an experiment showcasing building bootable ISO images from a container image. Building such an ISO is a 2-step process:
- Building a container image that fulfills the required contract (more on that later)
- Converting such an image to an ISO via image-builder and the
bootc-generic-isotype
Design decisions
- The ISO uses El Torito configuration, shim, and GRUB2 configured to maximize compatibility. I.e., it is supposed to boot on all combinations of UEFI/legacy and CD/USB.
- Shim, GRUB2 and its configuration, kernel, and initramfs come from well-specified paths in the container.
- The ISO embeds the container converted to a squashfs archive.
- The user is responsible for configuring GRUB2, kernel, and initramfs so they can load the squashfs.
Container-native ISO contract v0.1.0
This spec is inspired by the layout of Fedora bootc images and Fedora live ISO images.
- The kernel is expected to be in
/usr/lib/module/*/vmlinuz. If there are multiple kernels, the behavior is unspecified. This is to be specified in a future version of this contract. The kernel is put in/images/pxeboot/vmlinuzin the ISO. - The initramfs is expected to be next to the kernel with the filename
initramfs.img. The initramfs is put in/images/pxeboot/initrd.img. - The UEFI vendor is specified by a directory name in
/usr/lib/efi/shim/*/EFI/$VENDOR. If there are multiple directories, the behaviour is unspecified. TheBOOTdirectory is always ignored. - Shim and grub2 EFI binaries (
shimx64.efi,mmx64.efi,gcdx64.efi) are expected to be in/boot/efi/EFI/$VENDOR. - GRUB2 modules are expected to be in
/usr/lib/grub/i386-pc. - Required executables are
podman,mksquashfs,xorriso,implantisomd5,grub2-mkimage, andpython. - The container image is converted to a squashfs archive and put into
/LiveOS/squashfs.imgin the ISO. - Additional configuration can be written into
/usr/lib/bootc-image-builder/iso.yamlin YAML format. The file currently supports 2 top-level keys:label(string): Label of the ISOgrub2(object): GRUB2 configuration, supports the following keys:default(string): Default menu itemtimeout(string): Default timeout (in seconds)entries(array of objects): GRUB2 menu entries with the following keys (all are required):name(string): Name of the entrylinux(string): Path to the kernel + kernel arguments (the path is always/images/pxeboot/vmlinuzin this version of this spec)initrd(string): Path to the initramfs (the path is always/images/pxeboot/initrd.imgin this version of this spec)
- The
--bootc-installer-payload-refargument toimage-buildercan optionally be used to copy a container image from the host's container storage to/var/lib/containers/storagein the squashfs archive.
Example ISOs
This repository contains the following example ISOs:
bazzite- Clone of the Bazzite Live ISO but built using this contract andimage-builder. Contains a KDE environment with flatpaks, and an offline installer.kinoite- Live environment of Fedora Kinoite (Fedora with KDE)bluefin-lts- Live environment of Bluefin LTS (CentOS Stream 10 + GNOME)debian- Tiny Debian text environment, log in withliveuserubuntu- Tiny Ubuntu text environment, log in withliveuserfedora-payload- Minimal text-based Fedora bootc online installer.
Building ISOs
Build the container:
sudo just container <CONTAINER>
Then build the ISO:
sudo just iso <CONTAINER>
Since you need a fairly new version (TBD) of image-builder, I recommend using a containerized version of image-builder with all patches required for this spec ready:
sudo just build-image-builder iso-in-container <CONTAINER>
Quirks
- Due to an issue in
image-builder,/etc/os-releasein the container must containVERSION_ID. Its value is currently unused, though. - The squashfs is currently not SELinux-labeled. This will be fixed and configurable in the next version of the spec.
- The spec should live in
osbuild/image-builder-cli.