|
| 1 | +# CPU Training Image Dockerfile |
| 2 | +# |
| 3 | +# FIPS-friendly Features: |
| 4 | +# - uv is used only in build stage (not shipped in runtime image) |
| 5 | +# - Build tools are isolated in intermediate stages |
| 6 | +# - Final image contains only runtime dependencies |
| 7 | + |
| 8 | +################################################################################ |
| 9 | +# Build Arguments |
| 10 | +################################################################################ |
| 11 | +ARG BASE_IMAGE=quay.io/opendatahub/odh-workbench-jupyter-minimal-cpu-py312-ubi9:2025b-v1.39 |
| 12 | +ARG PYTHON_VERSION=3.12 |
| 13 | + |
| 14 | +################################################################################ |
| 15 | +# Builder Stage - Install uv for dependency resolution |
| 16 | +################################################################################ |
| 17 | +FROM ${BASE_IMAGE} AS builder |
| 18 | + |
| 19 | +USER 0 |
| 20 | +WORKDIR /tmp/builder |
| 21 | + |
| 22 | +# Install latest version of uv in builder stage |
| 23 | +RUN pip install --no-cache-dir uv |
| 24 | + |
| 25 | +################################################################################ |
| 26 | +# Base Stage |
| 27 | +################################################################################ |
| 28 | +FROM ${BASE_IMAGE} AS base |
| 29 | + |
| 30 | +LABEL name="cpu:py312-torch290" \ |
| 31 | + summary="CPU Python 3.12 image with PyTorch 2.9.0" \ |
| 32 | + description="CPU image combining minimal Jupyter workbench and runtime ML stack (PyTorch 2.9.0) on UBI9" \ |
| 33 | + io.k8s.display-name="CPU Python 3.12 (Workbench + Runtime)" \ |
| 34 | + io.k8s.description="CPU image: Jupyter workbench by default; runtime when command provided." |
| 35 | + |
| 36 | +# Copy license file |
| 37 | +COPY LICENSE.md /licenses/cpu-license.md |
| 38 | + |
| 39 | +USER 0 |
| 40 | +WORKDIR /opt/app-root/bin |
| 41 | + |
| 42 | +################################################################################ |
| 43 | +# System Dependencies Stage |
| 44 | +################################################################################ |
| 45 | +FROM base AS system-deps |
| 46 | + |
| 47 | +USER 0 |
| 48 | +WORKDIR /opt/app-root/bin |
| 49 | + |
| 50 | +# Install build toolchain (from UBI repos) |
| 51 | +# - gcc, gcc-c++, make: C/C++ compilation tools |
| 52 | +# - python3-devel: Python headers for building native extensions |
| 53 | +# - cmake: Build system (required by some Python packages) |
| 54 | +# - git: Version control (some pip installs need it) |
| 55 | +RUN dnf install -y --setopt=install_weak_deps=False \ |
| 56 | + gcc \ |
| 57 | + gcc-c++ \ |
| 58 | + make \ |
| 59 | + python3-devel \ |
| 60 | + cmake \ |
| 61 | + git && dnf clean all && rm -rf /var/cache/dnf/* |
| 62 | + |
| 63 | +################################################################################ |
| 64 | +# Python Dependencies Stage |
| 65 | +################################################################################ |
| 66 | +FROM system-deps AS python-deps |
| 67 | + |
| 68 | +USER 0 |
| 69 | +WORKDIR /tmp/deps |
| 70 | + |
| 71 | +# Copy uv from builder stage (FIPS: uv only used during build, not in runtime) |
| 72 | +COPY --from=builder /opt/app-root/bin/uv /usr/local/bin/uv |
| 73 | + |
| 74 | +# Copy dependency files |
| 75 | +COPY --chown=1001:0 pyproject.toml pylock.toml ./ |
| 76 | + |
| 77 | +# Switch to user 1001 for pip installations |
| 78 | +USER 1001 |
| 79 | +WORKDIR /opt/app-root/src |
| 80 | + |
| 81 | +# Install main dependencies from pylock.toml using uv pip sync |
| 82 | +ENV UV_NO_CACHE=1 |
| 83 | +RUN uv pip sync --python-platform=linux --python-version=3.12 /tmp/deps/pylock.toml |
| 84 | +ENV UV_NO_CACHE= |
| 85 | + |
| 86 | +# Install kubeflow-sdk from Git (not in pylock.toml) |
| 87 | +# TODO: use aipcc index |
| 88 | +RUN pip install --retries 5 --timeout 300 --no-cache-dir \ |
| 89 | + "git+https://github.com/opendatahub-io/kubeflow-sdk@main" |
| 90 | + |
| 91 | +# Fix permissions for OpenShift |
| 92 | +ARG PYTHON_VERSION |
| 93 | +USER 0 |
| 94 | +RUN chmod -R g+w /opt/app-root/lib/python${PYTHON_VERSION}/site-packages \ |
| 95 | + && fix-permissions /opt/app-root -P |
| 96 | + |
| 97 | +# Clean up uv and build artifacts |
| 98 | +RUN rm -f /usr/local/bin/uv \ |
| 99 | + && rm -rf /tmp/deps \ |
| 100 | + && dnf remove -y gcc gcc-c++ cmake python3-devel \ |
| 101 | + && dnf clean all \ |
| 102 | + && rm -rf /var/cache/dnf/* |
| 103 | + |
| 104 | +################################################################################ |
| 105 | +# Final Stage - FIPS-friendly Runtime |
| 106 | +################################################################################ |
| 107 | +FROM ${BASE_IMAGE} AS final |
| 108 | + |
| 109 | +USER 0 |
| 110 | +WORKDIR /opt/app-root/src |
| 111 | + |
| 112 | +# Copy Python site-packages and CLI entry points from python-deps stage |
| 113 | +ARG PYTHON_VERSION |
| 114 | +COPY --from=python-deps /opt/app-root/lib/python${PYTHON_VERSION}/site-packages /opt/app-root/lib/python${PYTHON_VERSION}/site-packages |
| 115 | +COPY --from=python-deps /opt/app-root/bin /opt/app-root/bin |
| 116 | + |
| 117 | +# FIPS-friendly: Remove uv from final image |
| 118 | +RUN rm -f /opt/app-root/bin/uv |
| 119 | + |
| 120 | +# Copy license file |
| 121 | +COPY LICENSE.md /licenses/cpu-license.md |
| 122 | + |
| 123 | +# Copy entrypoint |
| 124 | +COPY --chmod=0755 entrypoint-universal.sh /usr/local/bin/entrypoint-universal.sh |
| 125 | + |
| 126 | +# Fix permissions for OpenShift (final stage) |
| 127 | +RUN fix-permissions /opt/app-root -P \ |
| 128 | + && chmod -R g+w /opt/app-root/lib/python${PYTHON_VERSION}/site-packages |
| 129 | + |
| 130 | +USER 1001 |
| 131 | +WORKDIR /opt/app-root/src |
| 132 | + |
| 133 | +ENTRYPOINT ["/usr/local/bin/entrypoint-universal.sh"] |
| 134 | +CMD ["start-notebook.sh"] |
| 135 | + |
0 commit comments