How to build and use custom OS images

Remastering an OS image with a custom Dockerfile

Since OS images provided by Elemental are container images, they can also be used as a base image in a Dockerfile in order to create a new container image.

Imagine some additional packages from an extra repository is required, the following example showcases how this could be added:

  1. # The version of Elemental to modify
  2. FROM registry.suse.com/suse/sle-micro/5.5:latest
  3. # Custom commands
  4. RUN rpm --import <repo-signing-key-url> && \
  5. zypper addrepo --refresh <repo_url> extra_repo && \
  6. zypper install -y <extra_package>
  7. # IMPORTANT: /etc/os-release is used for versioning/upgrade. The
  8. # values here should reflect the tag of the image currently being built
  9. ARG IMAGE_REPO=norepo
  10. ARG IMAGE_TAG=latest
  11. RUN \
  12. sed -i -e "s|^IMAGE_REPO=.*|IMAGE_REPO=\"${IMAGE_REPO}\"|g" /etc/os-release && \
  13. sed -i -e "s|^IMAGE_TAG=.*|IMAGE_TAG=\"${IMAGE_TAG}\"|g" /etc/os-release && \
  14. sed -i -e "s|^IMAGE=.*|IMAGE=\"${IMAGE_REPO}:${IMAGE_TAG}\"|g" /etc/os-release
  15. # IMPORTANT: it is good practice to recreate the initrd and re-apply `elemental-init`
  16. # command that was used in the base image. This ensures that any eventual change that should
  17. # be synced in initrd included binaries is also applied there and consistent.
  18. RUN elemental init --force immutable-rootfs,grub-config,dracut-config,cloud-config-essentials,elemental-setup

Where latest is the base version we want to customize.

And then the following commands

  1. docker build --build-arg IMAGE_REPO=myrepo/custom-build \
  2. --build-arg IMAGE_TAG=v1.1.1 \
  3. -t myrepo/custom-build:v1.1.1 .
  4. docker push myrepo/custom-build:v1.1.1

The new customized OS is available as the Docker image myrepo/custom-build:v1.1.1 and it can be run and verified using docker with

  1. docker run -it myrepo/custom-build:v1.1.1 bash

Create a custom bootable installation ISO

Elemental leverages container images to build its root filesystems; therefore, it is possible to use it in a multi-stage environment to create custom bootable media that bundles a custom container image.

  1. FROM registry.suse.com/suse/sle-micro/5.5:latest AS os
  2. # Check the previous section on building custom images
  3. # The released OS already includes the toolchain for building ISOs
  4. FROM registry.suse.com/suse/sle-micro/5.5:latest AS builder
  5. ARG TARGETARCH
  6. WORKDIR /iso
  7. COPY --from=os / rootfs
  8. # work around buildah issue: https://github.com/containers/buildah/issues/4242
  9. RUN rm -f rootfs/etc/resolv.conf
  10. RUN elemental build-iso \
  11. dir:rootfs \
  12. --bootloader-in-rootfs \
  13. --squash-no-compression \
  14. -o /output -n "elemental-${TARGETARCH}"
  15. FROM busybox
  16. COPY --from=builder /output /elemental-iso
  17. ENTRYPOINT ["busybox", "sh", "-c"]

Build it with regular docker build command:

  1. docker build -t myrepo/custom-build:v1.1.1 \
  2. --build-arg IMAGE_REPO=myrepo/custom-build-iso \
  3. --build-arg IMAGE_TAG=v1.1.1 \
  4. .

The resulting container image is actually a container image including the ISO, this container image can be pushed to an OCI registry too. The ISO image can be extracted from the container to the current folder by executing the container as:

  1. docker run --rm -v $(pwd):/host mytest-image "busybox cp /elemental-iso/*.iso /host"

The new customized installation media can be found in elemental-<arch>.iso.

The above container run is equivalent to what elemental-operator does to extract the ISO from a container to build a new one including the registration URL, hence this is also a good check mark to verify the container can be pushed to a registry and used by the elemental-operator as a baseImage for a SeedImage resource.

List custom images as a ManagedOSVersion resource

In Elemental listing OS container images and ISO container images as ManagedOSVersion resources is not mandatory but handy. Specially from a UI perspective this makes the custom images visible and easy to use from the Elemental UI extension.

Continuing the example from the previous section a custom OS container referenced as myrepo/custom-build:v1.1.1 was built and eventually pushed to a registry. Then this image is ready to be added as a ManagedOSVersion resource with:

  1. apiVersion: elemental.cattle.io/v1beta1
  2. kind: ManagedOSVersion
  3. metadata:
  4. name: v1.1.1-custom-build
  5. namespace: fleet-default
  6. spec:
  7. metadata:
  8. displayName: Custom build image
  9. upgradeImage: myrepo/custom-build:v1.1.1
  10. type: container
  11. version: v1.1.1

Note the type: container states this is a container OS. This makes the image myrepo/custom-build:v1.1.1 eligible for OS upgrades from the UI.

Finally, the custom container for the ISO myrepo/custom-build-iso:v1.1.1 can also be included as a ManagedOSVersion resource with:

  1. apiVersion: elemental.cattle.io/v1beta1
  2. kind: ManagedOSVersion
  3. metadata:
  4. name: v1.1.1-custom-build-iso
  5. namespace: fleet-default
  6. spec:
  7. metadata:
  8. displayName: Custom build ISO image
  9. uri: myrepo/custom-build-iso:v1.1.1
  10. type: iso
  11. version: v1.1.1

Note the type: iso states this is an ISO. This makes the image myrepo/custom-build-iso:v1.1.1 eligible for SeedImages generation from UI.