@@ -8,18 +8,68 @@ ARG BASE_IMAGE
88####################
99FROM ${BASE_IMAGE} AS cpu-base
1010
11+ ARG TARGETARCH
12+
1113WORKDIR /opt/app-root/bin
1214
1315# OS Packages needs to be installed as root
1416USER 0
1517
18+ ARG TARGETARCH
19+
1620# upgrade first to avoid fixable vulnerabilities begin
1721RUN dnf -y upgrade --refresh --best --nodocs --noplugins --setopt=install_weak_deps=0 --setopt=keepcache=0 \
1822 && dnf clean all -y
1923# upgrade first to avoid fixable vulnerabilities end
2024
2125# Install useful OS packages
22- RUN dnf install -y mesa-libGL skopeo libxcrypt-compat && dnf clean all && rm -rf /var/cache/yum
26+ RUN --mount=type=cache,target=/var/cache/dnf \
27+ echo "Building for architecture: ${TARGETARCH}" && \
28+ PACKAGES="mesa-libGL skopeo libxcrypt-compat" && \
29+ # Additional dev tools only for s390x
30+ if [ "$TARGETARCH" = "s390x" ]; then \
31+ PACKAGES="$PACKAGES gcc gcc-c++ make openssl-devel autoconf automake libtool cmake python3-devel pybind11-devel openblas-devel unixODBC-devel openssl zlib-devel"; \
32+ fi && \
33+ if [ "$TARGETARCH" = "ppc64le" ]; then \
34+ PACKAGES="$PACKAGES git gcc-toolset-13 make wget unzip rust cargo unixODBC-devel cmake ninja-build"; \
35+ fi && \
36+ if [ -n "$PACKAGES" ]; then \
37+ echo "Installing: $PACKAGES" && \
38+ dnf install -y $PACKAGES && \
39+ dnf clean all && rm -rf /var/cache/yum; \
40+ fi
41+
42+ RUN if [ "$TARGETARCH" = "ppc64le" ]; then \
43+ echo 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/' >> /etc/profile.d/ppc64le.sh && \
44+ echo 'export LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib:/usr/lib64:/usr/lib:$LD_LIBRARY_PATH' >> /etc/profile.d/ppc64le.sh && \
45+ echo 'export OPENBLAS_VERSION=0.3.30' >> /etc/profile.d/ppc64le.sh && \
46+ echo 'export ONNX_VERSION=1.19.0' >> /etc/profile.d/ppc64le.sh && \
47+ echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> /etc/profile.d/ppc64le.sh && \
48+ echo 'export GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1' >> /etc/profile.d/ppc64le.sh; \
49+ fi
50+
51+ # For s390x only, set ENV vars and install Rust
52+ RUN if [ "$TARGETARCH" = "s390x" ]; then \
53+ # Install Rust and set up environment
54+ mkdir -p /opt/.cargo && \
55+ export HOME=/root && \
56+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o rustup-init.sh && \
57+ chmod +x rustup-init.sh && \
58+ CARGO_HOME=/opt/.cargo HOME=/root ./rustup-init.sh -y --no-modify-path && \
59+ rm -f rustup-init.sh && \
60+ chown -R 1001:0 /opt/.cargo && \
61+ # Set environment variables
62+ echo 'export PATH=/opt/.cargo/bin:$PATH' >> /etc/profile.d/cargo.sh && \
63+ echo 'export CARGO_HOME=/opt/.cargo' >> /etc/profile.d/cargo.sh && \
64+ echo 'export GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1' >> /etc/profile.d/cargo.sh; \
65+ fi
66+
67+ # Set python alternatives only for s390x (not needed for other arches)
68+ RUN if [ "$TARGETARCH" = "s390x" ]; then \
69+ alternatives --install /usr/bin/python python /usr/bin/python3.12 1 && \
70+ alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1 && \
71+ python --version && python3 --version; \
72+ fi
2373
2474# Other apps and tools installed as default user
2575USER 1001
@@ -35,11 +85,118 @@ RUN curl -L https://mirror.openshift.com/pub/openshift-v4/$(uname -m)/clients/oc
3585 rm -f /tmp/openshift-client-linux.tar.gz
3686# Install the oc client end
3787
88+ ##############################
89+ # wheel-builder stage #
90+ # NOTE: Only used in s390x
91+ ##############################
92+ FROM cpu-base AS s390x-builder
93+
94+ ARG TARGETARCH
95+ USER 0
96+ WORKDIR /tmp/build-wheels
97+
98+ # Build pyarrow optimized for s390x
99+ RUN --mount=type=cache,target=/root/.cache/pip \
100+ --mount=type=cache,target=/root/.cache/dnf \
101+ if [ "$TARGETARCH" = "s390x" ]; then \
102+ # Install build dependencies (shared for pyarrow and onnx)
103+ dnf install -y cmake make gcc-c++ pybind11-devel wget && \
104+ dnf clean all && \
105+ # Build and collect pyarrow wheel
106+ git clone --depth 1 https://github.com/apache/arrow.git && \
107+ cd arrow/cpp && \
108+ mkdir release && cd release && \
109+ cmake -DCMAKE_BUILD_TYPE=Release \
110+ -DCMAKE_INSTALL_PREFIX=/usr/local \
111+ -DARROW_PYTHON=ON \
112+ -DARROW_PARQUET=ON \
113+ -DARROW_ORC=ON \
114+ -DARROW_FILESYSTEM=ON \
115+ -DARROW_JSON=ON \
116+ -DARROW_CSV=ON \
117+ -DARROW_DATASET=ON \
118+ -DARROW_DEPENDENCY_SOURCE=BUNDLED \
119+ -DARROW_WITH_LZ4=OFF \
120+ -DARROW_WITH_ZSTD=OFF \
121+ -DARROW_WITH_SNAPPY=OFF \
122+ -DARROW_BUILD_TESTS=OFF \
123+ -DARROW_BUILD_BENCHMARKS=OFF \
124+ .. && \
125+ make -j$(nproc) VERBOSE=1 && \
126+ make install -j$(nproc) && \
127+ cd ../../python && \
128+ pip install --no-cache-dir -r requirements-build.txt && \
129+ PYARROW_WITH_PARQUET=1 \
130+ PYARROW_WITH_DATASET=1 \
131+ PYARROW_WITH_FILESYSTEM=1 \
132+ PYARROW_WITH_JSON=1 \
133+ PYARROW_WITH_CSV=1 \
134+ PYARROW_PARALLEL=$(nproc) \
135+ python setup.py build_ext --build-type=release --bundle-arrow-cpp bdist_wheel && \
136+ mkdir -p /tmp/wheels && \
137+ cp dist/pyarrow-*.whl /tmp/wheels/ && \
138+ # Ensure wheels directory exists and has content
139+ ls -la /tmp/wheels/; \
140+ else \
141+ # Create empty wheels directory for non-s390x
142+ mkdir -p /tmp/wheels; \
143+ fi
144+
145+ ###################################
146+ # openblas builder stage for ppc64le
147+ ##################################
148+
149+ FROM cpu-base AS openblas-builder
150+ USER root
151+ WORKDIR /root
152+
153+ ARG TARGETARCH
154+
155+ ENV OPENBLAS_VERSION=0.3.30
156+
157+ RUN echo "openblas-builder stage TARGETARCH: ${TARGETARCH}"
158+
159+ # Download and build OpenBLAS
160+ RUN if [ "$TARGETARCH" = "ppc64le" ]; then \
161+ source /opt/rh/gcc-toolset-13/enable && \
162+ wget https://github.com/OpenMathLib/OpenBLAS/releases/download/v${OPENBLAS_VERSION}/OpenBLAS-${OPENBLAS_VERSION}.zip && \
163+ unzip OpenBLAS-${OPENBLAS_VERSION}.zip && cd OpenBLAS-${OPENBLAS_VERSION} && \
164+ make -j$(nproc) TARGET=POWER9 BINARY=64 USE_OPENMP=1 USE_THREAD=1 NUM_THREADS=120 DYNAMIC_ARCH=1 INTERFACE64=0; \
165+ else \
166+ echo "Not ppc64le, skipping OpenBLAS build" && mkdir -p /root/OpenBLAS-dummy; \
167+ fi
168+
169+ ###################################
170+ # onnx builder stage for ppc64le
171+ ###################################
172+
173+ FROM cpu-base AS onnx-builder
174+ USER root
175+ WORKDIR /root
176+
177+ ARG TARGETARCH
178+ ENV ONNX_VERSION=1.19.0
179+
180+ RUN echo "onnx-builder stage TARGETARCH: ${TARGETARCH}"
181+
182+ RUN if [ "$TARGETARCH" = "ppc64le" ]; then \
183+ source /opt/rh/gcc-toolset-13/enable && \
184+ git clone --recursive https://github.com/onnx/onnx.git && \
185+ cd onnx && git checkout v${ONNX_VERSION} && \
186+ git submodule update --init --recursive && \
187+ pip install -r requirements.txt && \
188+ export CMAKE_ARGS="-DPython3_EXECUTABLE=$(which python3.12)" && \
189+ pip wheel . -w /onnx_wheels; \
190+ else \
191+ echo "Not ppc64le, skipping ONNX build" && mkdir -p /onnx_wheels; \
192+ fi
193+
38194#######################
39195# runtime-datascience #
40196#######################
41197FROM cpu-base AS runtime-datascience
42198
199+ ARG TARGETARCH
43200ARG DATASCIENCE_SOURCE_CODE=runtimes/datascience/ubi9-python-3.12
44201
45202LABEL name="odh-notebook-runtime-datascience-ubi9-python-3.12" \
@@ -53,18 +210,60 @@ LABEL name="odh-notebook-runtime-datascience-ubi9-python-3.12" \
53210 io.openshift.build.image="quay.io/opendatahub/workbench-images:runtime-datascience-ubi9-python-3.12"
54211
55212WORKDIR /opt/app-root/bin
213+ USER 0
56214
57- # Install Python packages from requirements.txt
215+ # Install ppc64le-built wheels if available
216+ COPY --from=openblas-builder /root/OpenBLAS-* /openblas
217+ COPY --from=onnx-builder /onnx_wheels /tmp/onnx_wheels
218+
219+ RUN if [ "$TARGETARCH" = "ppc64le" ]; then \
220+ echo "Installing ppc64le ONNX wheels and OpenBLAS..." && \
221+ HOME=/root pip install /tmp/onnx_wheels/*.whl && \
222+ if [ -d "/openblas" ] && [ "$(ls -A /openblas 2>/dev/null)" ]; then \
223+ PREFIX=/usr/local make -C /openblas install; \
224+ fi && rm -rf /openblas /tmp/onnx_wheels; \
225+ else \
226+ echo "Skipping architecture-specific wheel installs for (${TARGETARCH})" && \
227+ rm -rf /tmp/wheels /openblas /tmp/onnx_wheels; \
228+ fi
229+
230+ USER 0
231+ # Copy wheels from build stage (s390x only)
232+ COPY --from=s390x-builder /tmp/wheels /tmp/wheels
233+ RUN if [ "$TARGETARCH" = "s390x" ]; then \
234+ pip install --no-cache-dir /tmp/wheels/*.whl && rm -rf /tmp/wheels; \
235+ else \
236+ echo "Skipping wheel install for $TARGETARCH"; \
237+ fi
238+
239+
240+ # Install Python packages from pylock.toml
58241COPY ${DATASCIENCE_SOURCE_CODE}/pylock.toml ./
59242# Copy Elyra dependencies for air-gapped enviroment
60243COPY ${DATASCIENCE_SOURCE_CODE}/utils ./utils/
61244
62- RUN echo "Installing softwares and packages" && \
63- # This may have to download and compile some dependencies, and as we don't lock requirements from `build-system.requires`,
64- # we often don't know the correct hashes and `--require-hashes` would therefore fail on non amd64, where building is common.
65- uv pip install --strict --no-deps --no-cache --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml && \
66- # Fix permissions to support pip in Openshift environments \
245+ RUN --mount=type=cache,target=/root/.cache/pip \
246+ echo "Installing softwares and packages" && \
247+ if [ "$TARGETARCH" = "ppc64le" ]; then \
248+ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig; \
249+ export LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib:/usr/lib64:/usr/lib:$LD_LIBRARY_PATH; \
250+ GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 \
251+ pip install ml-dtypes && \
252+ uv pip install --strict --no-deps --no-cache --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml; \
253+ elif [ "$TARGETARCH" = "s390x" ]; then \
254+ # For s390x, we need special flags and environment variables for building packages
255+ GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 \
256+ CFLAGS="-O3" CXXFLAGS="-O3" \
257+ uv pip install --strict --no-deps --no-cache --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml; \
258+ else \
259+ # This may have to download and compile some dependencies, and as we don't lock requirements from `build-system.requires`,
260+ # we often don't know the correct hashes and `--require-hashes` would therefore fail on non amd64, where building is common.
261+ uv pip install --strict --no-deps --no-cache --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml; \
262+ fi && \
263+ # Fix permissions to support pip in Openshift environments
67264 chmod -R g+w /opt/app-root/lib/python3.12/site-packages && \
68265 fix-permissions /opt/app-root -P
69266
267+ USER 1001
268+
70269WORKDIR /opt/app-root/src
0 commit comments