Skip to content

CherryPicked: [v2.11] build: standardize container image - #375

Merged
myakove merged 1 commit into
v2.11from
CherryPicked-container-image-improvements-MczpD
Mar 24, 2026
Merged

myakove merged 1 commit into
v2.11from
CherryPicked-container-image-improvements-MczpD

Conversation

@myakove

@myakove myakove commented Mar 24, 2026

Copy link
Copy Markdown
Collaborator

Cherry-pick from main branch, original PR: #371, PR owner: rgolangh

* Standardize container image

- Base the image on UBI 10.1
- Make the container image able to run with user 1001 so special security
  context change. Standard /app directory structure
- Lock the uv version for reproducible builds
- Ignore python caches

Signed-off-by: Roy Golan <rgolan@redhat.com>

* fix: pin UBI base image by digest and use explicit pip invocation

- Pin ubi-minimal:10.1 by sha256 digest for reproducible builds
- Use python3 -m pip instead of bare pip for explicit interpreter binding
- Remove redundant UV_CACHE_DIR (UV_NO_CACHE=1 already disables caching)
- Remove unnecessary cache cleanup step

* docs: add non-root container guidance for bind-mount permissions

Document that the container runs as UID 1001 and provide guidance
for writable bind mounts across podman rootless, rootful, and OpenShift.

* fix: add --no-run-if-empty flag to xargs in Dockerfile

Prevents build failure when no __pycache__ directories exist,
which is more likely with PYTHONDONTWRITEBYTECODE=1 set.

* fix: install uv via COPY --from instead of pip

Use COPY --from=ghcr.io/astral-sh/uv:latest for cleaner uv installation.
Drop python3-pip dependency since pip is no longer needed.

---------

Signed-off-by: Roy Golan <rgolan@redhat.com>
@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • main

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e301a6a0-c21a-47d9-9028-3bc9cf995e8b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch CherryPicked-container-image-improvements-MczpD

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.

@qodo-code-review

Copy link
Copy Markdown
ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Review Summary by Qodo

Standardize container image to UBI 10.1 with non-root support

✨ Enhancement 📝 Documentation

Grey Divider

Walkthroughs

Description
• Standardize container image to UBI 10.1 with reproducible builds
• Enable non-root container execution as UID 1001
• Replace package manager with microdnf and optimize dependencies
• Install uv via COPY --from for cleaner dependency management
• Add documentation for non-root container bind-mount permissions
Diagram
flowchart LR
  A["Fedora 41 Base Image"] -->|"Switch to"| B["UBI 10.1 by Digest"]
  C["dnf Package Manager"] -->|"Replace with"| D["microdnf"]
  E["pip Installation"] -->|"Replace with"| F["COPY --from uv"]
  B -->|"Add"| G["Non-root UID 1001"]
  H["Python Cache Files"] -->|"Disable with"| I["PYTHONDONTWRITEBYTECODE"]
  G -->|"Document"| J["Bind-mount Guidance"]
Loading

Grey Divider

File Changes

1. Dockerfile ✨ Enhancement +21/-16

Standardize to UBI 10.1 with non-root support

• Changed base image from Fedora 41 to UBI 10.1 pinned by SHA256 digest for reproducibility
• Replaced dnf with microdnf and optimized package dependencies
• Added environment variables for Python cache control and unbuffered output
• Installed uv via COPY --from instead of pip, removing python3-pip dependency
• Added non-root user support with UID 1001 and group permissions configuration
• Fixed xargs command with -r flag to handle missing __pycache__ directories
• Reorganized build steps for better layer caching and clarity

Dockerfile


2. README.md 📝 Documentation +8/-0

Document non-root container bind-mount guidance

• Added guidance for non-root container (UID 1001) bind-mount permissions
• Documented differences between podman rootless, rootful, and OpenShift environments
• Explained group-permission pattern used in Dockerfile for automatic OpenShift handling
• Added security note about environment variable exposure in process listings

README.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Mar 24, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Action required

1. Permissions set too early 🐞 Bug ⛯ Reliability
Description
The Dockerfile applies the OpenShift group-permission pattern (chgrp -R 0 && chmod -R g=u) before
running uv sync/git installs, so files created during dependency installation (e.g.,
venv/site-packages) won’t receive the intended group/permission normalization. This contradicts the
README’s claim that this pattern “handles this automatically” on OpenShift and can lead to
permission issues when running with OpenShift’s group-based access model.
Code

