Build a bootc image

Create the Containerfile

The instructions will reflect nano commands.

In nano, you can save and exit with Ctrl+x, followed by the key y at the "Save modified buffer?" prompt and the Enter key at the prompt to keep the filename.

The vim editor is also available. Users of vim should already know the basics of opening, saving and exiting the editor.

Let’s examine a typical application container. We’ll start with something simple, a basic webserver running on the Red Hat Universal Base Image.

FROM registry.access.redhat.com/ubi9/ubi

RUN dnf install -y httpd
RUN echo "Hello Red Hat" > /var/www/html/index.html

ENTRYPOINT /usr/sbin/httpd -DFOREGROUND

A brief explanation of the key directives in the Containerfile above:

  • FROM → the base container image

  • RUN → commands to be executed during build

  • ENTRYPOINT → the command that will be executed by the container engine at run time

To create this basic webserver as an image mode system instead of an application container, create a Containerfile that contains the directives below.

 nano Containerfile
FROM registry.redhat.io/rhel9/rhel-bootc:9.5

RUN dnf install -y httpd
RUN echo "Hello Red Hat" > /var/www/html/index.html

RUN systemctl enable httpd.service

Let’s talk about the effects of these changes from the application container definition:

  • The FROM field is now pointing to the Red Hat Enterprise Linux 9.5 bootc image instead of the UBI base image.

    This new bootc image is a complete version of RHEL 9.5, much like the KVM image available on the Customer Portal. This image includes all of the OS components to run as a host as well as the new `bootc` command. It is built using `ostree` to facilitate the transactional updates that marks an image mode deployment from a package mode host.
  • RUN systemctl enable httpd.service replaces the ENTRYPOINT.

    To start the `httpd` service at host startup as you use `systemctl` would with any other host. There's no
    need to specify an executable that should be run when a container engine like podman starts the container.

Build the first bootc image

As with application containers, you can build this container with standard tools:

podman build --file Containerfile --tag {registry_hostname}/httpd

The arguments we pass to podman are:

  • --file Containerfile → what Containerfile to use for the build

  • --tag {registry_hostname}/httpd → the "tag" or name of the resulting container in the format <registry>/<repository>

You will see podman process each line of the Containerfile just as it would for an application container. Once complete, the last two lines of the output should read like this:

Successfully tagged {registry_hostname}/httpd
f1bea10eb37acf2e78a9b01c6242110c1901adbaf40dbce479241c6c735c58da

You have now built your first complete RHEL image as a bootc image!

Distributing the bootc image

Now that we have a full operating system in a standard OCI container image, we can use standard container registries to host and distribute our OS images. The only atypical thing so far is what’s in the base image. How we added software or files to the image is the same as any other application container. The special sauce of bootc comes when a host is running.

We have a registry available within the lab environment we can push our image to:

podman push {registry_hostname}/httpd

That’s all there is to designing and building a complete operating system. Start with a base, then add software and related configurations. You not only have the record of that work you can put under source control in the form of the Containerfile, you also have the binary image stored and versioned in the registry.

You’ve built your first bootc image, and it’s now published for use. How do we get from here to a running system?