Skip to content

feat(clp-package): Parameterize clp-package Docker image by Ubuntu codename; auto-detect host version. - #2273

Merged
junhaoliao merged 9 commits into
y-scope:mainfrom
junhaoliao:fix-noble
Jun 11, 2026
Merged

feat(clp-package): Parameterize clp-package Docker image by Ubuntu codename; auto-detect host version.#2273
junhaoliao merged 9 commits into
y-scope:mainfrom
junhaoliao:fix-noble

Conversation

@junhaoliao

@junhaoliao junhaoliao commented May 11, 2026

Copy link
Copy Markdown
Member

Description

Previously, the clp-package Docker image was hardcoded to ubuntu:jammy. Binaries built on an Ubuntu 24.04 (Noble) host (glibc 2.39) cannot run inside a Jammy container (glibc 2.35), causing task to fail on Noble hosts at the package-image stage. This affects both the C++ binaries (which require GLIBC_2.38) and Python packages with native extensions (e.g., _mysql_connector.so, psutil, greenlet) that are compiled on the host and linked against its glibc.

This PR makes two changes to tools/docker-images/clp-package/:

  1. Dockerfile — The base image is now parameterized via ARG UBUNTU_VERSION_CODENAME=jammy so FROM ubuntu:${UBUNTU_VERSION_CODENAME} resolves to the host-matching Ubuntu version. Additionally, userdel -r ubuntu is called before useradd clp-user to handle the default ubuntu user present in Noble cloud images (UID 1000), which would otherwise conflict with the clp-user UID.

  2. build.sh — Auto-detects the host's Ubuntu codename from /etc/os-release (VERSION_CODENAME) and passes it as --build-arg UBUNTU_VERSION_CODENAME=<codename>. Defaults to jammy when detection fails, preserving backward compatibility.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Scenario 1: Full build on Noble host

Task

Run task on an Ubuntu 24.04 (Noble) host to verify the build succeeds end-to-end.

Command

task

Output

task: [docker-images:package] ./build.sh
...
#4 [internal] load metadata for docker.io/library/ubuntu:noble
...
#30 exporting to image
#30 exporting layers done
...
task: [package] echo '0.12.1-dev' > '/home/ubuntu/workspace/clp/build/clp-package/VERSION'

Explanation

The Docker image build resolved the base image to ubuntu:noble, and the full task pipeline completed successfully on a Noble host.

Scenario 2: build.sh auto-detects the host Ubuntu codename

Task

Verify that build.sh reads the host's codename from /etc/os-release and passes it as a build-arg.

Command

bash -x tools/docker-images/clp-package/build.sh 2>&1 | grep -E "ubuntu_version|host_codename|UBUNTU_VERSION"

Output

+ ubuntu_version_codename=jammy
+ host_codename=noble
+ ubuntu_version_codename=noble
+ build_cmd+=(--build-arg "UBUNTU_VERSION_CODENAME=${ubuntu_version_codename}")
+ docker build --pull ... --build-arg UBUNTU_VERSION_CODENAME=noble ...

Explanation

The script defaults to jammy but correctly overrides with the host's VERSION_CODENAME=noble, ensuring the runtime image's glibc matches the host.

Scenario 3: Package Dockerfile builds with UBUNTU_VERSION_CODENAME=noble

Task

Verify the Dockerfile accepts --build-arg UBUNTU_VERSION_CODENAME=noble and pulls ubuntu:noble as the base image.

Command

docker build --check --build-arg UBUNTU_VERSION_CODENAME=noble -f tools/docker-images/clp-package/Dockerfile . 2>&1

Output

Check complete, no warnings found.

Explanation

Docker resolved the base image to docker.io/library/ubuntu:noble, confirming the build-arg is correctly substituted into the FROM directive.

Scenario 4: Package Dockerfile syntax check with default (jammy)

Task

Verify backward compatibility — the Dockerfile still works with the default jammy codename.

Command

docker build --check --build-arg UBUNTU_VERSION_CODENAME=jammy -f tools/docker-images/clp-package/Dockerfile . 2>&1

Output

Check complete, no warnings found.

Explanation

The Dockerfile passes syntax validation with the default jammy value, confirming no breaking change for existing builds.

