Skip to content

Commit 78118a8

Browse files
committed
RHAIENG-2852: Hermetic build for Jupyter tensorflow CUDA
- Hermetic Dockerfile.cuda / Dockerfile.konflux.cuda: Cachi2 gomod mongocli, prefetched RPMs, DNF openshift-clients, uv pip install --no-index from requirements.cuda.txt. - Symlink jupyter/tensorflow/ubi9-python-3.12/prefetch-input → repo prefetch-input. - Tekton push/PR: hermetic: true, prefetch-input params, amd64 m4xlarge, build/clair/ecosystem resourcing updates.
1 parent 131cde4 commit 78118a8

8 files changed

Lines changed: 238 additions & 127 deletions

.tekton/odh-workbench-jupyter-tensorflow-cuda-py312-ubi9-odh-main-pull-request.yaml

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,29 @@ spec:
3737
value: 5d
3838
- name: build-platforms
3939
value:
40-
- linux-d160-m2xlarge/amd64
41-
- linux-d160-m2xlarge/arm64
40+
- linux-d160-m4xlarge/amd64
4241
- name: dockerfile
4342
value: jupyter/tensorflow/ubi9-python-3.12/Dockerfile.cuda
4443
- name: path-context
4544
value: .
4645
- name: build-args-file
4746
value: jupyter/tensorflow/ubi9-python-3.12/build-args/cuda.conf
47+
# Hermetic build: no network during build; mongocli source from submodule, Go deps prefetched by Cachi2
48+
- name: hermetic
49+
value: 'true'
50+
- name: prefetch-input
51+
value:
52+
- path: prefetch-input/mongocli
53+
type: gomod
54+
- path: prefetch-input/odh
55+
type: rpm
56+
- path: prefetch-input/odh
57+
type: generic
58+
- path: jupyter/tensorflow/ubi9-python-3.12
59+
type: pip
60+
binary:
61+
arch: x86_64
62+
requirements_files: [requirements.cuda.txt]
4863
pipelineRef:
4964
name: multiarch-odh-main-combined-pipeline
5065
taskRunTemplate:
@@ -72,4 +87,20 @@ spec:
7287
limits:
7388
cpu: '8'
7489
memory: 32Gi
90+
- pipelineTaskName: clair-scan
91+
computeResources:
92+
requests:
93+
cpu: '4'
94+
memory: 8Gi
95+
limits:
96+
cpu: '4'
97+
memory: 8Gi
98+
- pipelineTaskName: ecosystem-cert-preflight-checks
99+
computeResources:
100+
requests:
101+
cpu: '4'
102+
memory: 8Gi
103+
limits:
104+
cpu: '4'
105+
memory: 8Gi
75106
status: {}

.tekton/odh-workbench-jupyter-tensorflow-cuda-py312-ubi9-odh-main-push.yaml

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,33 @@ spec:
2727
value: '{{revision}}'
2828
- name: output-image
2929
value: quay.io/opendatahub/odh-workbench-jupyter-tensorflow-cuda-py312-ubi9:{{revision}}
30+
- name: image-expires-after
31+
value: 5d
32+
- name: build-platforms
33+
value:
34+
- linux-d160-m4xlarge/amd64
3035
- name: dockerfile
3136
value: jupyter/tensorflow/ubi9-python-3.12/Dockerfile.cuda
3237
- name: build-args-file
3338
value: jupyter/tensorflow/ubi9-python-3.12/build-args/cuda.conf
3439
- name: path-context
3540
value: .
41+
# Hermetic build: no network during build; mongocli source from submodule, Go deps prefetched by Cachi2
42+
- name: hermetic
43+
value: 'true'
44+
- name: prefetch-input
45+
value:
46+
- path: prefetch-input/mongocli
47+
type: gomod
48+
- path: prefetch-input/odh
49+
type: rpm
50+
- path: prefetch-input/odh
51+
type: generic
52+
- path: jupyter/tensorflow/ubi9-python-3.12
53+
type: pip
54+
binary:
55+
arch: x86_64
56+
requirements_files: [requirements.cuda.txt]
3657
- name: additional-tags
3758
value:
3859
- '{{target_branch}}-{{revision}}'
@@ -55,22 +76,30 @@ spec:
5576
limits:
5677
cpu: '8'
5778
memory: 32Gi
79+
- name: build
80+
computeResources:
81+
requests:
82+
cpu: '4'
83+
memory: 8Gi
84+
limits:
85+
cpu: '4'
86+
memory: 8Gi
5887
- pipelineTaskName: clair-scan
5988
computeResources:
6089
requests:
61-
cpu: '8'
62-
memory: 32Gi
90+
cpu: '4'
91+
memory: 8Gi
6392
limits:
64-
cpu: '8'
65-
memory: 32Gi
93+
cpu: '4'
94+
memory: 8Gi
6695
- pipelineTaskName: ecosystem-cert-preflight-checks
6796
computeResources:
6897
requests:
69-
cpu: '8'
70-
memory: 32Gi
98+
cpu: '4'
99+
memory: 8Gi
71100
limits:
72-
cpu: '8'
73-
memory: 32Gi
101+
cpu: '4'
102+
memory: 8Gi
74103
pipelineRef:
75104
name: multiarch-odh-main-combined-pipeline
76105
taskRunTemplate:

