Skip to content

Commit 83c4262

Browse files
committed
RHAIENG-2645: add loop to retry package installation when it fails
1 parent e1df047 commit 83c4262

File tree

8 files changed

+299
-137
lines changed

8 files changed

+299
-137
lines changed

codeserver/ubi9-python-3.12/Dockerfile.cpu

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ ARG NODE_VERSION=22.18.0
2626
ARG CODESERVER_VERSION=v4.104.0
2727

2828
COPY ${CODESERVER_SOURCE_CODE}/get_code_server_rpm.sh .
29+
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/utils utils/
2930

3031
# create dummy file to ensure this stage is awaited before installing rpm
3132
RUN ./get_code_server_rpm.sh && touch /tmp/control
@@ -66,6 +67,8 @@ RUN touch /tmp/control
6667
####################
6768
FROM ${BASE_IMAGE} AS cpu-base
6869

70+
ARG CODESERVER_SOURCE_CODE=codeserver/ubi9-python-3.12
71+
6972
WORKDIR /opt/app-root/bin
7073

7174
# OS Packages needs to be installed as root
@@ -85,7 +88,8 @@ RUN dnf -y upgrade --refresh --nobest --skip-broken --nodocs --noplugins --setop
8588
# upgrade first to avoid fixable vulnerabilities end
8689

8790
# Install useful OS packages
88-
RUN dnf install -y perl mesa-libGL skopeo && dnf clean all && rm -rf /var/cache/yum
91+
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/utils utils/
92+
RUN --mount=type=cache,target=/var/cache/dnf ./utils/install_with_retry.sh dnf-install perl mesa-libGL skopeo
8993

9094
# (ARCH-ppc64le): since wheels are compiled from source, we need shared libs available at runtime
9195
RUN --mount=type=cache,from=whl-cache,source=/root/OpenBLAS,target=/OpenBlas,rw \
@@ -136,7 +140,7 @@ USER 0
136140
WORKDIR /opt/app-root/bin
137141

138142
# Install useful OS packages
139-
RUN dnf install -y jq git-lfs libsndfile && dnf clean all && rm -rf /var/cache/yum
143+
RUN --mount=type=cache,target=/var/cache/dnf ./utils/install_with_retry.sh dnf-install jq git-lfs libsndfile
140144

141145
# wait for rpm-base stage (rpm builds for ppc64le)
142146
COPY --from=rpm-base /tmp/control /dev/null
@@ -152,8 +156,6 @@ RUN --mount=type=cache,from=rpm-base,source=/tmp/,target=/code-server-rpm/,rw \
152156
dnf install -y cpio && dnf -y clean all && \
153157
cd / && rpm2cpio "/code-server-rpm/code-server-${CODESERVER_VERSION/v/}-${TARGETARCH}.rpm" | cpio -idmv
154158

155-
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/utils utils/
156-
157159
# Create and intall the extensions though build-time on a temporary directory. Later this directory will copied on the `/opt/app-root/src/.local/share/code-server/extensions` via run-code-server.sh file when it starts up.
158160
# https://coder.com/docs/code-server/FAQ#how-do-i-install-an-extension
159161
RUN mkdir -p /opt/app-root/extensions-temp && \
@@ -175,10 +177,10 @@ ENV NGINX_CONFIGURATION_PATH=${APP_ROOT}/etc/nginx.d \
175177
NGINX_PERL_MODULE_PATH=${APP_ROOT}/etc/perl
176178

177179
# Modules does not exist
178-
RUN INSTALL_PKGS="bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd" && \
179-
dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
180-
rpm -V $INSTALL_PKGS && \
181-
dnf -y clean all --enablerepo='*'
180+
RUN --mount=type=cache,target=/var/cache/dnf \
181+
DNF_EXTRA_OPTS="--setopt=tsflags=nodocs" ./utils/install_with_retry.sh dnf-install bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd \
182+
&& rpm -V bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd \
183+
&& dnf -y clean all --enablerepo='*'
182184

183185
# Configure httpd for CGI processing
184186
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/httpd/httpd.conf /etc/httpd/conf/httpd.conf

