The first requirement was getting the container tools and so I used the following to get those installed.
# dnf install container-tools
Updating Subscription Management repositories.
Last metadata expiration check: 2:20:17 ago on Fri 26 Jul 2024 07:17:27 AM CDT.
Dependencies resolved.
==============================================================================================================================================================================================================================================
Package Architecture Version Repository Size
==============================================================================================================================================================================================================================================
Installing:
container-tools noarch 1-14.el9 rhel-9-for-x86_64-appstream-rpms 8.3 k
Upgrading:
aardvark-dns x86_64 2:1.10.0-3.el9_4 rhel-9-for-x86_64-appstream-rpms 969 k
buildah x86_64 2:1.33.7-3.el9_4 rhel-9-for-x86_64-appstream-rpms 9.4 M
netavark x86_64 2:1.10.3-1.el9 rhel-9-for-x86_64-appstream-rpms 4.0 M
podman x86_64 4:4.9.4-6.el9_4 rhel-9-for-x86_64-appstream-rpms 16 M
Installing dependencies:
cockpit-podman noarch 84.1-1.el9 rhel-9-for-x86_64-appstream-rpms 683 k
podman-docker noarch 4:4.9.4-6.el9_4 rhel-9-for-x86_64-appstream-rpms 106 k
podman-remote x86_64 4:4.9.4-6.el9_4 rhel-9-for-x86_64-appstream-rpms 10 M
python3-podman noarch 3:4.9.0-1.el9 rhel-9-for-x86_64-appstream-rpms 178 k
python3-pyxdg noarch 0.27-3.el9 rhel-9-for-x86_64-appstream-rpms 108 k
python3-tomli noarch 2.0.1-5.el9 rhel-9-for-x86_64-appstream-rpms 37 k
skopeo x86_64 2:1.14.3-0.1.el9 rhel-9-for-x86_64-appstream-rpms 8.5 M
toolbox x86_64 0.0.99.5-2.el9 rhel-9-for-x86_64-appstream-rpms 2.5 M
udica noarch 0.2.8-1.el9 rhel-9-for-x86_64-appstream-rpms 54 k
Transaction Summary
==============================================================================================================================================================================================================================================
Install 10 Packages
Upgrade 4 Packages
Total download size: 52 M
Is this ok [y/N]: y
Downloading Packages:
(1/14): container-tools-1-14.el9.noarch.rpm 29 kB/s | 8.3 kB 00:00
(2/14): python3-tomli-2.0.1-5.el9.noarch.rpm 126 kB/s | 37 kB 00:00
(3/14): python3-pyxdg-0.27-3.el9.noarch.rpm 347 kB/s | 108 kB 00:00
(4/14): cockpit-podman-84.1-1.el9.noarch.rpm 3.0 MB/s | 683 kB 00:00
(5/14): udica-0.2.8-1.el9.noarch.rpm 616 kB/s | 54 kB 00:00
(6/14): python3-podman-4.9.0-1.el9.noarch.rpm 1.3 MB/s | 178 kB 00:00
(7/14): podman-docker-4.9.4-6.el9_4.noarch.rpm 1.2 MB/s | 106 kB 00:00
(8/14): toolbox-0.0.99.5-2.el9.x86_64.rpm 4.6 MB/s | 2.5 MB 00:00
(9/14): netavark-1.10.3-1.el9.x86_64.rpm 4.4 MB/s | 4.0 MB 00:00
(10/14): aardvark-dns-1.10.0-3.el9_4.x86_64.rpm 3.3 MB/s | 969 kB 00:00
(11/14): skopeo-1.14.3-0.1.el9.x86_64.rpm 3.9 MB/s | 8.5 MB 00:02
(12/14): podman-remote-4.9.4-6.el9_4.x86_64.rpm 3.2 MB/s | 10 MB 00:03
(13/14): buildah-1.33.7-3.el9_4.x86_64.rpm 3.5 MB/s | 9.4 MB 00:02
(14/14): podman-4.9.4-6.el9_4.x86_64.rpm 5.3 MB/s | 16 MB 00:02
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 9.6 MB/s | 52 MB 00:05
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Upgrading : aardvark-dns-2:1.10.0-3.el9_4.x86_64 1/18
Upgrading : netavark-2:1.10.3-1.el9.x86_64 2/18
Upgrading : podman-4:4.9.4-6.el9_4.x86_64 3/18
Installing : skopeo-2:1.14.3-0.1.el9.x86_64 4/18
(...)
Verifying : podman-4:4.9.4-6.el9_4.x86_64 17/18
Verifying : podman-2:4.6.1-8.el9_3.x86_64 18/18
Installed products updated.
Upgraded:
aardvark-dns-2:1.10.0-3.el9_4.x86_64 buildah-2:1.33.7-3.el9_4.x86_64 netavark-2:1.10.3-1.el9.x86_64 podman-4:4.9.4-6.el9_4.x86_64
Installed:
cockpit-podman-84.1-1.el9.noarch container-tools-1-14.el9.noarch podman-docker-4:4.9.4-6.el9_4.noarch podman-remote-4:4.9.4-6.el9_4.x86_64 python3-podman-3:4.9.0-1.el9.noarch python3-pyxdg-0.27-3.el9.noarch
python3-tomli-2.0.1-5.el9.noarch skopeo-2:1.14.3-0.1.el9.x86_64 toolbox-0.0.99.5-2.el9.x86_64 udica-0.2.8-1.el9.noarch
Complete!
Once the tooling is in place we need to login to register.redhat.io
with a Red Hat account.
# podman login registry.redhat.io
Username: myusername
Password:
Login Succeeded!
Next we need to pull two images for this workflow locally:
- The latest Red Hat Bootc Image Builder image
- The latest Red Hat Bootc image
First let's pull the image builder image.
# sudo podman pull registry.redhat.io/rhel9/bootc-image-builder
Trying to pull registry.redhat.io/rhel9/bootc-image-builder:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob edab65b863ae done |
Copying blob ce39a10ee5db done |
Copying blob 6e743249fd30 done |
Copying config 7e467a06cb done |
Writing manifest to image destination
Storing signatures
7e467a06cbc49d0e601ab5acad54afcf16c7fd3187296c74f2780ec3e758977a
Then we can pull the Red Hat Enterprise Linux Bootc image. Note if there is a need to build a custom Bootc image that can also be done as well and is documented here
# podman pull registry.redhat.io/rhel9/rhel-bootc:latest
Trying to pull registry.redhat.io/rhel9/rhel-bootc:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob b696b6658912 done |
Copying blob b696b6658912 done |
Copying blob e0b929cd893f done |
(...)
Copying blob 2942d3f50802 done |
Copying blob 8ea0992b56d4 done |
Copying blob ad312c5c40cc done |
Copying blob bd9ddc54bea9 done |
Copying config 482f4c67cc done |
Writing manifest to image destination
Storing signatures
482f4c67cc158fa4b8db27c09832d3133bc45b1d989aa6d166ca2ef45f6c7178
Once we have pulled our images let's just review what we have with podman images.
# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.redhat.io/rhel9/rhel-bootc latest 482f4c67cc15 4 days ago 1.47 GB
registry.redhat.io/rhel9/bootc-image-builder latest 7e467a06cbc4 4 days ago 521 MB
Next I created a directory structure under root
home directory.
# mkdir ~/bootc
# cd bootc
# mkdir output
I also created a config.toml file which allows us to customize the image. In this example I embedding my user/password, public ssh-key and the groups I should belong to.
# cat <<EOL > config.toml
[[blueprint.customizations.user]]
name = "myuser"
password = "password"
key = "ssh-rsa publick-key"
groups = ["wheel"]
EOL
Before we begin building let's review where we are and what is in the directory structure.
# pwd
/root/bootc
# ls
config.toml output
Before we begin the build process we need to workaround an issue here by removing the signatures in our local copy of the RHEL Bootc image.
# skopeo copy --remove-signatures containers-storage:registry.redhat.io/rhel9/rhel-bootc:latest containers-storage:registry.redhat.io/rhel9/rhel-bootc:latest
INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
Copying blob f2d952b04649 skipped: already exists
Copying blob bc1abff2c8d4 skipped: already exists
Copying blob 491341ca1509 skipped: already exists
(...)
Copying blob 6c118cde0f5c skipped: already exists
Copying blob 5f70bf18a086 skipped: already exists
Copying blob 12787d84fa13 skipped: already exists
Copying config 482f4c67cc done |
Writing manifest to image destination
If everything looks good we can proceed to run the build process which consists of using podman
to run the bootc-image-builder
while passing in some directories and referencing the starting image we will use to build our ISO. The entire build process happens within a container and the ISO generated is dumped to the output
directory we have mapped into the container. The process will take a bit to run and the log output is very long. I have provided the complete log run here with the condensed version below.
# podman run --rm -it --privileged --security-opt label=type:unconfined_t -v /var/lib/containers/storage:/var/lib/containers/storage -v /root/bootc/output:/output -v /root/bootc/config.toml:/config.toml registry.redhat.io/rhel9/bootc-image-builder --type iso --config /config.toml --local registry.redhat.io/rhel9/rhel-bootc:latest
Generating manifest manifest-iso.json
DONE
Building manifest-iso.json
starting -Pipeline source org.osbuild.containers-storage: 51102953cf5005007cf8b3bd76c39a0ae558aa34f311915042cdc0bc4c1fb246
Build
root: <host>
Pipeline source org.osbuild.curl: 07337b98b3c859adfb37b011d83cf0511884147bf999e7869ffbf9074b529a4f
Build
root: <host>
(...)
Writing to 'stdio:/run/osbuild/tree/install.iso' completed successfully.
⏱ Duration: 3s
org.osbuild.implantisomd5: bf37713d1bdb752cb80271b8243583e86665b003c69abff0e1730de24398fac1 {
"filename": "install.iso"
}
['implantisomd5', '/run/osbuild/tree/install.iso']
Inserting md5sum into iso image...
md5 = 11cf490ec817e7904ba35961d5323195
Inserting fragment md5sums into iso image...
fragmd5 = 4f7338c869faf1a2881d46dc4ac1eebf46148d4bf2fa1d59149d74f43195
frags = 20
Setting supported flag to 0
⏱ Duration: 3s
manifest - finished successfully
build: 9133fb8610ab053dae7e281e6a6655dbb912c4530d32e4da75c06b8713a87c80
anaconda-tree: fcd61d1236a42900977530f12f45fe452f2f0c8bf3c80a7ba60cb45ffe4bf36d
rootfs-image: 0a517e05ab42f947beec8dae4d2da338ca9cc7fe17b1daba013e24b1c60aeadf
efiboot-tree: 61a20c820b40436ce7bd6d1a74c6b97a05f7c8800b678083942e814cf9f7cc0e
bootiso-tree: 53d4713e1d036ca2d06ae3b0b64c8b9a4efb63cbc6fed4f13afe1e984b7af04d
bootiso: bf37713d1bdb752cb80271b8243583e86665b003c69abff0e1730de24398fac1
Build complete!
Results saved in
.
Once the build process completes we will find an install.iso
in the output/bootiso/
directory.
# cd ~/bootc/output/bootiso/
# ls -l
total 2211840
-rw-r--r--. 1 root root 2264924160 Jul 26 10:38 install.iso
The installation iso that was created can then be used to install RedHat Enterprise Linux on another host automatically and rather quickly compared to the old package based method.
Hopefully this provides a simple example to understand the concept of building and consuming Red Hat Image Mode.