Dockerfile[R41-50]

+RUN mkdir -p ${APP_DIR}/output

-ARG OPENSHIFT_PYTHON_WRAPPER_COMMIT=''
-ARG OPENSHIFT_PYTHON_UTILITIES_COMMIT=''
+RUN chgrp -R 0 ${APP_DIR} && chmod -R g=u ${APP_DIR}
+
+USER 1001

RUN uv sync --locked\
-  && if [ -n "${OPENSHIFT_PYTHON_WRAPPER_COMMIT}" ]; then uv pip install git+https://github.com/RedHatQE/openshift-python-wrapper.git@$OPENSHIFT_PYTHON_WRAPPER_COMMIT; fi \
-  && if [ -n "${OPENSHIFT_PYTHON_UTILITIES_COMMIT}" ]; then uv pip install git+https://github.com/RedHatQE/openshift-python-utilities.git@$OPENSHIFT_PYTHON_UTILITIES_COMMIT; fi \
-  && find ${APP_DIR}/ -type d -name "__pycache__" -print0 | xargs -0 rm -rfv \
-  && rm -rf ${APP_DIR}/.cache
+  && if [ -n "${OPENSHIFT_PYTHON_WRAPPER_COMMIT}" ]; then uv pip install "git+https://github.com/RedHatQE/openshift-python-wrapper.git@${OPENSHIFT_PYTHON_WRAPPER_COMMIT}"; fi \
+  && if [ -n "${OPENSHIFT_PYTHON_UTILITIES_COMMIT}" ]; then uv pip install "git+https://github.com/RedHatQE/openshift-python-utilities.git@${OPENSHIFT_PYTHON_UTILITIES_COMMIT}"; fi \
+  && find ${APP_DIR}/ -type d -name "__pycache__" -print0 | xargs -0 -r rm -rfv
Evidence
The Dockerfile runs the recursive chgrp/chmod before switching to a non-root user and before
installing dependencies via uv sync and optional uv pip install ... steps; therefore, any files
created by those install steps are not covered by the recursive permission fix. The README
explicitly states that the Dockerfile’s group-permission pattern handles OpenShift automatically,
but with the current order it only applies to the source tree copied before dependency installation,
not to the newly created dependency/venv artifacts.

Dockerfile[41-50]
README.md[674-677]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The Dockerfile applies `chgrp -R 0 && chmod -R g=u` before `uv sync` and optional `uv pip install ...`. Files created during these install steps will not be permission-normalized, undermining the intended OpenShift group-access pattern described in the README.

### Issue Context
The README explicitly relies on the Dockerfile’s group-permission pattern for OpenShift. To make that statement true, permission normalization must occur after all filesystem-writing install steps.

### Fix Focus Areas
- Dockerfile[41-50]
 - Run `uv sync` (and the two optional `uv pip install ...` lines) while still root **or** run them first under the target user, then apply `chgrp -R 0 && chmod -R g=u` afterwards.
 - Ensure the final image still runs as non-root.
- README.md[674-677]
 - If behavior changes (e.g., final ordering/user changes), adjust wording to match the actual permission model.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Unpinned uv image tag 🐞 Bug ⛨ Security
Description
The Dockerfile copies uv from ghcr.io/astral-sh/uv:latest, making builds non-reproducible and
allowing the toolchain to change without any Dockerfile change. This increases supply-chain risk and
can cause unexpected build/runtime changes across rebuilds.
Code

Dockerfile[29]

+COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
Evidence
The base image is pinned by digest, but the uv source image is not (it uses :latest). This means
the resulting image contents depend on when the build runs rather than solely on the Dockerfile
contents.

Dockerfile[1-1]
Dockerfile[29-29]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The Dockerfile uses `ghcr.io/astral-sh/uv:latest` as a build source for `/uv` and `/uvx`. Using `latest` makes builds non-deterministic.

### Issue Context
This Dockerfile already pins the base image by digest; pinning `uv` similarly keeps the build reproducible.