codeserver/ubi9-python-3.12/Dockerfile.konflux.cpu

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ ARG NODE_VERSION=22.18.0
2626
ARG CODESERVER_VERSION=v4.104.0
2727

2828
COPY ${CODESERVER_SOURCE_CODE}/get_code_server_rpm.sh .
29+
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/utils utils/
2930

3031
# create dummy file to ensure this stage is awaited before installing rpm
3132
RUN ./get_code_server_rpm.sh && touch /tmp/control
@@ -66,6 +67,8 @@ RUN touch /tmp/control
6667
####################
6768
FROM ${BASE_IMAGE} AS cpu-base
6869

70+
ARG CODESERVER_SOURCE_CODE=codeserver/ubi9-python-3.12
71+
6972
WORKDIR /opt/app-root/bin
7073

7174
# OS Packages needs to be installed as root
@@ -85,7 +88,8 @@ RUN dnf -y upgrade --refresh --nobest --skip-broken --nodocs --noplugins --setop
8588
# upgrade first to avoid fixable vulnerabilities end
8689

8790
# Install useful OS packages
88-
RUN dnf install -y perl mesa-libGL skopeo && dnf clean all && rm -rf /var/cache/yum
91+
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/utils utils/
92+
RUN --mount=type=cache,target=/var/cache/dnf ./utils/install_with_retry.sh dnf-install perl mesa-libGL skopeo
8993

9094
# (ARCH-ppc64le): since wheels are compiled from source, we need shared libs available at runtime
9195
RUN --mount=type=cache,from=whl-cache,source=/root/OpenBLAS,target=/OpenBlas,rw \
@@ -134,7 +138,7 @@ USER 0
134138
WORKDIR /opt/app-root/bin
135139

136140
# Install useful OS packages
137-
RUN dnf install -y jq git-lfs libsndfile && dnf clean all && rm -rf /var/cache/yum
141+
RUN --mount=type=cache,target=/var/cache/dnf ./utils/install_with_retry.sh dnf-install jq git-lfs libsndfile
138142

139143
# wait for rpm-base stage (rpm builds for ppc64le)
140144
COPY --from=rpm-base /tmp/control /dev/null
@@ -171,10 +175,10 @@ ENV APP_ROOT=/opt/app-root \
171175
NGINX_PERL_MODULE_PATH=${APP_ROOT}/etc/perl
172176

173177
# Modules does not exist
174-
RUN INSTALL_PKGS="bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd" && \
175-
dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
176-
rpm -V $INSTALL_PKGS && \
177-
dnf -y clean all --enablerepo='*'
178+
RUN --mount=type=cache,target=/var/cache/dnf \
179+
DNF_EXTRA_OPTS="--setopt=tsflags=nodocs" ./utils/install_with_retry.sh dnf-install bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd \
180+
&& rpm -V bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd \
181+
&& dnf -y clean all --enablerepo='*'
178182

179183
# Configure httpd for CGI processing
180184
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/httpd/httpd.conf /etc/httpd/conf/httpd.conf

codeserver/ubi9-python-3.12/get_code_server_rpm.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ if [[ "$ARCH" == "amd64" || "$ARCH" == "arm64" ||"$ARCH" == "ppc64le" ]]; then
3131
# install build dependencies
3232
# https://access.redhat.com/support/policy/updates/rhel-app-streams-life-cycle
3333
# https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/developing_c_and_cpp_applications_in_rhel_9/assembly_additional-toolsets-for-development-rhel-9_developing-applications#cpp-compatibility-in-gcc-toolset-14_gcc-toolset-14
34-
dnf install -y jq patch libtool rsync gettext gcc-toolset-14 krb5-devel libX11-devel
34+
./utils/install_with_retry.sh dnf-install jq patch libtool rsync gettext gcc-toolset-14 krb5-devel libX11-devel
3535

3636
# starting with node-22, c++20 is required
3737
. /opt/rh/gcc-toolset-14/enable

codeserver/ubi9-python-3.12/run-code-server.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env bash
22

