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