Container base images

When migrate --format container emits a Containerfile, the FROM line is not a guess. It is the provenance'd base image the Translation Index records for the target release (FR-22 C2), read from the container_base_image table (sql/43, extended for openSUSE Leap by sql/214) and returned to the engine with the translation. The same value is written into the Containerfile and recorded in the signed attestation, so a build and its attestation can never name different bases.

Two rules make the FROM deterministic and auditable:

  • Family and tag only, never a digest. A pinned @sha256:… digest is a session pin; the tag is the stable reference a registry resolves and verifies at pull time. The table's CHECK constraint structurally refuses a digest.
  • Absence is a refusal, not a placeholder. A target with no measured row makes migrate --format container refuse at FROM rather than write a placeholder. Red Hat Enterprise Linux is unseeded on purpose — UBI is not RHEL, and a RHEL image lives behind a subscription registry this Index has not fetched — and SUSE Linux Enterprise is unseeded until its BCI catalog is measured.

The targets below are the ones carrying a measured base image today. The table is generated by scripts/check-container-base-images-docs.py and bound by CI: change a row in sql/43, sql/214 or sql/218, or the engine's list of left-out packages, and regenerate, or the pipeline fails.

The third column lists the packages the engine leaves out of the dnf install line for that image. Some base images ship a reduced variant of a package (curl-minimal, coreutils-single) that provides the full package's name and conflicts with it, so asking dnf for the full package aborts the build. The engine leaves those names out and says so in a comment in the Containerfile. verify then reads the built image's own rpm database and counts a promised name as present when an installed package provides it, reporting name (provided by variant). The variant measured for each image is the one in parentheses. The column is read from the table the engine itself uses (BASE_IMAGE_PROVIDED in engine/src/render.rs), which was measured against each dnf base image, not derived from the release number. On an apt or zypper base image the engine leaves nothing out.

The fourth column lists the other names the measurement found on that image: names the engine does not leave out, where asking the image's package manager for the name does not do what was asked. Each entry is the name, and in parentheses the installed package it meets. Unless the entry says otherwise, asking for the name aborts the install. Oracle Linux 8 and 9 ship the full curl, libcurl and coreutils, so there it is the reduced names that abort. Ubuntu 26.04 ships coreutils-from-uutils, and apt there refuses the other coreutils-from-* packages. On Debian 12 apt does something else, and the entry says so: it removes the installed package, installs the name and reports success, so the build goes green with a package missing that the image shipped. The first install line in the Containerfile does not stop apt from doing that. The translations in sql/ send none of the names in this column to the target they are listed for.

In both columns nothing means the image was measured and no such name was found, and not measured means the measurement was not run on that image. The two openSUSE Leap images are not measured: no probe here handles zypper. What was measured is recorded per image in container_base_probe and container_base_variant (sql/218), and an image with no record there fails the CI check, so it cannot be printed as nothing. The measurement asks about names that conflict with an installed package directly. A name whose dependencies conflict with the image is not covered, on any image.

TargetBase image (FROM)Left out of the install line (provided by)Not left out, and must not be asked for (the image ships)
AlmaLinux 8almalinux:8coreutils (coreutils-single), libcurl (libcurl-minimal)nothing
AlmaLinux 9almalinux:9coreutils (coreutils-single), curl (curl-minimal), libcurl (libcurl-minimal)nothing
AlmaLinux 10almalinux:10coreutils (coreutils-single), libcurl (libcurl-minimal)nothing
Amazon Linux 2amazonlinux:2nothinglibcrypt-nss (libcrypt)
Amazon Linux 2023amazonlinux:2023coreutils (coreutils-single), curl (curl-minimal), gnupg2 (gnupg2-minimal), libcurl (libcurl-minimal)amazon-linux-repo-s3 (amazon-linux-repo-cdn)
Debian 12debian:12nothinglibelogind0 (libsystemd0): apt removes the package the image ships and reports success
Debian 13debian:13nothingnothing
Oracle Linux 8oraclelinux:8nothingcoreutils-single (coreutils), libcurl-minimal (libcurl)
Oracle Linux 9oraclelinux:9nothingcoreutils-single (coreutils), curl-minimal (curl), fips-provider-next (openssl-fips-provider-so), libcurl-minimal (libcurl)
Rocky Linux 8rockylinux/rockylinux:8coreutils (coreutils-single), libcurl (libcurl-minimal)nothing
Rocky Linux 9rockylinux/rockylinux:9coreutils (coreutils-single), curl (curl-minimal), libcurl (libcurl-minimal)nothing
Rocky Linux 10rockylinux/rockylinux:10coreutils (coreutils-single), libcurl (libcurl-minimal)nothing
Ubuntu 18.04ubuntu:18.04nothingnothing
Ubuntu 20.04ubuntu:20.04nothingnothing
Ubuntu 22.04ubuntu:22.04nothingnothing
Ubuntu 24.04ubuntu:24.04nothingnothing
Ubuntu 26.04ubuntu:26.04nothingcoreutils-from-busybox (coreutils-from-uutils), coreutils-from-gnu (coreutils-from-uutils), coreutils-from-toybox (coreutils-from-uutils)
openSUSE Leap 15opensuse/leap:15not measurednot measured
openSUSE Leap 16opensuse/leap:16not measurednot measured

