Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 113 additions & 78 deletions codeserver/ubi9-python-3.12/Dockerfile.cpu
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@ COPY ${CODESERVER_SOURCE_CODE}/devel_env_setup.sh ./
# Important: Since HOME & USER for the python-312 has been changed,
# we need to ensure the same cache directory is mounted in
# the final stage with the necessary permissions to consume from cache
RUN --mount=type=cache,target=/root/.cache/uv \
pip install --no-cache-dir uv && \
# the devel script is ppc64le and s390x specific - sets up build-time dependencies
source ./devel_env_setup.sh && \
# This may have to download and compile some dependencies, and as we don't lock requirements from `build-system.requires`,
# we often don't know the correct hashes and `--require-hashes` would therefore fail on non amd64, where building is common.
UV_LINK_MODE=copy uv pip install --strict --no-deps --refresh --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml
RUN --mount=type=cache,target=/root/.cache/uv /bin/bash <<'EOF'
set -Eeuxo pipefail
pip install --no-cache-dir uv
# the devel script is ppc64le and s390x specific - sets up build-time dependencies
source ./devel_env_setup.sh
# This may have to download and compile some dependencies, and as we don't lock requirements from `build-system.requires`,
# we often don't know the correct hashes and `--require-hashes` would therefore fail on non amd64, where building is common.
UV_LINK_MODE=copy uv pip install --strict --no-deps --refresh --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml
EOF

# dummy file to make image build wait for this stage
RUN touch /tmp/control
Expand All @@ -85,19 +87,29 @@ COPY --from=ubi-repos /etc/yum.repos.d/ubi.repo /etc/yum.repos.d/ubi.repo
# Problem: The operation would result in removing the following protected packages: systemd
# (try to add '--allowerasing' to command line to replace conflicting packages or '--skip-broken' to skip uninstallable packages)
# Solution: --best --skip-broken does not work either, so use --nobest
RUN dnf -y upgrade --refresh --nobest --skip-broken --nodocs --noplugins --setopt=install_weak_deps=0 --setopt=keepcache=0 \
&& dnf clean all -y
RUN /bin/bash <<'EOF'
set -Eeuxo pipefail
dnf -y upgrade --refresh --nobest --skip-broken --nodocs --noplugins --setopt=install_weak_deps=0 --setopt=keepcache=0
dnf clean all -y
EOF

# upgrade first to avoid fixable vulnerabilities end

# Install useful OS packages
RUN dnf install -y tar perl mesa-libGL skopeo && dnf clean all && rm -rf /var/cache/dnf
RUN /bin/bash <<'EOF'
set -Eeuxo pipefail
dnf install -y tar perl mesa-libGL skopeo
dnf clean all
rm -rf /var/cache/dnf
EOF

# (ARCH-ppc64le): since wheels are compiled from source, we need shared libs available at runtime
RUN --mount=type=cache,from=whl-cache,source=/root/OpenBLAS,target=/OpenBlas,rw \
bash -c ' \
if [[ $(uname -m) == "ppc64le" ]]; then \
PREFIX=/usr/ make install -C /OpenBlas; \
fi '
RUN --mount=type=cache,from=whl-cache,source=/root/OpenBLAS,target=/OpenBlas,rw /bin/bash <<'EOF'
set -Eeuxo pipefail
if [[ $(uname -m) == "ppc64le" ]]; then
PREFIX=/usr/ make install -C /OpenBlas
fi
EOF

# Other apps and tools installed as default user
USER 1001
Expand All @@ -107,10 +119,13 @@ RUN pip install --no-cache-dir -U "micropipenv[toml]==1.9.0" "uv==0.8.12"
# Install micropipenv and uv to deploy packages from requirements.txt end