### Fix Focus Areas
- Dockerfile[29-29]
 - Replace `ghcr.io/astral-sh/uv:latest` with a pinned version tag and digest (e.g., `ghcr.io/astral-sh/uv:<version>@sha256:<digest>`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@redhat-qe-bot

Copy link
Copy Markdown

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the OWNERS file in the repository root
  • Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are automatically applied based on changes
  • Issue Creation: Disabled for this repository
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified
  • Labels: All label categories are enabled (default configuration)

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (approvers only)
  • /hold cancel - Unblock PR merging
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)
  • /regenerate-welcome - Regenerate this welcome message

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /automerge - Enable automatic merging when all requirements are met (maintainers and approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest conventional-title - Validate commit message format
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. Status Checks: All required status checks must pass
  3. No Blockers: No wip, hold, has-conflicts labels and PR must be mergeable (no conflicts)
  4. Verified: PR must be marked as verified

📊 Review Process

Approvers and Reviewers

Approvers:

  • myakove
  • solenoci

Reviewers:

  • krcmarik
  • myakove
  • solenoci
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
  • automerge

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is automatically removed on each new commit
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

For more information, please refer to the project documentation or contact the maintainers.

@myakove

myakove commented Mar 24, 2026

Copy link
Copy Markdown
Collaborator Author

/lgtm
/approve
/verified

@myakove
myakove merged commit baae717 into v2.11 Mar 24, 2026
6 of 7 checks passed
@myakove
myakove deleted the CherryPicked-container-image-improvements-MczpD branch March 24, 2026 15:42
@redhat-qe-bot1

Copy link
Copy Markdown

New container for ghcr.io/redhatqe/mtv-api-tests:v2.11 published

Comment thread Dockerfile
Comment on lines +41 to +50
RUN mkdir -p ${APP_DIR}/output

ARG OPENSHIFT_PYTHON_WRAPPER_COMMIT=''
ARG OPENSHIFT_PYTHON_UTILITIES_COMMIT=''
RUN chgrp -R 0 ${APP_DIR} && chmod -R g=u ${APP_DIR}

USER 1001

RUN uv sync --locked\
&& if [ -n "${OPENSHIFT_PYTHON_WRAPPER_COMMIT}" ]; then uv pip install git+https://github.com/RedHatQE/openshift-python-wrapper.git@$OPENSHIFT_PYTHON_WRAPPER_COMMIT; fi \
&& if [ -n "${OPENSHIFT_PYTHON_UTILITIES_COMMIT}" ]; then uv pip install git+https://github.com/RedHatQE/openshift-python-utilities.git@$OPENSHIFT_PYTHON_UTILITIES_COMMIT; fi \
&& find ${APP_DIR}/ -type d -name "__pycache__" -print0 | xargs -0 rm -rfv \
&& rm -rf ${APP_DIR}/.cache
&& if [ -n "${OPENSHIFT_PYTHON_WRAPPER_COMMIT}" ]; then uv pip install "git+https://github.com/RedHatQE/openshift-python-wrapper.git@${OPENSHIFT_PYTHON_WRAPPER_COMMIT}"; fi \
&& if [ -n "${OPENSHIFT_PYTHON_UTILITIES_COMMIT}" ]; then uv pip install "git+https://github.com/RedHatQE/openshift-python-utilities.git@${OPENSHIFT_PYTHON_UTILITIES_COMMIT}"; fi \
&& find ${APP_DIR}/ -type d -name "__pycache__" -print0 | xargs -0 -r rm -rfv

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Permissions set too early 🐞 Bug ⛯ Reliability

The Dockerfile applies the OpenShift group-permission pattern (chgrp -R 0 && chmod -R g=u) before
running uv sync/git installs, so files created during dependency installation (e.g.,
venv/site-packages) won’t receive the intended group/permission normalization. This contradicts the
README’s claim that this pattern “handles this automatically” on OpenShift and can lead to
permission issues when running with OpenShift’s group-based access model.
Agent Prompt
### Issue description
The Dockerfile applies `chgrp -R 0 && chmod -R g=u` before `uv sync` and optional `uv pip install ...`. Files created during these install steps will not be permission-normalized, undermining the intended OpenShift group-access pattern described in the README.

### Issue Context
The README explicitly relies on the Dockerfile’s group-permission pattern for OpenShift. To make that statement true, permission normalization must occur after all filesystem-writing install steps.

### Fix Focus Areas
- Dockerfile[41-50]
  - Run `uv sync` (and the two optional `uv pip install ...` lines) while still root **or** run them first under the target user, then apply `chgrp -R 0 && chmod -R g=u` afterwards.
  - Ensure the final image still runs as non-root.
- README.md[674-677]
  - If behavior changes (e.g., final ordering/user changes), adjust wording to match the actual permission model.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants