Skip to content

Unified Container Build with Cache Mounts#318

Open
yairpod wants to merge 1 commit into
trusted-execution-clusters:mainfrom
yairpod:build_optimizing
Open

Unified Container Build with Cache Mounts#318
yairpod wants to merge 1 commit into
trusted-execution-clusters:mainfrom
yairpod:build_optimizing

Conversation

@yairpod

@yairpod yairpod commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Until now our builds have compiled the same files 4 times, As the builds were done in separate containers and had no access to the compilation objects from the other containers or previous builds. By Unifying the Build stage into one Container and interceding build caches we will prevent unnecessary work and achieve faster builds.

To check the effectiveness of these changes I used Opus 4.6 to write a build time benchmark script (see attached) and run a short test (also see attached).
The Highlights are these:
Without this PR the Operator container build was up to 30% faster the second build to the first build (~220 second time ~310 first time) , with the smaller gains for the other containers.
With the PR the difference is 70% (~110 second time ~305 first time) , but the other containers show a much larger improvement, as the speed up is about 90% (~30 seconds first build to ~3 in second build), also the build time of the first build of the other containers is reduced from the original code build time of ~220 seconds to ~30 in united build, is is due to the containers being build togather.

benchmark-builds.sh
results.csv
summary.txt

Summary by Sourcery

Unify container builds into a single cached builder stage that produces all Rust binaries and multi-stage images from one Containerfile.

New Features:

  • Provide individual distribution stages for operator, compute-pcrs, register-server, and attestation-key-register images from a unified build pipeline.
  • Define container entrypoints and exposed ports for register-server and attestation-key-register services.

Enhancements:

  • Enable shared cargo build caches to speed up repeat builds and avoid redundant compilation across images.
  • Extend the workspace members to include compute-pcrs, register-server, and attestation-key-register so they are built together with the operator.
  • Pre-build Rust dependencies in debug builds to reduce full rebuilds on source changes.
  • Clone reference-values into the build and include it in the compute-pcrs image.

Build:

  • Switch image builds in the Makefile to use a single Containerfile with multi-stage targets instead of separate per-component Containerfiles.
  • Set a default build_type of release and centralize binary copying into an /output directory in the builder stage.
  • Add a .containerignore file to control build context contents and improve container build efficiency.

Chores:

  • Remove legacy per-component Containerfiles now that all images are produced from the unified Containerfile.

@openshift-ci

openshift-ci Bot commented Jul 23, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: yairpod

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai

sourcery-ai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Reviewer's Guide

Unifies all Rust component builds into a single cached builder stage and reuses its artifacts across multiple final images, replacing per-component Containerfiles and aligning Makefile targets with multi-stage build targets.

File-Level Changes

Change Details Files
Unify Rust builds into a single builder stage with shared cargo caches and multi-binary compilation.
  • Set a default build_type=release argument for the container build.
  • Extend the unified builder stage to copy Cargo manifests and lib.rs stubs for all Rust components to enable dependency pre-build caching.
  • Update Cargo.toml members list to include all components and strip dev-dependencies from operator and register-server to stabilize dependency graph.
  • Introduce cargo build invocations in debug and release modes that compile operator, compute-pcrs, register-server, and attestation-key-register in one go using cache mounts for target and registry.
  • Collect built binaries into an /output directory for use by subsequent distribution stages.
Containerfile
Refactor distribution into multiple final images that all consume artifacts from the unified builder stage.
  • Add separate final stages for operator, compute-pcrs, register-server, and attestation-key-register based on the same Fedora runtime image.
  • Copy the appropriate binary from /output into each final image.
  • Include reference-values in the compute-pcrs image and configure ports and entrypoints for register-server and attestation-key-register.
Containerfile
Align Makefile image targets with the unified multi-stage Containerfile.
  • Change all image build commands to reference the root Containerfile instead of per-component Containerfiles.
  • Use --target to select the appropriate final stage (operator, compute-pcrs, register-server, attestation-key-register) for each image build.