jupyter/tensorflow/ubi9-python-3.12/Dockerfile.cuda

Lines changed: 64 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,34 @@ ARG TARGETARCH
55
#########################
66
ARG BASE_IMAGE
77

8-
### BEGIN mongocli-builder stage
98
######################################################
109
# mongocli-builder (build stage only, not published) #
10+
# Source: git submodule at prefetch-input/mongocli; #
11+
# Go deps prefetched by Konflux/Cachi2 (gomod). #
1112
######################################################
1213
FROM registry.access.redhat.com/ubi9/go-toolset:1.25.8-1775491036 AS mongocli-builder
1314

14-
ARG MONGOCLI_VERSION=2.0.4
15+
# OS Packages needs to be installed as root
16+
USER 0
17+
18+
# Mongocli source from repo submodule (no download; ProdSec/Conforma compliant)
19+
COPY prefetch-input/mongocli /tmp/mongocli-src
20+
WORKDIR /tmp/mongocli-src
1521

16-
WORKDIR /tmp/
22+
# [HERMETIC] Use prefetched Go modules from cachi2 (Konflux/Hermeto gomod). See
23+
# https://hermetoproject.github.io/hermeto/gomod/#using-fetched-dependencies
1724
RUN /bin/bash <<'EOF'
1825
set -Eeuxo pipefail
19-
curl -Lo mongodb-cli-mongocli-v${MONGOCLI_VERSION}.zip https://github.com/mongodb/mongodb-cli/archive/refs/tags/mongocli/v${MONGOCLI_VERSION}.zip
20-
unzip ./mongodb-cli-mongocli-v${MONGOCLI_VERSION}.zip
21-
cd ./mongodb-cli-mongocli-v${MONGOCLI_VERSION}/
26+
export GOCACHE=/cachi2/output/deps/gomod
27+
export GOMODCACHE=/cachi2/output/deps/gomod/pkg/mod
28+
export GOPATH=/cachi2/output/deps/gomod
29+
export GOPROXY=file:///cachi2/output/deps/gomod/pkg/mod/cache/download
2230
CGO_ENABLED=1 GOOS=linux go build -a -tags strictfipsruntime -o /tmp/mongocli ./cmd/mongocli/
2331
EOF
2432

25-
### END mongocli-builder stage
33+
# Other apps and tools installed as default user
34+
USER 1001
35+
2636

2737
####################
2838
# cuda-base #
@@ -34,42 +44,25 @@ WORKDIR /opt/app-root/bin
3444
# OS Packages needs to be installed as root
3545
USER 0
3646

37-
### BEGIN upgrade first to avoid fixable vulnerabilities
38-
RUN /bin/bash <<'EOF'
39-
# If we have a Red Hat subscription prepared, refresh it
40-
set -Eeuxo pipefail
41-
if command -v subscription-manager &> /dev/null; then
42-
subscription-manager identity &>/dev/null && subscription-manager refresh || echo "No identity, skipping refresh."
43-
fi
44-
EOF
45-
46-
RUN --mount=type=bind,source=base-images/utils/dnf-helper.sh,target=/utils/dnf-helper.sh,ro \
47-
/utils/dnf-helper.sh upgrade
47+
# [HERMETIC] Import GPG keys for prefetched RPM verification.
48+
# CentOS key imported only if prefetched (present in Dockerfile.cpu; may be absent in Konflux).
49+
RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official || true
50+
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
4851

49-
### END upgrade first to avoid fixable vulnerabilities
52+
# Bust layer cache when prefetched RPM set changes
53+
COPY prefetch-input/odh/rpms.lock.yaml /dev/null
54+
COPY prefetch-input/rhds/rpms.lock.yaml /dev/null
5055