Scenario 5: Container runs Noble and has correct user setup

Task

Verify the built container is based on Ubuntu Noble and the ubuntu user is removed while clp-user exists with UID 1000.

Command

docker run --rm <image> cat /etc/os-release | head -5
docker run --rm <image> id clp-user
docker run --rm <image> id ubuntu

Output

PRETTY_NAME="Ubuntu 24.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.4 LTS (Noble Numbat)"
VERSION_CODENAME=noble

uid=1000(clp-user) gid=1000(clp-user) groups=1000(clp-user)

id: 'ubuntu': no such user

Explanation

The container runs Ubuntu Noble; the default ubuntu user (present in Noble cloud images, UID 1000) was removed, and clp-user was created with UID 1000, avoiding the UID conflict that would otherwise occur.

Scenario 6: Start CLP package on Noble host

Task

Verify start-clp.sh starts all CLP services successfully.

Command

cd build/clp-package && ./sbin/start-clp.sh

Output

2026-05-11T03:36:54.358 INFO [controller] Setting up environment for compression_scheduler...
...
Container clp-package-ec9d-webui-1 Healthy
...
2026-05-11T03:37:06.327 INFO [controller] Started CLP.

Explanation

All services (database, queue, redis, results-cache, compression worker/scheduler, query worker/scheduler, api-server, webui, reducer, garbage-collector) started and became healthy.

Scenario 7: Compress logs

Task

Verify log compression works end-to-end in the Noble-based package.

Command

cd build/clp-package && ./sbin/compress.sh --timestamp-key timestamp ~/samples/postgresql.jsonl

Output

2026-05-11T03:55:03.410 INFO [compress] Compression job 5 submitted.
2026-05-11T03:55:05.415 INFO [compress] Compressed 389.02MB into 10.05MB (38.70x). Speed: 203.97MB/s.
2026-05-11T03:55:05.916 INFO [compress] Compression finished.
2026-05-11T03:55:05.916 INFO [compress] Compressed 389.02MB into 10.05MB (38.70x). Speed: 184.50MB/s.

Explanation

Compression completed successfully with a 38.70x compression ratio, confirming that the Noble-based runtime image correctly executes the CLP binaries built on the Noble host.

Scenario 8: Search logs

Task

Verify log search works end-to-end in the Noble-based package.

Command

cd build/clp-package && ./sbin/search.sh --count "error"

Output

(Container started, search completed, exit code 0)

Explanation

Search completed successfully, confirming the query pipeline works correctly with the Noble-based package.

Summary by CodeRabbit

  • Chores

    • Docker image build now supports selecting the Ubuntu base image at build time for greater flexibility.
    • Build script auto-detects the host Ubuntu codename and forwards it to the image build to improve compatibility.
    • CI workflow and build action updated to accept and pass the base image codename.
    • Image user initialization improved to detect and handle existing user ID conflicts, failing safely if unresolved.
  • Documentation

    • Build docs updated to clarify supported architectures and how host Ubuntu codename is used for runtime images.

@junhaoliao
junhaoliao requested a review from a team as a code owner May 11, 2026 04:00
@junhaoliao
junhaoliao requested a review from Bill-hbrhbr May 11, 2026 04:00
@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Docker build ARG UBUNTU_VERSION_CODENAME added and used as the base image tag; Dockerfile now removes any existing UID owner before creating the runtime user. build.sh detects host Ubuntu codename and passes it as a build-arg, and the GitHub Action/workflow expose and forward the same codename.

Changes

Docker Build Parameterization

