Skip to content

Migrate cp-kcat to UBI9 micro base image#113

Draft
Krish Vora (KrishVora01) wants to merge 2 commits intomasterfrom
micro-migration-ubi9
Draft

Migrate cp-kcat to UBI9 micro base image#113
Krish Vora (KrishVora01) wants to merge 2 commits intomasterfrom
micro-migration-ubi9

Conversation

@KrishVora01
Copy link
Contributor

@KrishVora01 Krish Vora (KrishVora01) commented Feb 22, 2026

Summary

  • Switch from 2-stage ubi9-minimal build to 3-stage build using ubi9-micro as the final base
  • Stage 1: Build kcat from source on ubi9 (unchanged logic)
  • Stage 2: Install runtime deps into /microdir using dnf --installroot
  • Stage 3: Copy runtime libs + kcat binary to ubi9-micro
  • User migration: useradd -> manual /etc/passwd entry (ubi9-micro has no shadow-utils)
  • Build arg: UBI_MINIMAL_VERSION -> UBI_MICRO_VERSION + UBI9_VERSION

Runtime dependency verification

Ran ldd against the compiled kcat binary and cross-referenced each shared library with what ubi9-micro ships natively. The following packages are installed in the runtime-deps stage because they are NOT in ubi9-micro:

Library RPM Package
libz.so.1 zlib
libcrypto.so.3, libssl.so.3 openssl-libs
libsasl2.so.3 cyrus-sasl-lib
libcrypt.so.2 libxcrypt
libgssapi_krb5.so.2, libkrb5.so.3, libk5crypto.so.3, libkrb5support.so.0 krb5-libs
libcom_err.so.2 libcom_err
libcurl.so.4 libcurl-minimal
libkeyutils.so.1 keyutils-libs
libnghttp2.so.14 libnghttp2

Plus ca-certificates for the TLS trust store.

Libraries already in ubi9-micro (no install needed): glibc (libc, libm, libresolv, ld-linux), libselinux, pcre2.

Docker build + functional test (13/13 passed)

Built the full image locally and ran all tests from the Confluent kcat docs against a cp-kafka broker:

# Test Result
1 kcat -V (version check) PASS
2 kafkacat symlink works PASS
3 Metadata listing (-L) PASS
4 Metadata listing as JSON (-L -J) PASS
5 Produce messages (-P) PASS
6 Consume messages (-C) PASS
7 Consume with format string (-f) PASS
8 Produce with keys (-K:) PASS
9 Consume keyed messages PASS
10 Consume with full metadata format PASS
11 Produce/consume to specific partition (-p) PASS
12 Metadata for specific topic (-L -t) PASS
13 Non-root user verification (uid=1000) PASS

Note: kcat 1.7.0 (librdkafka 1.7.0) has a pre-existing compatibility issue with latest Kafka ListOffsets API. Consume tests use -X broker.version.fallback=2.6.0. Not related to this image change.

Full test output: see kcat-micro-verification.md in this branch.

Test plan

  • Docker image builds successfully
  • kcat -V returns version info
  • kcat -L lists broker metadata
  • kcat -L -J returns JSON metadata
  • Produce/consume messages works
  • Keyed produce/consume works
  • Partition-specific produce/consume works
  • Format string output works
  • kafkacat symlink works
  • Container runs as non-root user (UID 1000)
  • CI build passes (Maven + Docker)
  • Kind local test script: ./run-kind-e2e-kcat.sh

Copilot AI review requested due to automatic review settings February 22, 2026 12:08
@KrishVora01 Krish Vora (KrishVora01) marked this pull request as draft February 22, 2026 12:09
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the cp-kcat container build from a ubi9-minimal-based final image to a 3-stage build that targets a ubi9-micro final image, aiming to reduce runtime image size while preserving required runtime libraries and running as non-root.

Changes:

  • Update Maven Docker build args to pass UBI9_VERSION and UBI_MICRO_VERSION into the Docker build.
  • Refactor kcat/Dockerfile.ubi9 into a 3-stage build: build from source, assemble runtime deps via dnf --installroot, then copy into a UBI micro final image.
  • Replace useradd with manual /etc/passwd + /etc/group entries and run as UID 1000.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
kcat/pom.xml Switch build args from minimal to UBI9 + UBI micro version args.
kcat/Dockerfile.ubi9 Convert to 3-stage build with runtime deps copied into a UBI micro final image and non-root user setup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