# Install the oc client begin
RUN curl -L https://mirror.openshift.com/pub/openshift-v4/$(uname -m)/clients/ocp/stable/openshift-client-linux.tar.gz \
-o /tmp/openshift-client-linux.tar.gz && \
tar -xzvf /tmp/openshift-client-linux.tar.gz oc && \
rm -f /tmp/openshift-client-linux.tar.gz
RUN /bin/bash <<'EOF'
set -Eeuxo pipefail
curl -L https://mirror.openshift.com/pub/openshift-v4/$(uname -m)/clients/ocp/stable/openshift-client-linux.tar.gz \
-o /tmp/openshift-client-linux.tar.gz
tar -xzvf /tmp/openshift-client-linux.tar.gz oc
rm -f /tmp/openshift-client-linux.tar.gz
EOF
# Install the oc client end

####################
Expand Down Expand Up @@ -157,21 +172,28 @@ COPY --from=rpm-base /tmp/control /dev/null
# Install code-server
# Note: Use cache mounts, bind mounts fail on konflux
# https://redhat-internal.slack.com/archives/C04PZ7H0VA8/p1755628065772589?thread_ts=1755597929.335999&cid=C04PZ7H0VA8
RUN --mount=type=cache,from=rpm-base,source=/tmp/,target=/code-server-rpm/,rw \
# EXPLANATION: dnf installation produces an "unsigned rpm" error from Konflux (Conforma)
# since we're building rpm from source, we will simply unpack it over /
# dnf install -y "/code-server-rpm/code-server-${CODESERVER_VERSION/v/}-${TARGETARCH}.rpm"
# dnf -y clean all --enablerepo='*'
dnf install -y cpio && dnf -y clean all && \
cd / && rpm2cpio "/code-server-rpm/code-server-${CODESERVER_VERSION/v/}-${TARGETARCH}.rpm" | cpio -idmv
RUN --mount=type=cache,from=rpm-base,source=/tmp/,target=/code-server-rpm/,rw /bin/bash <<'EOF'
set -Eeuxo pipefail
# EXPLANATION: dnf installation produces an "unsigned rpm" error from Konflux (Conforma)
# since we're building rpm from source, we will simply unpack it over /
# dnf install -y "/code-server-rpm/code-server-${CODESERVER_VERSION/v/}-${TARGETARCH}.rpm"
# dnf -y clean all --enablerepo='*'
dnf install -y cpio
dnf -y clean all
cd /
rpm2cpio "/code-server-rpm/code-server-${CODESERVER_VERSION/v/}-${TARGETARCH}.rpm" | cpio -idmv
EOF

COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/utils utils/

# 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.
# https://coder.com/docs/code-server/FAQ#how-do-i-install-an-extension
RUN mkdir -p /opt/app-root/extensions-temp && \
code-server --install-extension /opt/app-root/bin/utils/ms-python.python-2025.14.0.vsix --extensions-dir /opt/app-root/extensions-temp && \
code-server --install-extension /opt/app-root/bin/utils/ms-toolsai.jupyter-2025.8.0.vsix --extensions-dir /opt/app-root/extensions-temp
RUN /bin/bash <<'EOF'
set -Eeuxo pipefail
mkdir -p /opt/app-root/extensions-temp
code-server --install-extension /opt/app-root/bin/utils/ms-python.python-2025.14.0.vsix --extensions-dir /opt/app-root/extensions-temp
code-server --install-extension /opt/app-root/bin/utils/ms-toolsai.jupyter-2025.8.0.vsix --extensions-dir /opt/app-root/extensions-temp
EOF

# Install NGINX to proxy code-server and pass probes check
ENV APP_ROOT=/opt/app-root
Expand All @@ -188,10 +210,13 @@ ENV NGINX_CONFIGURATION_PATH=${APP_ROOT}/etc/nginx.d \
NGINX_PERL_MODULE_PATH=${APP_ROOT}/etc/perl

# Modules does not exist
RUN INSTALL_PKGS="bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd" && \
dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
dnf -y clean all --enablerepo='*'
RUN /bin/bash <<'EOF'
set -Eeuxo pipefail
INSTALL_PKGS="bind-utils nginx nginx-mod-stream nginx-mod-http-perl httpd"
dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS
rpm -V $INSTALL_PKGS
dnf -y clean all --enablerepo='*'
EOF