Layer / File(s) Summary
Dockerfile base image parameterization
tools/docker-images/clp-package/Dockerfile
ARG UBUNTU_VERSION_CODENAME=jammy added and used in FROM ubuntu:${UBUNTU_VERSION_CODENAME} to make the base image configurable.
Dockerfile user initialization
tools/docker-images/clp-package/Dockerfile
Pre-useradd step added: lookup existing owner of ${UID} and run userdel --remove (build fails if deletion cannot be performed) before creating ${USER}.
Build script Ubuntu version detection and docs update
tools/docker-images/clp-package/build.sh, docs/src/dev-docs/building-package.md
Detect host Ubuntu codename from /etc/os-release (default jammy) and append --build-arg UBUNTU_VERSION_CODENAME=... to docker build; docs updated to note host-matching runtime image behaviour and architecture guidance.
GitHub Action input and workflow wiring
.github/actions/clp-build-runtime-image/action.yaml, .github/workflows/clp-artifact-build.yaml
Add required action input platform_version_codename and pass it as UBUNTU_VERSION_CODENAME in build-args; workflow invocation supplies platform_version_codename: "jammy".

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as clp-artifact-build workflow
  participant Action as clp-build-runtime-image action
  participant DockerCLI as docker build
  participant Dockerfile as Dockerfile (build-time)

  Workflow->>Action: invoke with platform_version_codename="jammy"
  Action->>DockerCLI: docker build --build-arg UBUNTU_VERSION_CODENAME=platform_version_codename
  DockerCLI->>Dockerfile: provide build-arg UBUNTU_VERSION_CODENAME
  Dockerfile->>Dockerfile: ARG UBUNTU_VERSION_CODENAME used in FROM and runtime setup
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 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 accurately and specifically describes the main change: parameterizing the Docker image by Ubuntu codename and adding auto-detection of the host version.
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

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.

@junhaoliao junhaoliao changed the title feat(package): Parameterize clp-package Docker image by Ubuntu codename; auto-detect host version. feat(clp-package): Parameterize clp-package Docker image by Ubuntu codename; auto-detect host version. May 11, 2026
@junhaoliao
junhaoliao requested a review from jackluo923 May 12, 2026 10:12
Comment thread tools/docker-images/clp-package/Dockerfile
USER="clp-user"

RUN useradd --uid ${UID} --shell /bin/bash --home-dir ${CLP_HOME} ${USER}
RUN userdel -r ubuntu 2>/dev/null || true \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of hardcoding ubuntu, we should resolve the username from the UID, using something like getent passwd "${UID}" | cut -d: -f1.

Also, is it possible to raise an error when encountering a UID conflict?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

sg. i tried to address it in 5af1885 . let me know if i understand correctly


ubuntu_version_codename="jammy"
if [[ -f /etc/os-release ]]; then
host_codename="$(. /etc/os-release && echo "$VERSION_CODENAME")"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Right now, task package builds a clp-package image using the same Ubuntu release as the host invoking the task command. However, I believe a 22.04 host should still be able to build a 24.04 clp-package image.

Should we expose the Ubuntu version codename as a Task argument or environment variable so the package target is not tied to the host release?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

dynamic ubuntu version detection on host should make more sense. the main reason why we want to avoid hardcoding a version of the ubuntu image is because whatever (Python wheels, glibc dependent binaries, etc.) a non-Jammy host builds do not run inside the Jammy-based image container.

the long-term plan is to migrate the base image from Ubuntu to Muslinux / Manylinux as @jackluo923 proposed. we (or whoever has bandwidth) can work on it in the next month. also, i think we shall explore setting up https://containers.dev/ too.

for now, this PR can unblock our developers to develop on different versions of Ubuntu hosts, without use of Ubuntu Jammy build containers

let me know what you think

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just realized that tools/docker-images/clp-package/Dockerfile copies built artifacts instead of building the package itself. Yes I agree we should keep host and host-built container image consistent.

@junhaoliao
junhaoliao requested a review from Bill-hbrhbr May 18, 2026 04:06

@Bill-hbrhbr Bill-hbrhbr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Need to update docs:

* An x86_64 Ubuntu 22.04 (Jammy) machine or container

Comment on lines 19 to 20
default: "amd64"
required: false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
default: "amd64"
required: false
required: true

Maybe open an issue to make this required?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@coderabbitai open an issue to track making the arch input required for .github/actions/clp-build-runtime-image. The issue should cover updating all current and future callers to pass arch explicitly, removing the default value, and verifying behavior for both amd64 and arm64. This is a follow-up cleanup and is out of scope for this PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh issue create \
  --repo "y-scope/clp" \
  --title "refactor(clp-build-runtime-image): make \`arch\` input required" \
  --assignee "junhaoliao" \
  --body "## Summary