RUN echo "Building kcat ....." \
&& microdnf install -y dnf \
&& dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This build installs epel-release-latest-8.noarch.rpm on a UBI9 (RHEL 9) base. EPEL major versions are tied to the RHEL major version; using the EPEL 8 release package on UBI9 is likely to break dnf dependency resolution or pull incompatible packages. Consider switching to the EPEL 9 release RPM (or removing EPEL entirely if it’s no longer needed).

Suggested change
&& dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \
&& dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm \

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is carried over unchanged from the original master Dockerfile. kcat's bootstrap.sh doesn't actually pull packages from EPEL — the build packages (gcc-c++, cmake, etc.) all come from the base UBI9 repos. The EPEL repo is enabled but unused in practice. Changing it is out of scope for this migration, but harmless either way.

Comment on lines +24 to 26
# Stage 1: Build kcat from source
FROM registry.access.redhat.com/ubi9:${UBI9_VERSION} AS build

Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FROM registry.access.redhat.com/ubi9:${UBI9_VERSION} looks like an invalid UBI image reference (UBI images are typically under registry.access.redhat.com/ubi9/ubi:<tag>). As written, the build stage may fail to pull the base image; consider switching to the correct repository path for the full UBI9 base image.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registry.access.redhat.com/ubi9 is a valid top-level alias for ubi9/ubi. Both references resolve to the same image. This is the same reference used in all other micro-migration Dockerfiles across kafka-images, ksql-images, and kafka-rest-images. The image builds successfully with this reference.

Comment on lines +43 to +45
# Stage 2: Install runtime dependencies to /microdir
FROM registry.access.redhat.com/ubi9:${UBI9_VERSION} AS runtime-deps

Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The runtime-deps stage uses FROM registry.access.redhat.com/ubi9:${UBI9_VERSION}; if the intended base is the standard UBI9 image, the correct reference is usually registry.access.redhat.com/ubi9/ubi:<tag>. Using registry.access.redhat.com/ubi9:<tag> is likely to fail at pull time.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above — registry.access.redhat.com/ubi9 is a valid alias for ubi9/ubi. The full Docker image builds and all 13 functional tests pass with this reference.

&& rm -rf /microdir/dev/* /microdir/proc/* /microdir/sys/*

# Stage 3: Final ultra-lightweight image using ubi9-micro
FROM registry.access.redhat.com/ubi9-micro:${UBI_MICRO_VERSION}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FROM registry.access.redhat.com/ubi9-micro:${UBI_MICRO_VERSION} is likely not the correct UBI micro image path; the UBI micro image is typically registry.access.redhat.com/ubi9/ubi-micro:<tag>. If the repository name is wrong, the final stage will fail to pull.

Suggested change
FROM registry.access.redhat.com/ubi9-micro:${UBI_MICRO_VERSION}
FROM registry.access.redhat.com/ubi9/ubi-micro:${UBI_MICRO_VERSION}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registry.access.redhat.com/ubi9-micro is a valid top-level alias for ubi9/ubi-micro. This matches the convention used in cp-base-java-micro and other micro-migration Dockerfiles. The image builds and kcat -V runs successfully on the final ubi9-micro base.

Switch from 2-stage ubi9-minimal build to 3-stage build using
ubi9-micro as the final base:
- Stage 1: Build kcat from source on ubi9 (unchanged logic)
- Stage 2: Install runtime deps (libcurl, cyrus-sasl, krb5, etc.)
  into /microdir using dnf --installroot
- Stage 3: Copy runtime libs + kcat binary to ubi9-micro

Key changes:
- Base image: ubi9-minimal -> ubi9-micro (ultra-lightweight, no pkg mgr)
- Package manager: microdnf -> dnf --installroot=/microdir
- Runtime deps installed in isolated stage, only /usr/lib64 + /etc/pki copied
- Remove shadow-utils from build deps; manually create appuser in /etc/passwd
- Build arg: UBI_MINIMAL_VERSION -> UBI_MICRO_VERSION + UBI9_VERSION
- Fix LABEL summary quoting (remove nested quotes)
- Fix fabric8 plugin indentation in pom.xml

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full ldd analysis and 13 functional tests (version, metadata, produce,
consume, keyed messages, partitions, format strings, non-root user)
all passing against a local cp-kafka broker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants