Container images
The CKI Project uses container images for services, cron jobs, and the kernel build/test pipeline.
Repositories
| Repo | Images | Pattern | Notes |
|---|---|---|---|
| containers | ~35 (builders, buildah, dependency-tools, etc.) | Converted (most) | Includes live in working tree |
| cki-tools | 11 converted, 6 legacy | Mixed | Legacy blocked on Helm CA (W4 Aspect C) |
| cki-lib | 1 | Converted | |
| datawarehouse | 2 | Converted | Inline pip install |
| kernel-qe-tools | 1 | Converted | Inline pip install, heavy --no-emit-package |
| reporter | 1 | Converted | |
| kpet | 1 | Converted | |
| kwai | 1 | Converted | Experimental repo |
| kernel-workflow | 24 | Unconverted | Pending per-image conversion |
The containers repository holds shared includes, builder images, and base infrastructure. Service repositories (cki-tools, datawarehouse, etc.) hold their own image definitions alongside the source code.
Image types
Service and cron-job images
Fedora-based images with RPM and Python dependencies, deployed to OpenShift via
the :production tag. Examples: pipeline-herder, mr-auto-approver,
datawarehouse.
CI/pipeline images
Consumed by SHA-locked digest in .gitlab-ci.yml (production@sha256:<digest>).
The primary CI images are cki-tools (general CI jobs) and buildah (container
builds).
Builder images
RHEL/CentOS Stream/ELN/rawhide-based, RPM-only images used for kernel
compilation and testing in the containers repo. Support z-stream derivation via
ci/rewrite-rpms-in-for-zstream.py.
Image layout
Each image lives under builds/<name>/ with a Containerfile.in preprocessed
by cpp:
builds/<name>/
├── Containerfile.in
├── rpms/
│ ├── rpms.in.yaml
│ └── rpms.lock.yaml
└── requirements.lock (if Python deps)
The Containerfile.in starts with a digest-pinned base image and the standard
setup include:
/* renovate: datasource=docker depName=quay.io/fedora/fedora */
#define _BASE_IMAGE_TAG 44@sha256:abc123...
#include "setup"
The digest is inline in the tag (<ver>@sha256:<digest>) – this is the
current standard. cki_validate_containerfiles.sh accepts either this format
or a separate currentDigest=sha256:... in the Renovate comment for backward
compatibility. Builder images can override _BASE_IMAGE (e.g.,
registry.access.redhat.com/ubi9).
The setup include
Beyond FROM + labels, setup includes 7 sub-snippets:
snippet-rhel-version– version detection macros like_AT_LEAST_RHEL()snippet-envvars–REQUESTS_CA_BUNDLE,PYTHONUNBUFFERED,CKI_ARCHsnippet-cki-homesnippet-curlrcsnippet-nobest– disablesbest=Truesnippet-krb5snippet-dist-git-bastion
It configures the package manager (fastestmirror=true,
install_weak_deps=false for RHEL 8+; yum fallback with
skip_missing_names_on_install=False for RHEL 7 and earlier) and sets
OpenShift arbitrary UID/GID compatibility (chmod g=u /etc/passwd /etc/group).
Includes and build system
Shared includes (setup, rpm-lockfile, python-requirements, cleanup,
verify-python-lockfiles, rpm-lockfile-repos) are authored in the containers
repo under includes/.
In the containers repo, cpp resolves includes from the working tree
(-Iincludes). In all other repos, they come baked into the buildah image
at /usr/local/share/cki/buildah/
(COPY "includes/"* /usr/local/share/cki/buildah).
The standard local build tool is cki_build_image.sh (from cki-lib, installed
via pip into the buildah image and developer environments). It handles include
resolution, directory layout detection, and image naming. Its cpp search
order is: -Ibuilds -Iincludes -I/usr/local/share/cki/buildah.
For the containers repo, raw cpp -E -traditional -undef -Iincludes also works
for quick preprocessing checks.
Python dependency installation
Two patterns are in use:
-
Standard include:
#define _PYTHON_REQUIREMENTS_LOCKFILE+#include "python-requirements". The include copies the full repo to/code, runspip install --no-deps -rthenpip install --no-deps -e .(editable install). -
Inline commands:
pip install/uv pip installdirectly in the Containerfile – used by datawarehouse (uv pip install --system --no-cache --no-deps) and kernel-qe-tools (python3 -m pip install --no-cache-dir --no-deps) for more control over the install sequence.
Both patterns are valid; the include is simpler, inline is more flexible.
Dependency management
All container images use lockfiles for reproducible builds. See Lockfiles for the full lockfile architecture and Renovate for automated maintenance.
The dependency-tools image
Based on quay.io/konflux-ci/mintmaker-renovate-image (which provides Renovate
and rpm-lockfile-prototype). On top, it adds:
-
A
uvwrapper at/usr/local/bin/uv(PATH-ordered ahead of realuv; transparently adds--overridefor two-pass VCS dep resolution and--upgradefor range constraint updates). See Renovate for wrapper details. -
COPY files/registries.conf.d/ /etc/containers/registries.conf.d/– OCI cache mirror routing (pull-from-mirror = "digest-only") for three image families:quay.io/fedora/fedora,quay.io/fedora/eln, andquay.io/centos/centos. Without this config, digest-pinned base image pulls during manual builds and Renovate runs would not go through the dependency-archive OCI cache.
Used by both make targets for manual lockfile regeneration and by the Renovate
CronJob for automated updates. See Lockfiles for caching
details and Renovate for CronJob details.
CI builds
Each image is registered in the CI build matrix with IMAGE_NAME, CHANGES
(paths that trigger rebuild), and SMOKE_TEST_COMMANDS. Path-based filtering
via CHANGES/CHANGES_EXTRA determines which images are rebuilt on each
pipeline run.
CI consumption
Repos pin CI image digests as production@sha256:<digest> in .gitlab-ci.yml
or .gitlab/ci_templates/ci-images.yml. Some repos use the separate
ci-images.yml file specifically for CODEOWNERS exclusion – this lets Renovate
digest updates merge without requiring review from CI config owners.
Variables used:
cki_tools_image_tag: production@sha256:<digest>buildah_image_tag: production@sha256:<digest>
Renovate auto-updates digests; mr-auto-approver auto-approves.
Deployment
Service images deploy to OpenShift via the :production tag on the default
branch. CI images are consumed by digest (no :production tag needed).
Tags and environments
| Tag | Default branch | Tag pipeline | Merge request |
|---|---|---|---|
p-123456 |
always | always | always |
g-123456 |
on success | on success | on success |
latest |
on success | ||
tag |
on success | ||
mr-123 |
on success |
For production deployments, images are tagged with production. This runs
automatically on the default branch.
Multi-arch builds
Set IMAGE_ARCH to build for a non-native architecture via qemu (resulting
tags get an appended -arch). Set IMAGE_ARCHES to a stringified list of
architectures to build and upload a multi-arch manifest.
Non-Fedora image variants
Some images use non-Fedora bases and don’t follow the standard pattern:
receiver(Lambda custom runtime, cki-tools)dependency-archive(Lambda Python runtime, cki-tools)s3-proxy/testing-farm-dashboard(alpine-based)datawarehouse-nginx(nginx:stable-alpine)
These don’t use #include "setup" or lockfile includes.
Unconverted images
Six cki-tools images (amqp-bridge, cki-mr-viewer, cki-notifier, datawarehouse-submitter, kwaier, qe-pipeline-dashboard) still use the legacy pattern, blocked on Helm CA injection (W4 Aspect C).
kernel-workflow has 24 images still using the legacy pattern, pending per-image conversion.
Container image registries
quay.io
The cki organization on quay.io hosts public, internal, and mirror
repositories. Access is controlled via three teams:
- owners: admin access, CKI project members only
- repocreators: allows new repository creation, contains the
push_accountrobot account - readers: read-only access, external users and the
pull_accountrobot
registry.gitlab.com
Container registries in the cki-project group on gitlab.com contain mirrors
of public container image tags. A group deploy token with read_registry scope
is used for pulls from PSI OpenShift.
Docker Hub
Due to pull rate limits, images consumed from Docker Hub are mirrored into
quay.io/cki/mirror_* repositories (e.g., quay.io/cki/mirror_postgres:alpine
for the postgres image used by datawarehouse).