Makefile
Remove per-component Containerfiles and add container build ignore configuration.
  • Delete attestation-key-register/Containerfile, compute-pcrs/Containerfile, and register-server/Containerfile in favor of the unified Containerfile.
  • Introduce a .containerignore file to exclude unnecessary files from the build context (contents not shown in the diff).
attestation-key-register/Containerfile
compute-pcrs/Containerfile
register-server/Containerfile
.containerignore

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="Containerfile" line_range="58-61" />
<code_context>
+      -p attestation-key-register \
+      $release_flag && \
+    mkdir -p /output && \
+    cp /build/target/${build_type}/operator /output/ && \
+    cp /build/target/${build_type}/compute-pcrs /output/ && \
+    cp /build/target/${build_type}/register-server /output/ && \
+    cp /build/target/${build_type}/attestation-key-register /output/
+
+# Distribution stages
</code_context>
<issue_to_address>
**issue (bug_risk):** The use of `build_type` directly in the target path can break builds for unexpected values.

This logic only works when `build_type` is `release` or `debug`: Cargo will still build to `debug` unless `--release` is used, but the `cp /build/target/${build_type}/...` paths will then be wrong for other values (e.g., `prod`) and the copy will fail. Either derive a `profile_dir` (`release`/`debug`) used consistently for both `cargo build` and copy paths, or validate `build_type` and fail early if it’s not one of the supported values.
</issue_to_address>

### Comment 2
<location path="Containerfile" line_range="32" />
<code_context>
     sed -i '/\[dev-dependencies\]/,$d' operator/Cargo.toml && \
+    sed -i '/\[dev-dependencies\]/,$d' register-server/Cargo.toml && \
     sed -i '/trusted-cluster-operator-test-utils/d' lib/Cargo.toml && \
+    git clone --depth 1 https://github.com/trusted-execution-clusters/reference-values && \
     make crds-rs

</code_context>
<issue_to_address>
**🚨 suggestion (security):** Unpinned `git clone` introduces non-reproducible builds and potential supply-chain risk.

Cloning `reference-values` without pinning a commit, tag, or at least a branch means builds can change unexpectedly as the upstream repo evolves and increases supply-chain risk. Please pin to a specific commit or tag (and ideally verify signatures/checksums) so the builder always uses a known, trusted revision and only changes when explicitly updated.

Suggested implementation:

```
ARG REFERENCE_VALUES_REV=v0.0.0

RUN sed -i 's/members = .*/members = ["lib", "operator", "compute-pcrs", "register-server", "attestation-key-register"]/' Cargo.toml && \
    sed -i '/\[dev-dependencies\]/,$d' operator/Cargo.toml && \
    sed -i '/\[dev-dependencies\]/,$d' register-server/Cargo.toml && \
    sed -i '/trusted-cluster-operator-test-utils/d' lib/Cargo.toml && \
    git clone --depth 1 --branch "${REFERENCE_VALUES_REV}" https://github.com/trusted-execution-clusters/reference-values && \

```

```
    make crds-rs

ARG build_type=release

```

1. Replace the placeholder `v0.0.0` in `REFERENCE_VALUES_REV` with a real, trusted tag (or branch) from `trusted-execution-clusters/reference-values`. Using a tag is preferable for immutability.
2. If you decide to pin to a specific commit instead of a tag, drop `--depth 1` and `--branch` and use `git checkout <commit-sha>` after cloning; this will still be reproducible but with a slightly larger clone.
3. Optionally, you can add checksum or signature verification (e.g., verifying a signed tag) after cloning if your build environment supports that, to further reduce supply-chain risk.
</issue_to_address>

### Comment 3
<location path="Containerfile" line_range="69" />
<code_context>
+
+FROM quay.io/fedora/fedora:43 AS compute-pcrs
+COPY --from=builder /output/compute-pcrs /usr/bin
+COPY --from=builder /build/reference-values /reference-values
+
+FROM quay.io/fedora/fedora:43 AS register-server
</code_context>
<issue_to_address>
**suggestion (performance):** Copying the entire `reference-values` repo into the compute-pcrs image may bloat the runtime and include unnecessary content.

