Skip to content

docker/unified: derive rootless image from root container - #644

Merged
mostlygeek merged 1 commit into
mainfrom
improve-unified-rootless
Apr 11, 2026
Merged

docker/unified: derive rootless image from root container#644
mostlygeek merged 1 commit into
mainfrom
improve-unified-rootless

Conversation

@mostlygeek

Copy link
Copy Markdown
Owner

Build the root image once, then derive the rootless variant from it using a small inline Dockerfile that adds the non-root user and chowns the writable directories. This halves the number of CI jobs (4 → 2) and eliminates the redundant full CUDA compilation for the rootless variant.

  • remove RUN_UID build arg from build-image.sh
  • derive rootless image inline after root build completes
  • collapse variant matrix out of unified-docker.yml
  • push both root and rootless tags in a single CI job

…DA build

Build the root image once, then derive the rootless variant from it using
a small inline Dockerfile that adds the non-root user and chowns the
writable directories. This halves the number of CI jobs (4 → 2) and
eliminates the redundant full CUDA compilation for the rootless variant.

- remove RUN_UID build arg from build-image.sh
- derive rootless image inline after root build completes
- collapse variant matrix out of unified-docker.yml
- push both root and rootless tags in a single CI job

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown

Walkthrough

This PR modifies the unified Docker image build workflow to eliminate the matrix.variant dimension and instead generates rootless image variants unconditionally during the push phase. The build script no longer uses RUN_UID as a build argument; instead, it builds a secondary rootless-tagged image using a heredoc Dockerfile that creates a non-root user.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
.github/workflows/unified-docker.yml
Removed matrix.variant dimension; updated build step to produce single base tag; replaced push logic to publish base tag plus date-suffixed variant, along with corresponding -rootless tags.
Build Script
docker/unified/build-image.sh
Removed RUN_UID build argument from initial build invocation; added rootless image build step using heredoc Dockerfile to create UID/GID 10001 user/group and apply ownership changes; updated output to display both base and rootless image tags.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: deriving rootless Docker images from the root container instead of building them separately.
Description check ✅ Passed The description is directly related to the changeset, explaining the rationale, specific implementation steps, and benefits of the modifications across both files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch improve-unified-rootless

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.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
.github/workflows/unified-docker.yml (1)

102-109: Define the base tag once.

DOCKER_IMAGE_TAG and BASE_TAG are the same value, but they're assembled in two different steps. Hoisting that to a job-level env would remove an easy build/push drift point the next time the tag format changes.

Also applies to: 121-121

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/unified-docker.yml around lines 102 - 109, Define a single
base tag env var at the job level (e.g., BASE_TAG) and use it wherever the image
tag is needed instead of constructing the same string in multiple steps;
specifically, replace the duplicated assembly of DOCKER_IMAGE_TAG in the step
that sets DOCKER_IMAGE_TAG and the separate BASE_TAG usage (referenced as
DOCKER_IMAGE_TAG and BASE_TAG in the diff) by hoisting BASE_TAG =
ghcr.io/mostlygeek/llama-swap:unified-${{ matrix.backend }} into the job env and
change DOCKER_IMAGE_TAG to reference that BASE_TAG (and update the other
occurrence at the second location that also constructs the tag).
docker/unified/build-image.sh (1)

257-275: Add one smoke test for the rootless tag before declaring success.

The verification block above only exercises ${DOCKER_IMAGE_TAG}. Since the workflow pushes ${ROOTLESS_TAG} immediately afterward, a permissions/runtime regression in the derived image would currently ship without CI ever running it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker/unified/build-image.sh` around lines 257 - 275, After building the
rootless image (ROOTLESS_TAG), run a small smoke test before printing success:
pull/run the image using the same runtime flags as used for ${DOCKER_IMAGE_TAG}
(e.g., docker run --rm -u 10001 or equivalent) and execute a lightweight command
that verifies startup and filesystem permissions (for example check that /app
and /models are accessible as UID 10001 and that the process can run a health
command); if the container fails or permission checks fail, exit non‑zero and
print the container logs. Insert this check immediately after the docker buildx
build --load -t "${ROOTLESS_TAG}" ... EOF block and before the final echo
"Rootless image built: ${ROOTLESS_TAG}" so the script only declares success when
the smoke test passes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/unified-docker.yml:
- Around line 102-109: Define a single base tag env var at the job level (e.g.,
BASE_TAG) and use it wherever the image tag is needed instead of constructing
the same string in multiple steps; specifically, replace the duplicated assembly
of DOCKER_IMAGE_TAG in the step that sets DOCKER_IMAGE_TAG and the separate
BASE_TAG usage (referenced as DOCKER_IMAGE_TAG and BASE_TAG in the diff) by
hoisting BASE_TAG = ghcr.io/mostlygeek/llama-swap:unified-${{ matrix.backend }}
into the job env and change DOCKER_IMAGE_TAG to reference that BASE_TAG (and
update the other occurrence at the second location that also constructs the
tag).

In `@docker/unified/build-image.sh`:
- Around line 257-275: After building the rootless image (ROOTLESS_TAG), run a
small smoke test before printing success: pull/run the image using the same
runtime flags as used for ${DOCKER_IMAGE_TAG} (e.g., docker run --rm -u 10001 or
equivalent) and execute a lightweight command that verifies startup and
filesystem permissions (for example check that /app and /models are accessible
as UID 10001 and that the process can run a health command); if the container
fails or permission checks fail, exit non‑zero and print the container logs.
Insert this check immediately after the docker buildx build --load -t
"${ROOTLESS_TAG}" ... EOF block and before the final echo "Rootless image built:
${ROOTLESS_TAG}" so the script only declares success when the smoke test passes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fcc9cb99-b193-4bc7-8f5b-3dbbefaf7f85

📥 Commits

Reviewing files that changed from the base of the PR and between d87f0ce and 60c124b.

📒 Files selected for processing (2)
  • .github/workflows/unified-docker.yml
  • docker/unified/build-image.sh

@mostlygeek
mostlygeek merged commit 7b2b827 into main Apr 11, 2026
3 checks passed
@mostlygeek
mostlygeek deleted the improve-unified-rootless branch April 11, 2026 05:59
celendis pushed a commit to celendis/llama-swap that referenced this pull request May 18, 2026
…#644)

Build the root image once, then derive the rootless variant from it
using a small inline Dockerfile that adds the non-root user and chowns
the writable directories. This halves the number of CI jobs (4 → 2) and
eliminates the redundant full CUDA compilation for the rootless variant.

- remove RUN_UID build arg from build-image.sh
- derive rootless image inline after root build completes
- collapse variant matrix out of unified-docker.yml
- push both root and rootless tags in a single CI job

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
mostlygeek added a commit that referenced this pull request May 26, 2026
Build the root image once, then derive the rootless variant from it
using a small inline Dockerfile that adds the non-root user and chowns
the writable directories. This halves the number of CI jobs (4 → 2) and
eliminates the redundant full CUDA compilation for the rootless variant.

- remove RUN_UID build arg from build-image.sh
- derive rootless image inline after root build completes
- collapse variant matrix out of unified-docker.yml
- push both root and rootless tags in a single CI job

Co-authored-by: Claude Sonnet 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.

1 participant