Skip to content

Refactor Containerfile to multi-stage build#191

Open
are-ces wants to merge 12 commits into
lightspeed-core:mainfrom
are-ces:multi-stage-containerfile
Open

Refactor Containerfile to multi-stage build#191
are-ces wants to merge 12 commits into
lightspeed-core:mainfrom
are-ces:multi-stage-containerfile

Conversation

@are-ces
Copy link
Copy Markdown
Contributor

@are-ces are-ces commented May 19, 2026

Description

Refactor both CPU and CUDA Containerfiles from single-stage to multi-stage builds to eliminate image bloat from build tools.

Stage 1 (builder): Installs all build tools (gcc, cmake, cargo, rust, dev libs, openssl-devel) and compiles Python dependencies from sdist. This stage is discarded after the venv is built.

Stage 2 (runtime): Clean image with only runtime packages (python3.12, git, ruby, skopeo, runtime shared libs). Copies .venv from the builder via COPY --from=builder. No build tools in the final image.

Image size reduction

CPU:

Old (single-stage) Multi-stage Savings
amd64 4.67 GB 2.69 GB 1.98 GB (42%)
arm64 3.96 GB 2.35 GB 1.61 GB (41%)

CUDA:

Old (single-stage) Multi-stage Savings
amd64 29.8 GB 20.1 GB 9.7 GB (33%)
arm64 15 GB 12.1 GB 2.9 GB (19%)

Changes

  • Containerfile: Split into builder + runtime stages
  • Containerfile-cuda: Split into builder + runtime stages
  • .konflux/build-args-konflux.conf: BASE_IMAGEBUILDER_BASE_IMAGE + RUNTIME_BASE_IMAGE
  • .konflux/build-args-konflux-cuda.conf: BASE_IMAGEBUILDER_BASE_IMAGE + RUNTIME_BASE_IMAGE
  • .konflux/rpms.in.yaml: Added openssl-devel for cryptography sdist build
  • .konflux/rpms.lock.yaml: Regenerated with openssl-devel
  • cffi arch-specific wheel split for CUDA (cherry-picked fix)

Key details

  • Both stages use same WORKDIR /rag-content (venv shebangs are absolute paths)
  • UV_LINK_MODE=copy ensures venv is self-contained (no broken symlinks)
  • Build tools conditional on hermetic build (if [ -f /cachi2/cachi2.env ]) so GH Actions still works
  • /cachi2/ available in all stages via buildah --volume mount
  • Runtime stage includes shared libs (libpq, libxml2, libxslt, libjpeg-turbo, etc.) for compiled Python packages

Type of change

  • Refactoring
  • Configuration Update

Tools used to create PR

  • Assisted-by: Claude Code (Claude Opus 4.6)
  • Generated by: N/A

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

  • CPU multi-stage build verified in GH Actions (2.69 GB vs 4.67 GB)
  • CUDA multi-stage build verified in GH Actions (20.1 GB vs 29.8 GB)
  • Verified final images do not contain build tools

Summary by CodeRabbit

  • Chores

    • Updated Python dependency pins (including cryptography, click, lxml, openai/opentelemetry) and added cffi where applicable.
    • Refreshed binary wheel hashes and per-architecture wheel pins.
    • Added openssl-devel and other dev libs to RPM manifests and lockfiles.
  • New Features

    • Switched to multi-stage container builds separating build/runtime images for leaner runtime artifacts.
    • Improved CPU/CUDA architecture-specific dependency handling and wheel selection.

Review Change Stack

are-ces and others added 4 commits May 19, 2026 14:28
RHOAI only has up to 46.0.5. Pin override to 46.0.7 so uv resolves
from PyPI (sdist). Cryptography builds with Cargo which is already
in the build image RPMs.

Fixes all three open cryptography CVEs:
- CVE-2026-26007 (High): Subgroup attack on SECT curves (fixed 46.0.5)
- CVE-2026-34073 (Low): Incomplete DNS name constraint (fixed 46.0.6)
- CVE-2026-39892 (Medium): Buffer overflow via non-contiguous buffer (fixed 46.0.7)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
RHOAI rebuilds cffi with different hashes than PyPI. Strip cffi from
the universal wheel file and pin per-arch pulp URLs, same pattern as
aiohttp and markupsafe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Install cargo and rust RPMs for building cryptography from source.
Remove them after pip install to keep the final image clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split into builder (build tools, sdist compilation) and runtime
(clean image, no gcc/cargo/rust/dev libs). Builder stage is discarded
so build tools never appear in the final image.

This enables building packages from sdist (e.g. cryptography, pillow)
without bloating the runtime image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c5e2f963-93d3-4b25-9a07-3b8501241b68

📥 Commits

Reviewing files that changed from the base of the PR and between c4987ce and 3c4efbf.

📒 Files selected for processing (2)
  • .konflux/cuda/rpms.in.yaml
  • .konflux/cuda/rpms.lock.yaml

Walkthrough

Split base-image build args and convert Containerfile(s) to multi-stage builder/runtime; add cffi/pycparser to build sets, refresh many dependency pins and hashes (cryptography, lxml, click, numpy, etc.), add per-architecture cffi wheel pins, update scripts to generate arch-specific wheel entries, and update RPM and Tekton prefetch lists.