The `/build/reference-values` path in the final image likely contains the entire cloned repo (including `.git` and other non-runtime assets). If `compute-pcrs` only needs specific data or subdirectories, please adjust the Dockerfile to copy just those artifacts from the builder stage to minimize image size and avoid bundling unnecessary files into the runtime image.

Suggested implementation:

```
    cp /build/target/${build_type}/compute-pcrs /output/ && \
    cp /build/target/${build_type}/register-server /output/ && \
    cp /build/target/${build_type}/attestation-key-register /output/ && \
    mkdir -p /output/reference-values && \
    cp -r /build/reference-values/runtime-data /output/reference-values

```

```
FROM quay.io/fedora/fedora:43 AS compute-pcrs
COPY --from=builder /output/compute-pcrs /usr/bin
COPY --from=builder /output/reference-values /reference-values

```

- Replace `/build/reference-values/runtime-data` with the actual path (subdirectory or artifact files) that `compute-pcrs` needs at runtime (for example, a `data/` or `artifacts/` directory, or specific JSON/YAML files).
- Ensure that whatever path you choose is produced/available in the builder stage (e.g., populated by `git clone`, build scripts, or other tooling) so the `cp -r` command succeeds.
- If `compute-pcrs` only requires individual files instead of a directory, adjust the `cp -r` command to copy just those files into `/output/reference-values` and keep the `COPY --from=builder /output/reference-values /reference-values` line unchanged.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread Containerfile Outdated
Comment thread Containerfile
sed -i '/\[dev-dependencies\]/,$d' operator/Cargo.toml && \
sed -i '/\[dev-dependencies\]/,$d' register-server/Cargo.toml && \
sed -i '/trusted-cluster-operator-test-utils/d' lib/Cargo.toml && \
git clone --depth 1 https://github.com/trusted-execution-clusters/reference-values && \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 suggestion (security): Unpinned git clone introduces non-reproducible builds and potential supply-chain risk.

Cloning reference-values without pinning a commit, tag, or at least a branch means builds can change unexpectedly as the upstream repo evolves and increases supply-chain risk. Please pin to a specific commit or tag (and ideally verify signatures/checksums) so the builder always uses a known, trusted revision and only changes when explicitly updated.

Suggested implementation:

ARG REFERENCE_VALUES_REV=v0.0.0

RUN sed -i 's/members = .*/members = ["lib", "operator", "compute-pcrs", "register-server", "attestation-key-register"]/' Cargo.toml && \
    sed -i '/\[dev-dependencies\]/,$d' operator/Cargo.toml && \
    sed -i '/\[dev-dependencies\]/,$d' register-server/Cargo.toml && \
    sed -i '/trusted-cluster-operator-test-utils/d' lib/Cargo.toml && \
    git clone --depth 1 --branch "${REFERENCE_VALUES_REV}" https://github.com/trusted-execution-clusters/reference-values && \

    make crds-rs

ARG build_type=release

  1. Replace the placeholder v0.0.0 in REFERENCE_VALUES_REV with a real, trusted tag (or branch) from trusted-execution-clusters/reference-values. Using a tag is preferable for immutability.
  2. If you decide to pin to a specific commit instead of a tag, drop --depth 1 and --branch and use git checkout <commit-sha> after cloning; this will still be reproducible but with a slightly larger clone.
  3. Optionally, you can add checksum or signature verification (e.g., verifying a signed tag) after cloning if your build environment supports that, to further reduce supply-chain risk.

Comment thread Containerfile Outdated
Until now our builds have compiled the same files 4 times,
As the builds were done in separate containers and had no access to the compilation objects from the other containers or previous builds.
By Unifying the Build stage into one Container and interceding build caches we will prevent unnecessary work and achieve faster builds.

Signed-off-by: Yair Podemsky <ypodemsk@redhat.com>
Assisted-by: Opus:4.6
@yairpod
yairpod force-pushed the build_optimizing branch from 964033f to 0b02453 Compare July 23, 2026 12:03
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