# Configure httpd for CGI processing
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/httpd/httpd.conf /etc/httpd/conf/httpd.conf
Expand All @@ -216,34 +241,37 @@ COPY ${CODESERVER_SOURCE_CODE}/nginx/api/ /opt/app-root/api/
# UID=1001 && GID=0
# UID=<any>&& GID=0
# UID=1001 && GID=<any>
RUN sed -i -f ${NGINX_APP_ROOT}/nginxconf.sed ${NGINX_CONF_PATH} && \
mkdir -p ${NGINX_APP_ROOT}/etc/nginx.d/ && \
mkdir -p ${NGINX_APP_ROOT}/etc/nginx.default.d/ && \
mkdir -p ${NGINX_APP_ROOT}/api/ && \
mkdir -p ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start && \
mkdir -p ${NGINX_LOG_PATH} && \
mkdir -p ${NGINX_PERL_MODULE_PATH} && \
# Create httpd directories and set permissions
mkdir -p /var/log/httpd /var/run/httpd /etc/httpd/logs && \
chown -R 1001:0 ${NGINX_CONF_PATH} && \
chown -R 1001:0 ${NGINX_APP_ROOT}/etc && \
chown -R 1001:0 ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start && \
chown -R 1001:0 /var/lib/nginx /var/log/nginx /run && \
chown -R 1001:0 /var/log/httpd /var/run/httpd /etc/httpd/logs && \
chmod ug+rw ${NGINX_CONF_PATH} && \
chmod -R ug+rwX ${NGINX_APP_ROOT}/etc && \
chmod -R ug+rwX ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start && \
chmod -R ug+rwX /var/lib/nginx /var/log/nginx /run && \
chmod -R ug+rwX /var/log/httpd /var/run/httpd /etc/httpd/logs && \
# Make CGI script executable
chmod +x /opt/app-root/api/kernels/access.cgi && \
rpm-file-permissions && \
# Ensure the temporary directory and target directory have the correct permissions
mkdir -p /opt/app-root/src/.local/share/code-server/extensions && \
mkdir -p /opt/app-root/src/.local/share/code-server/coder-logs && \
chown -R 1001:0 /opt/app-root/src/.local/share/code-server && \
chown -R 1001:0 /opt/app-root/extensions-temp && \
chown -R 1001:0 /opt/app-root/src/.config/code-server
RUN /bin/bash <<'EOF'
set -Eeuxo pipefail
sed -i -f ${NGINX_APP_ROOT}/nginxconf.sed ${NGINX_CONF_PATH}
mkdir -p ${NGINX_APP_ROOT}/etc/nginx.d/
mkdir -p ${NGINX_APP_ROOT}/etc/nginx.default.d/
mkdir -p ${NGINX_APP_ROOT}/api/
mkdir -p ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start
mkdir -p ${NGINX_LOG_PATH}
mkdir -p ${NGINX_PERL_MODULE_PATH}
# Create httpd directories and set permissions
mkdir -p /var/log/httpd /var/run/httpd /etc/httpd/logs
chown -R 1001:0 ${NGINX_CONF_PATH}
chown -R 1001:0 ${NGINX_APP_ROOT}/etc
chown -R 1001:0 ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start
chown -R 1001:0 /var/lib/nginx /var/log/nginx /run
chown -R 1001:0 /var/log/httpd /var/run/httpd /etc/httpd/logs
chmod ug+rw ${NGINX_CONF_PATH}
chmod -R ug+rwX ${NGINX_APP_ROOT}/etc
chmod -R ug+rwX ${NGINX_CONTAINER_SCRIPTS_PATH}/nginx-start
chmod -R ug+rwX /var/lib/nginx /var/log/nginx /run
chmod -R ug+rwX /var/log/httpd /var/run/httpd /etc/httpd/logs
# Make CGI script executable
chmod +x /opt/app-root/api/kernels/access.cgi
rpm-file-permissions
# Ensure the temporary directory and target directory have the correct permissions
mkdir -p /opt/app-root/src/.local/share/code-server/extensions
mkdir -p /opt/app-root/src/.local/share/code-server/coder-logs
chown -R 1001:0 /opt/app-root/src/.local/share/code-server
chown -R 1001:0 /opt/app-root/extensions-temp
chown -R 1001:0 /opt/app-root/src/.config/code-server
EOF