Changes

Build Infrastructure and Dependency Management

Layer / File(s) Summary
Build arguments and multi-stage Containerfile
.konflux/build-args-konflux.conf, Containerfile, Containerfile-cuda
Build arguments split from single BASE_IMAGE into BUILDER_BASE_IMAGE and RUNTIME_BASE_IMAGE. Containerfiles refactored into builder and runtime stages: builder installs Python build toolchain and creates a locked .venv; runtime installs runtime OS packages, copies the .venv, and runs bundle install.
Dependency pins and source/hash lock regeneration
.konflux/requirements-build.*.txt, .konflux/requirements.hashes.source.*.txt, .konflux/requirements.overrides.*.txt
Build requirements add cffi and pycparser, replace coherent-licensed, and bump cryptography to 46.0.7. Source/hash lock files regenerated (click 8.3.3→8.4.0, lxml 6.1.0→6.1.1, oci/openai/opentelemetry bumps, python-frontmatter/python-multipart), and zipp removal reflected. Override files pin cryptography==46.0.7.
Architecture-specific wheel handling and scripts
.konflux/requirements.hashes.wheel.*.txt, scripts/konflux_requirements.sh, scripts/konflux_requirements_cuda.sh
Remove cffi from universal wheel hashes and add per-architecture cffi wheel pins (x86_64 and aarch64, including CUDA/pypi variants). Scripts updated to strip universal cffi stanzas and emit hardcoded RHOAI/pulp direct-url pins with per-arch hashes.
Wheel hash updates (pypi CUDA/base)
.konflux/requirements.hashes.wheel.pypi.cuda.base.txt
Bumped wheel-only packages: click 8.3.3→8.4.0, docling-core 2.75.0→2.76.0, and regenerated numpy wheel hashes for 2.4.6.
Wheel hash files adjustments
.konflux/requirements.hashes.wheel.txt, .konflux/requirements.hashes.wheel.cuda.txt, .konflux/requirements.hashes.wheel.cpu.*.txt, .konflux/requirements.hashes.wheel.pypi.cuda.*.txt
Removed cffi and some runtime wheel pins from universal/CUDA wheel files and added per-arch cffi wheel pins for CPU and CUDA pypi variants.
RPM inputs and lock updates
.konflux/rpms.in.yaml, .konflux/rpms.lock.yaml
Added openssl-devel to RPM inputs; updated rpms.lock to add openssl-devel, bzip2-libs, and crypto-policies, bump glib2/glib2-devel evrs, and removed findutils entries for both architectures.
CUDA rpms expansion
.konflux/cuda/rpms.in.yaml, .konflux/cuda/rpms.lock.yaml
Added multiple -devel packages to CUDA rpms.in.yaml and inserted corresponding locked RPM records for aarch64 and x86_64 in the CUDA rpms.lock.
Tekton pipeline prefetch updates
.tekton/rag-tool-pull-request.yaml, .tekton/rag-tool-push.yaml
Updated Konflux prefetch binary.packages lists to remove cryptography and importlib-metadata from prefetched package strings.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Suggested reviewers

  • syedriko
  • tisnik
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Refactor Containerfile to multi-stage build' directly and accurately summarizes the main change—converting single-stage container builds into multi-stage builds across CPU and CUDA Containerfiles.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/konflux_requirements_cuda.sh`:
- Around line 392-408: The current block in scripts that matches cffi writes
both x86_64 and aarch64 wheels back into the shared WHEEL_HASH_FILE, causing pip
to try installing both arches; change it to remove cffi from the shared
"$WHEEL_HASH_FILE" and instead write arch-specific wheel files (e.g. a CUDA
x86_64 wheel file and a CUDA aarch64 wheel file) similar to the CPU script.
Modify the awk/shell logic that uses CFFI_CUDA_PULP_BASE, CFFI_CUDA_X86_WHEEL,
CFFI_CUDA_X86_SHA256, CFFI_CUDA_AARCH_WHEEL and CFFI_CUDA_AARCH_SHA256 so that
when matching /^cffi==|^cffi `@/` it prints nothing for the main WHEEL_HASH_FILE
(effectively stripping cffi) and writes the two arch-specific entries to
separate files (names analogous to requirements.hashes.wheel.cpu.x86_64.txt and
requirements.hashes.wheel.cpu.aarch64.txt), then mv the temp main file back into
"$WHEEL_HASH_FILE" and create/mv the temp arch files into their final
CUDA-specific filenames so Containerfile-cuda can include them by TARGETARCH.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea3b23b9-4266-4943-996c-23ebe5b4ec51

📥 Commits