51-
# Install useful OS packages
56+
# Install useful OS packages (versions follow UBI stream; pinning each would drift with point releases)
57+
# compat-openssl11 provides libcrypto.so.1.1 required for FIPS-compliance scanning.
58+
# hadolint ignore=DL3041
5259
RUN --mount=type=bind,source=base-images/utils/dnf-helper.sh,target=/utils/dnf-helper.sh,ro \
53-
/utils/dnf-helper.sh install perl mesa-libGL skopeo
60+
/utils/dnf-helper.sh install perl mesa-libGL skopeo compat-openssl11 openshift-clients
61+
RUN pip install --no-cache-dir --no-index --find-links /cachi2/output/deps/pip "micropipenv[toml]" "uv"
5462

5563
# Other apps and tools installed as default user
5664
USER 1001
5765

58-
### BEGIN Install micropipenv and uv to deploy packages from requirements.txt
59-
RUN pip install --no-cache-dir --extra-index-url https://pypi.org/simple -U "micropipenv[toml]==1.10.0" "uv==0.10.8"
60-
### END Install micropipenv and uv to deploy packages from requirements.txt
61-
62-
### BEGIN Install the oc client
63-
RUN /bin/bash <<'EOF'
64-
set -Eeuxo pipefail
65-
curl -L https://mirror.openshift.com/pub/openshift-v4/$(uname -m)/clients/ocp/stable/openshift-client-linux.tar.gz \
66-
-o /tmp/openshift-client-linux.tar.gz
67-
tar -xzvf /tmp/openshift-client-linux.tar.gz oc
68-
rm -f /tmp/openshift-client-linux.tar.gz
69-
EOF
70-
71-
### END Install the oc client
72-
7366
#########################
7467
# cuda-jupyter-minimal #
7568
#########################
@@ -78,14 +71,25 @@ FROM cuda-base AS cuda-jupyter-minimal
7871
ARG JUPYTER_REUSABLE_UTILS=jupyter/utils
7972
ARG MINIMAL_SOURCE_CODE=jupyter/minimal/ubi9-python-3.12
8073

74+
# OS Packages needs to be installed as root
75+
USER 0
76+
8177
WORKDIR /opt/app-root/bin
8278

79+
# [HERMETIC] Import GPG keys for prefetched RPM verification.
80+
# CentOS key imported only if prefetched (present in Dockerfile.cpu; may be absent in Konflux).
81+
RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-CentOS-Official || true
82+
RUN rpm --import /cachi2/output/deps/generic/RPM-GPG-KEY-EPEL-9 || true
83+
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
84+
85+
# Bust layer cache when prefetched RPM set changes
86+
COPY prefetch-input/odh/rpms.lock.yaml /dev/null
87+
COPY prefetch-input/rhds/rpms.lock.yaml /dev/null
88+
8389
COPY ${JUPYTER_REUSABLE_UTILS} utils/
8490

8591
COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
8692

87-
USER 0
88-
8993
### BEGIN Dependencies for PDF export
9094
RUN ./utils/install_pdf_deps.sh
9195
ENV PATH="/usr/local/texlive/bin/linux:/usr/local/pandoc/bin:$PATH"
@@ -105,25 +109,27 @@ FROM cuda-jupyter-minimal AS cuda-jupyter-datascience
105109

106110
ARG DATASCIENCE_SOURCE_CODE=jupyter/datascience/ubi9-python-3.12
107111

108-
WORKDIR /opt/app-root/bin
109-
110112
# OS Packages needs to be installed as root
111113
USER root
112114

115+
WORKDIR /opt/app-root/bin
116+
117+
# Bust layer cache when prefetched RPM set changes
118+
COPY prefetch-input/odh/rpms.lock.yaml /dev/null
119+
COPY prefetch-input/rhds/rpms.lock.yaml /dev/null
120+
113121
# Install useful OS packages
114122
RUN --mount=type=bind,source=base-images/utils/dnf-helper.sh,target=/utils/dnf-helper.sh,ro \
115-
/utils/dnf-helper.sh install jq unixODBC postgresql git-lfs libsndfile libxcrypt-compat
123+
/utils/dnf-helper.sh install jq unixODBC postgresql git-lfs libsndfile libxcrypt-compat protobuf
116124