3-
# Load bash libraries
3+
# Load bash libraries (only process.sh is needed at runtime; install_with_retry.sh is for build-only)
44
SCRIPT_DIR=$(dirname -- "$0")
5-
source ${SCRIPT_DIR}/utils/*.sh
5+
source "${SCRIPT_DIR}/utils/process.sh"
66

77
# Start nginx and httpd
88
run-nginx.sh &
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/bin/bash
2+
3+
# Shared install script with retry logic for dnf and texlive (install_pdf_deps).
4+
# Usage:
5+
# ./install_with_retry.sh dnf-install <package> [package ...]
6+
# ./install_with_retry.sh texlive-install
7+
8+
set -Eeuxo pipefail
9+
10+
readonly MAX_RETRIES="${MAX_RETRIES:-3}"
11+
readonly RETRY_DELAY="${RETRY_DELAY:-30}"
12+
13+
# Runs a command with retry logic.
14+
# Optional: set CLEANUP_CMD to a shell command (e.g. "dnf clean metadata") to run between retries.
15+
# Returns 0 on success, exits 1 after MAX_RETRIES failures.
16+
run_with_retry() {
17+
local retry_count=0
18+
while true; do
19+
if "$@"; then
20+
return 0
21+
fi
22+
retry_count=$((retry_count + 1))
23+
if [ "$retry_count" -ge "$MAX_RETRIES" ]; then
24+
echo "ERROR: Command failed after $MAX_RETRIES attempts" >&2
25+
exit 1
26+
fi
27+
echo "Command failed (attempt $retry_count/$MAX_RETRIES), retrying in ${RETRY_DELAY} seconds..."
28+
if [ -n "${CLEANUP_CMD:-}" ]; then
29+
$CLEANUP_CMD || true
30+
fi
31+
sleep "$RETRY_DELAY"
32+
done
33+
}
34+
35+
dnf_install() {
36+
local packages=("$@")
37+
if [ ${#packages[@]} -eq 0 ]; then
38+
echo "Usage: $0 dnf-install <package> [package ...]" >&2
39+
exit 1
40+
fi
41+
CLEANUP_CMD="dnf clean metadata" run_with_retry dnf install -y ${DNF_EXTRA_OPTS:-} "${packages[@]}"
42+
dnf clean all
43+
rm -rf /var/cache/yum
44+
}
45+
46+
texlive_install() {
47+
local script_dir
48+
script_dir="$(cd "$(dirname "$0")" && pwd)"
49+
CLEANUP_CMD= run_with_retry "$script_dir/install_pdf_deps.sh"
50+
}
51+
52+
main() {
53+
case "${1:-}" in
54+
dnf-install)
55+
shift
56+
dnf_install "$@"
57+
;;
58+
texlive-install)
59+
texlive_install
60+
;;
61+
*)
62+
echo "Usage: $0 {dnf-install|texlive-install} [args...]" >&2
63+
echo " dnf-install <package> [package ...] Install RPM packages with retry" >&2
64+
echo " texlive-install Run install_pdf_deps.sh with retry" >&2
65+
exit 1
66+
;;
67+
esac
68+
}
69+
70+
# Only run main when this script is executed directly (not when sourced by run-code-server.sh)
71+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
72+
main "$@"
73+
fi

jupyter/datascience/ubi9-python-3.12/Dockerfile.cpu

Lines changed: 65 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ RUN dnf -y upgrade --refresh --nobest --skip-broken --nodocs --noplugins --setop
5555
# upgrade first to avoid fixable vulnerabilities end
5656

5757
# Install useful OS packages
58-
RUN --mount=type=cache,target=/var/cache/dnf \
59-
echo "Building for architecture: ${TARGETARCH}" && \
60-
if [ "$TARGETARCH" = "s390x" ]; then \
61-
PACKAGES="perl mesa-libGL skopeo gcc gcc-c++ make openssl-devel autoconf automake libtool cmake python3-devel pybind11-devel openblas-devel unixODBC-devel"; \
62-
else \
63-
PACKAGES="perl mesa-libGL skopeo"; \
64-
fi && \
65-
echo "Installing: $PACKAGES" && \
66-
dnf install -y $PACKAGES && \
67-
dnf clean all && rm -rf /var/cache/yum
58+
COPY jupyter/utils utils/
59+
RUN --mount=type=cache,target=/var/cache/dnf /bin/bash <<'EOF'
60+
set -Eeuxo pipefail
61+
echo "Building for architecture: ${TARGETARCH}"
62+
if [ "$TARGETARCH" = "s390x" ]; then
63+
./utils/install_with_retry.sh dnf-install perl mesa-libGL skopeo gcc gcc-c++ make openssl-devel autoconf automake libtool cmake python3-devel pybind11-devel openblas-devel unixODBC-devel
64+
else
65+
./utils/install_with_retry.sh dnf-install perl mesa-libGL skopeo
66+
fi
67+
EOF
6868

6969
RUN if [ "$TARGETARCH" = "s390x" ]; then \
7070
# Install Rust and set up environment
@@ -114,51 +114,58 @@ WORKDIR /tmp/build-wheels
114114

115115
# Build pyarrow on ppc64le and s390x
116116
RUN --mount=type=cache,target=/root/.cache/pip \
117-
--mount=type=cache,target=/root/.cache/dnf \
118-
if [ "$TARGETARCH" = "ppc64le" ] || [ "$TARGETARCH" = "s390x" ]; then \
119-
# Install build dependencies (shared for pyarrow and onnx)
120-
dnf install -y cmake make gcc-c++ pybind11-devel wget && \
121-
dnf clean all && \
122-
# Build and collect pyarrow wheel
123-
git clone --depth 1 --branch "apache-arrow-17.0.0" https://github.com/apache/arrow.git && \
124-
cd arrow/cpp && \
125-
mkdir release && cd release && \
126-
cmake -DCMAKE_BUILD_TYPE=Release \
127-
-DCMAKE_INSTALL_PREFIX=/usr/local \
128-
-DARROW_PYTHON=ON \
129-
-DARROW_PARQUET=ON \
130-
-DARROW_ORC=ON \
131-
-DARROW_FILESYSTEM=ON \
132-
-DARROW_JSON=ON \
133-
-DARROW_CSV=ON \
134-
-DARROW_DATASET=ON \
135-
-DARROW_DEPENDENCY_SOURCE=BUNDLED \
136-
-DARROW_WITH_LZ4=OFF \
137-
-DARROW_WITH_ZSTD=OFF \
138-
-DARROW_WITH_SNAPPY=OFF \
139-
-DARROW_BUILD_TESTS=OFF \
140-
-DARROW_BUILD_BENCHMARKS=OFF \
141-
.. && \
142-
make -j$(nproc) VERBOSE=1 && \
143-
make install -j$(nproc) && \
144-
cd ../../python && \
145-
pip install --no-cache-dir -r requirements-build.txt && \
146-
PYARROW_WITH_PARQUET=1 \
147-
PYARROW_WITH_DATASET=1 \
148-
PYARROW_WITH_FILESYSTEM=1 \
149-
PYARROW_WITH_JSON=1 \
150-
PYARROW_WITH_CSV=1 \
151-
PYARROW_PARALLEL=$(nproc) \
152-
python setup.py build_ext --build-type=release --bundle-arrow-cpp bdist_wheel && \
153-
mkdir -p /tmp/wheels && \
154-
cp dist/pyarrow-*.whl /tmp/wheels/ && \
155-
chmod -R 777 /tmp/wheels && \
156-
# Ensure wheels directory exists and has content
157-
ls -la /tmp/wheels/; \
158-
else \
159-
# Create empty wheels directory for non-s390x
160-
mkdir -p /tmp/wheels; \
161-
fi
117+
--mount=type=cache,target=/root/.cache/dnf /bin/bash <<'EOF'
118+
set -Eeuxo pipefail
119+
120+
if [ "$TARGETARCH" = "ppc64le" ] || [ "$TARGETARCH" = "s390x" ]; then
121+
/opt/app-root/bin/utils/install_with_retry.sh dnf-install cmake make gcc-c++ pybind11-devel wget
122+
123+
# Build and collect pyarrow wheel
124+
git clone --depth 1 --branch "apache-arrow-17.0.0" https://github.com/apache/arrow.git
125+
cd arrow/cpp && mkdir release && cd release
126+
127+
cmake -DCMAKE_BUILD_TYPE=Release \
128+
-DCMAKE_INSTALL_PREFIX=/usr/local \
129+
-DARROW_PYTHON=ON \
130+
-DARROW_PARQUET=ON \
131+
-DARROW_ORC=ON \
132+
-DARROW_FILESYSTEM=ON \
133+
-DARROW_JSON=ON \
134+
-DARROW_CSV=ON \
135+
-DARROW_DATASET=ON \
136+
-DARROW_DEPENDENCY_SOURCE=BUNDLED \
137+
-DARROW_WITH_LZ4=OFF \
138+
-DARROW_WITH_ZSTD=OFF \
139+
-DARROW_WITH_SNAPPY=OFF \
140+
-DARROW_BUILD_TESTS=OFF \
141+
-DARROW_BUILD_BENCHMARKS=OFF \
142+
..
143+
144+
make -j$(nproc) VERBOSE=1
145+
make install -j$(nproc)
146+
147+
cd ../../python
148+
149+
pip install --no-cache-dir -r requirements-build.txt
150+
151+
PYARROW_WITH_PARQUET=1 \
152+
PYARROW_WITH_DATASET=1 \
153+
PYARROW_WITH_FILESYSTEM=1 \
154+
PYARROW_WITH_JSON=1 \
155+
PYARROW_WITH_CSV=1 \
156+
PYARROW_PARALLEL=$(nproc) \
157+
python setup.py build_ext --build-type=release --bundle-arrow-cpp bdist_wheel
158+
159+
mkdir -p /tmp/wheels
160+
cp dist/pyarrow-*.whl /tmp/wheels/
161+
chmod -R 777 /tmp/wheels
162+
# Ensure wheels directory exists and has content
163+
ls -la /tmp/wheels/;
164+
else
165+
# Create empty wheels directory for non-s390x
166+
mkdir -p /tmp/wheels;
167+
fi
168+
EOF
162169

163170
#######################################################
164171
# common-builder (for Power-only)
@@ -169,8 +176,7 @@ USER root
169176
RUN <<'EOF'
170177
set -Eeuxo pipefail
171178
if [ "${TARGETARCH}" = "ppc64le" ]; then
172-
dnf install -y gcc-toolset-13 cmake ninja-build git wget unzip
173-
dnf clean all
179+
/opt/app-root/bin/utils/install_with_retry.sh dnf-install gcc-toolset-13 cmake ninja-build git wget unzip
174180
else
175181
echo "Skipping common-builder package install on non-Power"
176182
fi
@@ -235,7 +241,7 @@ COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
235241
USER 0
236242

237243
# Dependencies for PDF export begin
238-
RUN ./utils/install_pdf_deps.sh
244+
RUN ./utils/install_with_retry.sh texlive-install
239245
ENV PATH="/usr/local/texlive/bin/linux:/usr/local/pandoc/bin:$PATH"
240246
# Dependencies for PDF export end
241247

@@ -272,8 +278,7 @@ WORKDIR /opt/app-root/bin
272278
USER root
273279

274280
# Install useful OS packages
275-
RUN dnf install -y jq unixODBC unixODBC-devel postgresql git-lfs libsndfile libxcrypt-compat && \
276-
dnf clean all && rm -rf /var/cache/yum
281+
RUN ./utils/install_with_retry.sh dnf-install jq unixODBC unixODBC-devel postgresql git-lfs libsndfile libxcrypt-compat
277282

278283
# Copy dynamically-linked mongocli built in earlier build stage
279284
COPY --from=mongocli-builder /tmp/mongocli /opt/app-root/bin/

0 commit comments

Comments
 (0)