Red Hat UBI (Universal Base Images) are great. Except when you need to install a pervious package version, you can’t. By default RHEL Universal Base Images ship with only the latest version of packages. So how can you “rollback” if one of the package apps has a problem?
You probably only realize you need this feature when something broke. Hopefully your Container Registry has enough image tags to go back to a working version for a quick fix. You don’t use the latest tag, right? But even if you can rollback to an older image tag, you should still be building new Container Images even if you need to rollback (version pin) only 1 package.
Important information that I couldn’t easily find:
The RHEL (Red Hat Enterprise Linux) host version must match the RHEL UBI container version built on the host because the RHEL Subscription entitlement files need to be passed into the container.
For example: From a RHEL 8 host, build a RHEL 8 UBI container with previous package versions available for install.
Another example: From a RHEL 9 host, build a RHEL 9 UBI container with previous package versions available for install.
This means a RHEL 9 host cannot build a RHEL 8 UBI container with previous package versions available for install.
How to version pin a package in RHEL UBI?
During the container build, the RHEL subscription entitlement needs to be available to the container.
Using podman, this is easy to accomplish. And Red Hat has a simple article for details about this.
But, if using Docker it’s not so easy. This is roughly how I do it on my host as part of the Docker Image build. Copy the host’s entitlement to a ‘local’ location for use in the build:
mkdir -p ./mount-local/etc-pki-entitlement
mkdir -p ./mount-local/rhsm
touch ./mount-local/redhat.repo
cp -rp /etc/pki/entitlement/* ./mount-local/etc-pki-entitlement
cp -rp /etc/rhsm/* ./mount-local/rhsm
awk '/-appstream-/' RS= ORS="\n\n" /etc/yum.repos.d/redhat.repo >> ./mount-local/redhat.repo
awk '/-baseos-/' RS= ORS="\n\n" /etc/yum.repos.d/redhat.repo >> ./mount-local/redhat.repo
ls -lR ./mount-local/
And my Dockerfile / Containerfile will mount the local entitlement (just change packagename-1.0.1-1.el9 to the package and version needed). The important part is using RUN with the mount to pass the entitlement to the build:
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
RUN --mount=type=bind,source=mount-local/,target=/run/secrets/ \
echo \
&& microdnf install -y --nodocs --setopt=install_weak_deps=0 packagename-1.0.1-1.el9 \
&& microdnf clean all \
&& rm -rf /var/cache/yum \
# Remove RHEL host repos
&& rm -rf /etc/yum.repos.d/redhat.repo
The installation of the older package version is successful!
Conclusion
Using this solution the version of RHEL on the host must match the version of RHEL UBI being used, since the host’s subscription entitlement must be passed into the container. Now a rollback to an older package version is possible!