The \`arch\` input for the \`.github/actions/clp-build-runtime-image\` composite action currently has a default value of \`\"amd64\"\`. This default masks potential misconfiguration and makes call sites less explicit about their intent.

## Tasks

- [ ] Remove the \`default: \"amd64\"\` from the \`arch\` input and set \`required: true\`.
- [ ] Audit all current callers of \`.github/actions/clp-build-runtime-image\` and update them to pass \`arch\` explicitly.
- [ ] Ensure any future callers are documented/required to pass \`arch\` explicitly.
- [ ] Verify the action behaves correctly for both \`amd64\` and \`arm64\`.

## Context

Raised during review of PR `#2273` (comment: https://github.com/y-scope/clp/pull/2273#discussion_r3268557767). This is a follow-up cleanup and was considered out of scope for that PR."

Length of output: 1091



@junhaoliao, I've opened #2301 to track this. It covers:

  • Removing the default: "amd64" and setting required: true on the arch input.
  • Auditing and updating all current callers to pass arch explicitly.
  • Documenting the requirement for future callers.
  • Verifying behaviour for both amd64 and arm64.


ubuntu_version_codename="jammy"
if [[ -f /etc/os-release ]]; then
host_codename="$(. /etc/os-release && echo "$VERSION_CODENAME")"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just realized that tools/docker-images/clp-package/Dockerfile copies built artifacts instead of building the package itself. Yes I agree we should keep host and host-built container image consistent.

Comment on lines 27 to 30
RUN existing_user="$(getent passwd "${UID}" | cut --delimiter=: --fields=1)" || true; \
[ -z "${existing_user}" ] || userdel --remove "${existing_user}" \
|| { echo "ERROR: Cannot delete user '${existing_user}' that occupies UID ${UID}"; exit 1; }
RUN useradd --uid ${UID} --shell /bin/bash --home-dir ${CLP_HOME} ${USER}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To make the user handling more coherent, we can maybe merge these two inside a single RUN. Your choice.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

makes sense

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/clp-artifact-build.yaml (1)

680-742: 🧹 Nitpick | 🔵 Trivial

Consider an explicit least-privilege permissions block (pre-existing).

zizmor flags this job as using default token permissions. Since the composite action pushes images to GHCR, an explicit job-level permissions: (e.g. contents: read, packages: write) would tighten the security posture. This is a pre-existing, repo-wide pattern and not introduced by this PR, so it's optional here.

🤖 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 @.github/workflows/clp-artifact-build.yaml around lines 680 - 742, The
package-image job uses default token permissions; add an explicit
least-privilege permissions block to the job to limit token scope (e.g.,
contents: read and packages: write). Edit the job named package-image and insert
a permissions: section under that job (near the strategy/matrix or runs-on)
specifying at minimum contents: read and packages: write so the composite action
that pushes to GHCR (./.github/actions/clp-build-runtime-image) has only the
needed rights; adjust other scopes if additional actions require them.
🤖 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.

Outside diff comments:
In @.github/workflows/clp-artifact-build.yaml:
- Around line 680-742: The package-image job uses default token permissions; add
an explicit least-privilege permissions block to the job to limit token scope
(e.g., contents: read and packages: write). Edit the job named package-image and
insert a permissions: section under that job (near the strategy/matrix or
runs-on) specifying at minimum contents: read and packages: write so the
composite action that pushes to GHCR (./.github/actions/clp-build-runtime-image)
has only the needed rights; adjust other scopes if additional actions require
them.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e5dde365-bb61-4043-95db-d893c123a368

📥 Commits

Reviewing files that changed from the base of the PR and between 1da7e74 and 45e57bb.

📒 Files selected for processing (4)
  • .github/actions/clp-build-runtime-image/action.yaml
  • .github/workflows/clp-artifact-build.yaml
  • docs/src/dev-docs/building-package.md
  • tools/docker-images/clp-package/Dockerfile

@junhaoliao
junhaoliao requested a review from Bill-hbrhbr June 11, 2026 06:58
@junhaoliao
junhaoliao merged commit 3144ca0 into y-scope:main Jun 11, 2026
29 checks passed
@junhaoliao
junhaoliao deleted the fix-noble branch June 11, 2026 17:20
@junhaoliao junhaoliao added this to the June 2026 milestone Jul 13, 2026
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