117-
### BEGIN Copy mongocli from builder
118125
# Copy dynamically-linked mongocli built in earlier build stage
119-
COPY --from=mongocli-builder /tmp/mongocli /opt/app-root/bin/
120-
### END Copy mongocli from builder
126+
COPY --from=mongocli-builder /tmp/mongocli /opt/app-root/bin/mongocli
121127

122128
# Other apps and tools installed as default user
123129
USER 1001
124130

125131
# Copy Elyra setup to utils so that it's sourced at startup
126-
COPY ${DATASCIENCE_SOURCE_CODE}/setup-elyra.sh ${DATASCIENCE_SOURCE_CODE}/utils ./utils/
132+
COPY "${DATASCIENCE_SOURCE_CODE}/setup-elyra.sh" "${DATASCIENCE_SOURCE_CODE}/utils" ./utils/
127133

128134
WORKDIR /opt/app-root/src
129135

@@ -132,13 +138,15 @@ WORKDIR /opt/app-root/src
132138
############################
133139
FROM cuda-jupyter-datascience AS cuda-jupyter-tensorflow
134140

135-
ARG JUPYTER_REUSABLE_UTILS=jupyter/utils
136-
ARG DATASCIENCE_SOURCE_CODE=jupyter/datascience/ubi9-python-3.12
137141
ARG TENSORFLOW_SOURCE_CODE=jupyter/tensorflow/ubi9-python-3.12
138142
ARG PYLOCK_FLAVOR
139143

140144
WORKDIR /opt/app-root/bin
141145

146+
# Root required for uv pip install and runtime setup; switch to 1001 before WORKDIR at end
147+
# hadolint ignore=DL3002
148+
USER root
149+
142150
LABEL name="odh-notebook-cuda-jupyter-tensorflow-ubi9-python-3.12" \
143151
summary="Jupyter CUDA tensorflow notebook image for ODH notebooks" \
144152
description="Jupyter CUDA tensorflow notebook image with base Python 3.12 builder image based on UBI9 for ODH notebooks" \
@@ -149,21 +157,22 @@ LABEL name="odh-notebook-cuda-jupyter-tensorflow-ubi9-python-3.12" \
149157
io.openshift.build.source-location="https://github.com/opendatahub-io/notebooks/tree/main/jupyter/tensorflow/ubi9-python-3.12" \
150158
io.openshift.build.image="quay.io/opendatahub/workbench-images:cuda-jupyter-tensorflow-ubi9-python-3.12"
151159

152-
# Install Python packages and Jupyterlab extensions from requirements.txt
160+
# Install Python packages and Jupyterlab extensions from lockfile (requirements.cuda.txt used only for Cachi2 prefetch)
153161
COPY ${TENSORFLOW_SOURCE_CODE}/uv.lock.d/pylock.${PYLOCK_FLAVOR}.toml ./pylock.toml
162+
COPY ${TENSORFLOW_SOURCE_CODE}/requirements.${PYLOCK_FLAVOR}.txt ./requirements.txt
154163

155164
RUN /bin/bash <<'EOF'
156165
set -Eeuxo pipefail
157166

158-
### BEGIN Install software and packages
159167
echo "Installing software and packages"
160-
# Install Python packages from lockfile with hash verification
168+
# Install Python packages from lockfile (hermetic: use Cachi2 prefetched pip deps)
161169
# All dependencies are explicitly listed in pylock.toml (--no-deps)
162-
UV_NO_CACHE=true UV_LINK_MODE=copy UV_PREVIEW_FEATURES=pylock uv pip install \
170+
UV_NO_CACHE=true UV_LINK_MODE=copy UV_PREVIEW_FEATURES=pylock uv pip install --no-index \
163171
--strict --no-deps --no-config --no-progress \
164-
--require-hashes --compile-bytecode --index-strategy=unsafe-best-match \
165-
--requirements=./pylock.toml
166-
### END Install software and packages
172+
--compile-bytecode --index-strategy=unsafe-best-match \
173+
--no-verify-hashes \
174+
--find-links /cachi2/output/deps/pip \
175+
--requirements=./requirements.txt
167176

168177
# setup path for runtime configuration
169178
mkdir /opt/app-root/runtimes
@@ -182,4 +191,5 @@ chmod -R g+w /opt/app-root/lib/python3.12/site-packages
182191
fix-permissions /opt/app-root -P
183192
EOF
184193

194+
USER 1001
185195
WORKDIR /opt/app-root/src

0 commit comments

Comments
 (0)