Reviewing files that changed from the base of the PR and between 6246f18 and 2fef2de.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (17)
  • .konflux/build-args-konflux.conf
  • .konflux/requirements-build.cuda.txt
  • .konflux/requirements-build.txt
  • .konflux/requirements.hashes.source.cuda.txt
  • .konflux/requirements.hashes.source.txt
  • .konflux/requirements.hashes.wheel.cpu.aarch64.txt
  • .konflux/requirements.hashes.wheel.cpu.x86_64.txt
  • .konflux/requirements.hashes.wheel.cuda.txt
  • .konflux/requirements.hashes.wheel.pypi.cuda.base.txt
  • .konflux/requirements.hashes.wheel.txt
  • .konflux/requirements.overrides.cuda.txt
  • .konflux/requirements.overrides.txt
  • .tekton/rag-tool-pull-request.yaml
  • .tekton/rag-tool-push.yaml
  • Containerfile
  • scripts/konflux_requirements.sh
  • scripts/konflux_requirements_cuda.sh
💤 Files with no reviewable changes (1)
  • .konflux/requirements.hashes.wheel.txt

Comment thread scripts/konflux_requirements_cuda.sh
are-ces and others added 4 commits May 19, 2026 15:40
GH Actions builds use ubi-minimal without entitlement certs — packages
like swig are not available. Keep build tools behind the cachi2 check
as before; the multi-stage separation still ensures they don't appear
in the final image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cryptography's Rust code links against OpenSSL and needs the dev
headers + pkg-config file to compile from source.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cffi has arch-specific RHOAI wheels. Putting both in the universal
wheel file causes pip to fail with "not a supported wheel on this
platform". Strip from universal file and add to per-arch files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@are-ces
Copy link
Copy Markdown
Contributor Author

are-ces commented May 20, 2026

Image size drops from 4.6GB to 2.7GB with this approach, alternative approach to #190

@are-ces are-ces requested a review from syedriko May 20, 2026 12:31
Same pattern as CPU: builder stage has build tools (gcc, cargo, rust,
dev libs), runtime stage has only Python, CUDA libs, and runtime
shared libraries. Build tools never appear in the final image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Containerfile-cuda`:
- Line 3: The RUNTIME_BASE_IMAGE ARG currently defaults to a “-devel” variant
which keeps build tools in the final stage; change the default value of ARG
RUNTIME_BASE_IMAGE from nvcr.io/nvidia/cuda:12.9.1-devel-ubi9 to a non-devel
runtime (for example nvcr.io/nvidia/cuda:12.9.1-base-ubi9 or
nvcr.io/nvidia/cuda:12.9.1-runtime-ubi9) and ensure the final runtime stage uses
RUNTIME_BASE_IMAGE so the final image only includes CUDA runtime libraries, not
development toolchains.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b6cc29ec-7f6d-40d1-943b-7be2124bae45

📥 Commits

Reviewing files that changed from the base of the PR and between f91726c and 85ae9b6.

📒 Files selected for processing (2)
  • .konflux/build-args-konflux-cuda.conf
  • Containerfile-cuda

Comment thread Containerfile-cuda
ARG BASE_IMAGE=nvcr.io/nvidia/cuda:12.9.1-devel-ubi9
FROM ${BASE_IMAGE}
ARG BUILDER_BASE_IMAGE=nvcr.io/nvidia/cuda:12.9.1-devel-ubi9
ARG RUNTIME_BASE_IMAGE=nvcr.io/nvidia/cuda:12.9.1-devel-ubi9
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Runtime base image should not default to a -devel variant.

The RUNTIME_BASE_IMAGE defaults to nvcr.io/nvidia/cuda:12.9.1-devel-ubi9, which is a development image containing build tools, compilers, and development headers. This defeats the primary goal of the multi-stage build: removing build tools from the final runtime image to reduce size.

The runtime stage should default to a non-devel image (e.g., nvcr.io/nvidia/cuda:12.9.1-base-ubi9 or nvcr.io/nvidia/cuda:12.9.1-runtime-ubi9) that contains only the CUDA runtime libraries needed to execute applications, not build them.

🔧 Suggested fix
 ARG BUILDER_BASE_IMAGE=nvcr.io/nvidia/cuda:12.9.1-devel-ubi9
-ARG RUNTIME_BASE_IMAGE=nvcr.io/nvidia/cuda:12.9.1-devel-ubi9
+ARG RUNTIME_BASE_IMAGE=nvcr.io/nvidia/cuda:12.9.1-runtime-ubi9
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Containerfile-cuda` at line 3, The RUNTIME_BASE_IMAGE ARG currently defaults
to a “-devel” variant which keeps build tools in the final stage; change the
default value of ARG RUNTIME_BASE_IMAGE from
nvcr.io/nvidia/cuda:12.9.1-devel-ubi9 to a non-devel runtime (for example
nvcr.io/nvidia/cuda:12.9.1-base-ubi9 or nvcr.io/nvidia/cuda:12.9.1-runtime-ubi9)
and ensure the final runtime stage uses RUNTIME_BASE_IMAGE so the final image
only includes CUDA runtime libraries, not development toolchains.

are-ces and others added 3 commits May 21, 2026 09:47
Add libxml2-devel, libxslt-devel, libjpeg-turbo-devel, libtiff-devel,
freetype-devel, libwebp-devel, openssl-devel and their transitive deps
for building pillow and cryptography from sdist in CUDA hermetic builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Generated against registry.redhat.io/rhai/base-image-cuda-12.9-rhel9:3.3
with all dev libs for sdist builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <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.

1 participant