# Launcher
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/run-code-server.sh ${CODESERVER_SOURCE_CODE}/run-nginx.sh ./
Expand All @@ -261,28 +289,35 @@ COPY --from=whl-cache /tmp/control /dev/null
# Install packages and cleanup
# (ARCH-ppc64le): install packages (eg. pyarrow) that need to be built from source repository on ppc64le
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=cache,from=whl-cache,source=/wheelsdir/,target=/wheelsdir/,rw \
bash -c ' \
if [[ $(uname -m) == "ppc64le" ]] || [[ $(uname -m) == "s390x" ]]; then \
uv pip install /wheelsdir/*.whl; \
fi '
--mount=type=cache,from=whl-cache,source=/wheelsdir/,target=/wheelsdir/,rw /bin/bash <<'EOF'
set -Eeuxo pipefail
if [[ $(uname -m) == "ppc64le" ]] || [[ $(uname -m) == "s390x" ]]; then
uv pip install /wheelsdir/*.whl
fi
EOF

# install packages as USER 0 (this will allow us to consume uv cache)
RUN --mount=type=cache,target=/root/.cache/uv \
echo "Installing softwares and packages" && \
# we can ensure wheels are consumed from the cache only by restricting internet access for uv install with '--offline' flag
# TODO(jdanek): seen some builds fail on GitHub Actions with --offline and see no need to limit ourselves to the cache, will remove this
UV_LINK_MODE=copy uv pip install --cache-dir /root/.cache/uv --requirements=./pylock.toml && \
# Note: debugpy wheel availabe on pypi (in uv cache) is none-any but bundles amd64.so files
# Build debugpy from source instead
UV_LINK_MODE=copy uv pip install --no-cache git+https://github.com/microsoft/debugpy.git@v$(grep -A1 '\"debugpy\"' ./pylock.toml | grep -Eo '\b[0-9\.]+\b') && \
# change ownership to default user (all packages were installed as root and has root:root ownership \
chown -R 1001:0 /opt/app-root
RUN --mount=type=cache,target=/root/.cache/uv /bin/bash <<'EOF'
set -Eeuxo pipefail
echo "Installing softwares and packages"
# we can ensure wheels are consumed from the cache only by restricting internet access for uv install with '--offline' flag
# TODO(jdanek): seen some builds fail on GitHub Actions with --offline and see no need to limit ourselves to the cache, will remove this
UV_LINK_MODE=copy uv pip install --cache-dir /root/.cache/uv --requirements=./pylock.toml
# Note: debugpy wheel availabe on pypi (in uv cache) is none-any but bundles amd64.so files
# Build debugpy from source instead
UV_LINK_MODE=copy uv pip install --no-cache git+https://github.com/microsoft/debugpy.git@v$(grep -A1 '\"debugpy\"' ./pylock.toml | grep -Eo '\b[0-9\.]+\b')
# change ownership to default user (all packages were installed as root and has root:root ownership
chown -R 1001:0 /opt/app-root
EOF

USER 1001

# Fix permissions to support pip in Openshift environments
RUN chmod -R g+w /opt/app-root/lib/python3.12/site-packages && \
fix-permissions /opt/app-root -P
RUN /bin/bash <<'EOF'
set -Eeuxo pipefail
chmod -R g+w /opt/app-root/lib/python3.12/site-packages
fix-permissions /opt/app-root -P
EOF

WORKDIR /opt/app-root/src

Expand Down
Loading