Minimal base images

The Index also records, per target, the distribution's minimal image, the package manager that image ships, and the package names that must stay out of an install line on it. translate --json shows them for the target as container_minimal_base. migrate --format container writes the image above and does not start from them. They are here for thin images, which start from the minimal image and install only the packages one workload needs, with the image's own package manager. Thin images are not released: verify does not grade one yet.

A target is in this table only if its catalog publishes a minimal image. Ubuntu, Amazon Linux and openSUSE Leap publish none under the image name used above, and have no row. Red Hat Enterprise Linux has none for the same reason it has no row above.

The last column is measured in each image with its own microdnf and does not follow from the table above. A minimal image is not always the smaller one: Rocky Linux 9's full image ships curl-minimal and libcurl-minimal, and its minimal image ships the full curl and libcurl, so on the minimal image it is the -minimal names that cannot be installed. Each entry is the name, and in parentheses the package the image ships in its place. Asking for the name aborts the install, with one exception that is marked: on the three EL8 images microdnf does not abort, it installs the i686 build of the package beside the x86_64 one and reports success.

nothing and not measured mean what they mean in the table above. The two Debian images were measured with apt, and their entry is marked the same way: apt does not abort, it removes the package the image ships.

The table is generated from sql/217 and sql/218 by the same script and bound by the same CI check.

TargetMinimal base imagePackage managerKept out of the install line (the image ships)
AlmaLinux 8almalinux:8-minimalmicrodnfcoreutils (coreutils-single), libcurl-minimal (libcurl): the i686 build is installed beside it
AlmaLinux 9almalinux:9-minimalmicrodnfcoreutils (coreutils-single), curl (curl-minimal), libcurl (libcurl-minimal)
AlmaLinux 10almalinux:10-minimalmicrodnfcoreutils (coreutils-single), libcurl (libcurl-minimal)
Debian 12debian:12-slimaptlibelogind0 (libsystemd0): apt removes the package the image ships and reports success
Debian 13debian:13-slimaptnothing
Oracle Linux 8oraclelinux:8-slimmicrodnfcoreutils (coreutils-single), libcurl-minimal (libcurl): the i686 build is installed beside it
Oracle Linux 9oraclelinux:9-slimmicrodnfcoreutils (coreutils-single), curl-minimal (curl), fips-provider-next (openssl-fips-provider-so), libcurl-minimal (libcurl)
Rocky Linux 8rockylinux/rockylinux:8-minimalmicrodnfcoreutils (coreutils-single), libcurl (libcurl-minimal): the i686 build is installed beside it
Rocky Linux 9rockylinux/rockylinux:9-minimalmicrodnfcoreutils (coreutils-single), curl-minimal (curl), libcurl-minimal (libcurl)
Rocky Linux 10rockylinux/rockylinux:10-minimalmicrodnfcoreutils (coreutils-single), libcurl-minimal (libcurl)

For how a target spec like rocky9 expands to one of these releases, see Supported targets. For where the FROM is recorded in the attestation, see Parity Attestation.

Operator overrides and digest pinning

The Index names each image by tag. migrate pins it by digest when it writes the Containerfile: it asks the image's registry what the tag names at that moment and writes FROM with that digest. See Base image per target for what is asked, what is recorded and what happens when the registry does not answer. The tables above are the tags; no digest is stored in the Index.

Whether an operator can override the base image is still deferred to an owner decision. The trade-offs are written up in docs/container-base-image-override-options.md.