|
| 1 | +ARG TARGETARCH |
| 2 | + |
| 3 | +######################### |
| 4 | +# configuration args # |
| 5 | +######################### |
| 6 | +ARG BASE_IMAGE |
| 7 | + |
| 8 | +# External image alias for UBI repository configuration |
| 9 | +FROM registry.access.redhat.com/ubi9/ubi AS ubi-repos |
| 10 | + |
| 11 | +#################### |
| 12 | +# cpu-base # |
| 13 | +#################### |
| 14 | +FROM ${BASE_IMAGE} AS cpu-base |
| 15 | + |
| 16 | +WORKDIR /opt/app-root/bin |
| 17 | + |
| 18 | +# OS Packages needs to be installed as root |
| 19 | +USER root |
| 20 | + |
| 21 | +# Inject the official UBI 9 repository configuration into the AIPCC base image. |
| 22 | +# The Quay-based AIPCC image is "repo-less" by default (https://gitlab.com/redhat/rhel-ai/core/base-images/app#repositories), so dnf cannot upgrade or install packages. |
| 23 | +# By copying ubi.repo from the public UBI 9 image, we enable package management for upgrades and installations. |
| 24 | +COPY --from=ubi-repos /etc/yum.repos.d/ubi.repo /etc/yum.repos.d/ubi.repo |
| 25 | +COPY --from=ubi-repos /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release |
| 26 | + |
| 27 | +### BEGIN upgrade first to avoid fixable vulnerabilities |
| 28 | +# If we have a Red Hat subscription prepared, refresh it |
| 29 | +RUN /bin/bash <<'EOF' |
| 30 | +set -Eeuxo pipefail |
| 31 | +if command -v subscription-manager &> /dev/null; then |
| 32 | + subscription-manager identity &>/dev/null && subscription-manager refresh || echo "No identity, skipping refresh." |
| 33 | +fi |
| 34 | +EOF |
| 35 | + |
| 36 | +# Problem: The operation would result in removing the following protected packages: systemd |
| 37 | +# (try to add '--allowerasing' to command line to replace conflicting packages or '--skip-broken' to skip uninstallable packages) |
| 38 | +# Solution: --best --skip-broken does not work either, so use --nobest |
| 39 | +RUN /bin/bash <<'EOF' |
| 40 | +set -Eeuxo pipefail |
| 41 | +dnf -y upgrade --refresh --nobest --skip-broken --nodocs --noplugins --setopt=install_weak_deps=0 --setopt=keepcache=0 |
| 42 | +dnf clean all -y |
| 43 | +EOF |
| 44 | + |
| 45 | +### END upgrade first to avoid fixable vulnerabilities |
| 46 | + |
| 47 | +# Install useful OS packages |
| 48 | +# remove skopeo, CVE-2025-4674 |
| 49 | +RUN dnf install -y perl mesa-libGL && dnf clean all && rm -rf /var/cache/yum |
| 50 | + |
| 51 | +# Other apps and tools installed as default user |
| 52 | +USER 1001 |
| 53 | + |
| 54 | +### BEGIN Install micropipenv and uv to deploy packages from requirements.txt |
| 55 | +RUN pip install --no-cache-dir --extra-index-url https://pypi.org/simple -U "micropipenv[toml]==1.9.0" "uv==0.8.12" |
| 56 | +### END Install micropipenv and uv to deploy packages from requirements.txt |
| 57 | + |
| 58 | +WORKDIR /opt/app-root/src |
| 59 | + |
| 60 | +##################### |
| 61 | +# cpu-rstudio # |
| 62 | +##################### |
| 63 | +FROM cpu-base AS cpu-rstudio |
| 64 | + |
| 65 | +ARG RSTUDIO_SOURCE_CODE=rstudio/rhel9-python-3.12 |
| 66 | +ARG TARGETARCH |
| 67 | + |
| 68 | +WORKDIR /opt/app-root/bin |
| 69 | + |
| 70 | +# TODO THIS SHOULD BE REMOVED |
| 71 | +# Access the client's secret for the subscription manager from the environment variable |
| 72 | +ARG SECRET_DIR=/opt/app-root/src/.sec |
| 73 | +ARG SERVERURL_DEFAULT="" |
| 74 | +ARG BASEURL_DEFAULT="" |
| 75 | +# TILL HERE |
| 76 | + |
| 77 | +LABEL name="rhoai/odh-workbench-rstudio-minimal-cpu-py312-rhel9" \ |
| 78 | + com.redhat.component="odh-workbench-rstudio-minimal-cpu-py312-rhel9" \ |
| 79 | + summary="RStudio Server CPU image with python 3.12 based on Red Hat Enterprise Linux 9" \ |
| 80 | + description="RStudio Server CPU image with python 3.12 based on Red Hat Enterprise Linux 9" \ |
| 81 | + maintainer="Red Hat AI Notebooks Team" \ |
| 82 | + io.k8s.display-name="RStudio Server CPU image with python 3.12 based on Red Hat Enterprise Linux 9" \ |
| 83 | + io.k8s.description="RStudio Server CPU image with python 3.12 based on Red Hat Enterprise Linux 9" \ |
| 84 | + authoritative-source-url="https://github.com/opendatahub-io/notebooks" \ |
| 85 | + io.openshift.build.commit.ref="main" \ |
| 86 | + io.openshift.build.source-location="https://github.com/opendatahub-io/notebooks/tree/main/rstudio/rhel9-python-3.12" \ |
| 87 | + io.openshift.build.image="quay.io/opendatahub/workbench-images:rstudio-rhel9-python-3.12" |
| 88 | + |
| 89 | +USER 0 |
| 90 | + |
| 91 | +ENV R_VERSION=4.5.1 |
| 92 | + |
| 93 | +# Install R |
| 94 | +RUN /bin/bash <<'EOF' |
| 95 | +set -Eeuxo pipefail |
| 96 | +dnf install -y dnf-plugins-core |
| 97 | +if command -v subscription-manager &> /dev/null; then |
| 98 | + subscription-manager repos --enable codeready-builder-for-rhel-9-x86_64-rpms |
| 99 | +else |
| 100 | + dnf config-manager --set-enabled crb |
| 101 | +fi |
| 102 | +dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm |
| 103 | +INSTALL_PKGS="R-core R-core-devel R-java R-Rcpp R-highlight \ |
| 104 | +R-littler R-littler-examples openssl-libs compat-openssl11" |
| 105 | +dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS |
| 106 | +echo 'options(repos = c(CRAN = "https://cran.rstudio.com/"), download.file.method = "libcurl")' >> /usr/lib64/R/etc/Rprofile.site |
| 107 | +(umask 002;touch /usr/lib64/R/etc/Renviron.site) |
| 108 | +dnf -y clean all --enablerepo='*' |
| 109 | +EOF |
| 110 | + |
| 111 | +# set R library to default (used in install.r from littler) |
| 112 | +ENV LIBLOC=/usr/lib64/R/library |
| 113 | +ENV R_LIBS_USER=/opt/app-root/bin/Rpackages/4.5 |
| 114 | + |
| 115 | +RUN /bin/bash <<'EOF' |
| 116 | +set -Eeuxo pipefail |
| 117 | +chmod -R a+w ${LIBLOC} |
| 118 | +# create User R Library path |
| 119 | +mkdir -p ${R_LIBS_USER} |
| 120 | +chmod -R a+w ${R_LIBS_USER} |
| 121 | +EOF |
| 122 | + |
| 123 | +WORKDIR /tmp/ |
| 124 | +COPY /rstudio/utils /tmp/utils |
| 125 | + |
| 126 | +# Install RStudio |
| 127 | +ARG RSTUDIO_RPM=rstudio-server-rhel-2025.09.0-387-x86_64.rpm |
| 128 | +RUN /bin/bash <<'EOF' |
| 129 | +set -Eeuxo pipefail |
| 130 | +wget --progress=dot:giga https://download2.rstudio.org/server/rhel9/x86_64/${RSTUDIO_RPM} |
| 131 | +dnf install -y ${RSTUDIO_RPM} |
| 132 | +rm ${RSTUDIO_RPM} |
| 133 | +dnf -y clean all --enablerepo='*' |
| 134 | +# Specific RStudio config and fixes |
| 135 | +chmod 1777 /var/run/rstudio-server |
| 136 | +mkdir -p /usr/share/doc/R |
| 137 | +# package installation |
| 138 | +# install necessary texlive-framed package to make Knit R markup to PDF rendering possible |
| 139 | +dnf install -y libgit2-devel.x86_64 libcurl-devel harfbuzz-devel.x86_64 fribidi-devel.x86_64 cmake "flexiblas-*" texlive-framed |
| 140 | +# install npm to run cve_remediation script |
| 141 | +dnf install -y npm |
| 142 | +dnf clean all |
| 143 | +rm -rf /var/cache/yum |
| 144 | +(cd /tmp/utils && ./cve_remediation.sh) |
| 145 | +EOF |
| 146 | + |
| 147 | +COPY ${RSTUDIO_SOURCE_CODE}/rsession.conf /etc/rstudio/rsession.conf |
| 148 | + |
| 149 | +# # Install R packages |
| 150 | +# # https://cran.r-project.org/web/packages |
| 151 | +# COPY ${RSTUDIO_SOURCE_CODE}/install_packages.R ./ |
| 152 | +# RUN /bin/bash <<'EOF' |
| 153 | +# set -Eeuxo pipefail |
| 154 | +# R -f ./install_packages.R |
| 155 | +# rm ./install_packages.R |
| 156 | +# EOF |
| 157 | + |
| 158 | +ENV APP_ROOT=/opt/app-root |
| 159 | + |
| 160 | +# Install NGINX to proxy RStudio and pass probes check |
| 161 | +ENV NGINX_VERSION=1.24 \ |
| 162 | + NGINX_SHORT_VER=124 \ |
| 163 | + NGINX_CONFIGURATION_PATH=${APP_ROOT}/etc/nginx.d \ |
| 164 | + NGINX_CONF_PATH=/etc/nginx/nginx.conf \ |
| 165 | + NGINX_DEFAULT_CONF_PATH=${APP_ROOT}/etc/nginx.default.d \ |
| 166 | + NGINX_CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/nginx \ |
| 167 | + NGINX_APP_ROOT=${APP_ROOT} \ |
| 168 | + NGINX_LOG_PATH=/var/log/nginx \ |
| 169 | + NGINX_PERL_MODULE_PATH=${APP_ROOT}/etc/perl |
| 170 | + |
| 171 | +# Modules does not exist |
| 172 | +RUN /bin/bash <<'EOF' |
| 173 | +set -Eeuxo pipefail |
| 174 | +dnf -y module enable nginx:$NGINX_VERSION |
| 175 | +INSTALL_PKGS="nss_wrapper bind-utils gettext hostname nginx nginx-mod-stream nginx-mod-http-perl httpd" |
| 176 | +dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS |
| 177 | +rpm -V $INSTALL_PKGS |
| 178 | +nginx -v 2>&1 | grep -qe "nginx/$NGINX_VERSION\." && echo "Found VERSION $NGINX_VERSION" |
| 179 | +dnf -y clean all --enablerepo='*' |
| 180 | +EOF |
| 181 | + |
| 182 | +# Configure httpd for CGI processing |
| 183 | +COPY --chown=1001:0 ${RSTUDIO_SOURCE_CODE}/httpd/httpd.conf /etc/httpd/conf/httpd.conf |
| 184 | +COPY --chown=1001:0 ${RSTUDIO_SOURCE_CODE}/httpd/rstudio-cgi.conf /etc/httpd/conf.d/rstudio-cgi.conf |
| 185 | + |
| 186 | +# Copy extra files to the image. |
| 187 | +COPY --chown=1001:0 ${RSTUDIO_SOURCE_CODE}/nginx/root/ / |
| 188 | + |
| 189 | +# Configure nginx |
| 190 | +COPY ${RSTUDIO_SOURCE_CODE}/nginx/serverconf/ /opt/app-root/etc/nginx.default.d/ |
| 191 | +COPY ${RSTUDIO_SOURCE_CODE}/nginx/httpconf/ /opt/app-root/etc/nginx.d/ |
| 192 | +COPY ${RSTUDIO_SOURCE_CODE}/nginx/api/ /opt/app-root/api/ |
| 193 | + |
| 194 | +# Changing ownership and user rights to support following use-cases: |
| 195 | +# 1) running container on OpenShift, whose default security model |
| 196 | +# is to run the container under random UID, but GID=0 |
| 197 | +# 2) for working root-less container with UID=1001, which does not have |
| 198 | +# to have GID=0 |
| 199 | +# 3) for default use-case, that is running container directly on operating system, |
| 200 | +# with default UID and GID (1001:0) |
| 201 | +# Supported combinations of UID:GID are thus following: |
| 202 | +# UID=1001 && GID=0 |
| 203 | +# UID=<any>&& GID=0 |
| 204 | +# UID=1001 && GID=<any> |
| 205 | +RUN /bin/bash <<'EOF' |
| 206 | +set -Eeuxo pipefail |
| 207 | +sed -i -f ${NGINX_APP_ROOT}/nginxconf.sed ${NGINX_CONF_PATH} |
| 208 | +mkdir -p ${NGINX_APP_ROOT}/etc/nginx.d/ |
| 209 | +mkdir -p ${NGINX_APP_ROOT}/etc/nginx.default.d/ |
| 210 | +mkdir -p ${NGINX_APP_ROOT}/api/ |
| 211 | +mkdir -p ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start |
| 212 | +mkdir -p ${NGINX_LOG_PATH} |
| 213 | +mkdir -p ${NGINX_PERL_MODULE_PATH} |
| 214 | +# Create httpd directories and set permissions |
| 215 | +mkdir -p /var/log/httpd /var/run/httpd /etc/httpd/logs |
| 216 | +chown -R 1001:0 ${NGINX_CONF_PATH} |
| 217 | +chown -R 1001:0 ${NGINX_APP_ROOT}/etc |
| 218 | +chown -R 1001:0 ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start |
| 219 | +chown -R 1001:0 /var/lib/nginx /var/log/nginx /run |
| 220 | +chown -R 1001:0 /var/log/httpd /var/run/httpd /etc/httpd/logs |
| 221 | +chmod ug+rw ${NGINX_CONF_PATH} |
| 222 | +chmod -R ug+rwX ${NGINX_APP_ROOT}/etc |
| 223 | +chmod -R ug+rwX ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start |
| 224 | +chmod -R ug+rwX /var/lib/nginx /var/log/nginx /run |
| 225 | +chmod -R ug+rwX /var/log/httpd /var/run/httpd /etc/httpd/logs |
| 226 | +# Make CGI scripts executable and set proper ownership |
| 227 | +chmod +x /opt/app-root/api/kernels/access.cgi |
| 228 | +chmod +x /opt/app-root/api/probe.cgi |
| 229 | +chown -R 1001:0 /opt/app-root/api |
| 230 | +rpm-file-permissions |
| 231 | +EOF |
| 232 | + |
| 233 | +# Launcher |
| 234 | +WORKDIR /opt/app-root/bin |
| 235 | + |
| 236 | +COPY ${RSTUDIO_SOURCE_CODE}/utils utils/ |
| 237 | +COPY ${RSTUDIO_SOURCE_CODE}/run-rstudio.sh ${RSTUDIO_SOURCE_CODE}/setup_rstudio.py ${RSTUDIO_SOURCE_CODE}/rsession.sh ${RSTUDIO_SOURCE_CODE}/run-nginx.sh ./ |
| 238 | + |
| 239 | +USER 1001 |
| 240 | + |
| 241 | +COPY ${RSTUDIO_SOURCE_CODE}/pylock.toml ./ |
| 242 | + |
| 243 | +RUN /bin/bash <<'EOF' |
| 244 | +set -Eeuxo pipefail |
| 245 | +echo "Installing softwares and packages" |
| 246 | +# This may have to download and compile some dependencies, and as we don't lock requirements from `build-system.requires`, |
| 247 | +# we often don't know the correct hashes and `--require-hashes` would therefore fail on non amd64, where building is common. |
| 248 | +uv pip install --strict --no-deps --no-cache --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml |
| 249 | +# Fix permissions to support pip in Openshift environments |
| 250 | +chmod -R g+w /opt/app-root/lib/python3.12/site-packages |
| 251 | +fix-permissions /opt/app-root -P |
| 252 | +EOF |
| 253 | + |
| 254 | +WORKDIR /opt/app-root/src |
| 255 | + |
| 256 | +CMD ["/opt/app-root/bin/run-rstudio.sh"] |
0 commit comments