From 307917d56a1a5aff1007b87b209a45c5be97fac8 Mon Sep 17 00:00:00 2001 From: "Benjamin R. J. Schwedler" Date: Fri, 14 Aug 2026 10:55:28 -0500 Subject: [PATCH 1/2] Add Ubuntu 26.04 support Adds Ubuntu 26.04 (resolute) as a new OS target for workbench, workbench-session, and workbench-session-init, alongside the existing 22.04 and 24.04 targets, for both amd64 and arm64 platforms. Templates mirror the Ubuntu 24.04 baseline exactly: Containerfiles are byte-for-byte identical in structure once the OS version and codename strings are normalized, and package lists render to identical content. - bakery.yaml: add Ubuntu 26.04 entries for workbench (2026.08.0 and preview), workbench-session-init (preview), and the workbench-session matrix, each with amd64/arm64 platforms. - Containerfile.ubuntu2604.jinja2 templates for all three images, based on the Ubuntu 24.04 templates with the base image, package file paths, and codename references (resolute, not noble) updated for 26.04, including the Standard/Minimal variant branching for workbench and workbench-session. - ubuntu-26.04_packages.txt.jinja2 / ubuntu-26.04_optional_packages.txt.jinja2 dependency lists for workbench and workbench-session, matching the 24.04 package sets (including the default-libmysqlclient-dev vs libmysqlclient-dev distinction called out in the 24.04 comment, to avoid a build-breaking conflict with libgdal-dev). - Rendered workbench/2026.08 and workbench-session matrix Containerfiles and dep files for Ubuntu 26.04. --- bakery.yaml | 12 ++ .../template/Containerfile.ubuntu2604.jinja2 | 33 ++++ .../matrix/Containerfile.ubuntu2604.min | 127 +++++++++++++ .../matrix/Containerfile.ubuntu2604.std | 130 ++++++++++++++ .../deps/ubuntu-26.04_optional_packages.txt | 76 ++++++++ .../matrix/deps/ubuntu-26.04_packages.txt | 10 ++ .../template/Containerfile.ubuntu2604.jinja2 | 93 ++++++++++ .../ubuntu-26.04_optional_packages.txt.jinja2 | 102 +++++++++++ .../deps/ubuntu-26.04_packages.txt.jinja2 | 10 ++ .../2026.08/Containerfile.ubuntu2604.min | 103 +++++++++++ .../2026.08/Containerfile.ubuntu2604.std | 167 ++++++++++++++++++ .../deps/ubuntu-26.04_optional_packages.txt | 85 +++++++++ .../2026.08/deps/ubuntu-26.04_packages.txt | 12 ++ .../template/Containerfile.ubuntu2604.jinja2 | 156 ++++++++++++++++ .../ubuntu-26.04_optional_packages.txt.jinja2 | 112 ++++++++++++ .../deps/ubuntu-26.04_packages.txt.jinja2 | 12 ++ 16 files changed, 1240 insertions(+) create mode 100644 workbench-session-init/template/Containerfile.ubuntu2604.jinja2 create mode 100644 workbench-session/matrix/Containerfile.ubuntu2604.min create mode 100644 workbench-session/matrix/Containerfile.ubuntu2604.std create mode 100644 workbench-session/matrix/deps/ubuntu-26.04_optional_packages.txt create mode 100644 workbench-session/matrix/deps/ubuntu-26.04_packages.txt create mode 100644 workbench-session/template/Containerfile.ubuntu2604.jinja2 create mode 100644 workbench-session/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 create mode 100644 workbench-session/template/deps/ubuntu-26.04_packages.txt.jinja2 create mode 100644 workbench/2026.08/Containerfile.ubuntu2604.min create mode 100644 workbench/2026.08/Containerfile.ubuntu2604.std create mode 100644 workbench/2026.08/deps/ubuntu-26.04_optional_packages.txt create mode 100644 workbench/2026.08/deps/ubuntu-26.04_packages.txt create mode 100644 workbench/template/Containerfile.ubuntu2604.jinja2 create mode 100644 workbench/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 create mode 100644 workbench/template/deps/ubuntu-26.04_packages.txt.jinja2 diff --git a/bakery.yaml b/bakery.yaml index 7fbbe9ac..8ba4b456 100644 --- a/bakery.yaml +++ b/bakery.yaml @@ -76,6 +76,10 @@ images: product: workbench channel: preview os: + - name: Ubuntu 26.04 + platforms: + - linux/amd64 + - linux/arm64 - name: Ubuntu 24.04 primary: true platforms: @@ -97,6 +101,10 @@ images: platforms: - linux/amd64 - linux/arm64 + - name: Ubuntu 26.04 + platforms: + - linux/amd64 + - linux/arm64 dependencies: - dependency: R version: 4.6.1 @@ -331,6 +339,10 @@ images: constraint: latest: true os: + - name: Ubuntu 26.04 + platforms: + - linux/amd64 + - linux/arm64 - name: Ubuntu 24.04 primary: true platforms: diff --git a/workbench-session-init/template/Containerfile.ubuntu2604.jinja2 b/workbench-session-init/template/Containerfile.ubuntu2604.jinja2 new file mode 100644 index 00000000..613f8fe0 --- /dev/null +++ b/workbench-session-init/template/Containerfile.ubuntu2604.jinja2 @@ -0,0 +1,33 @@ +{#- +Below are imports for Bakery's macros. If any are unneeded, they can be removed. +Bakery handles bootstrapping the files into template rendering. +-#} +{%- import "apt.j2" as apt -%} +FROM docker.io/library/ubuntu:26.04 AS builder + +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILDARCH +ARG TARGETARCH=${BUILDARCH} + +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +### Initialize PTI in container ### +{{ apt.run_setup() }} + +# Download the RStudio Workbench session components +RUN case ${TARGETARCH} in \ + amd64) CDN_ARCH=x86_64 ;; \ + arm64) CDN_ARCH=arm64 ;; \ + *) echo "Unsupported architecture: ${TARGETARCH}" && exit 1 ;; \ + esac && \ + mkdir -p /pwb-staging && \ + curl -fsSL -o /pwb-staging/rsp-session-multi-linux.tar.gz "https://s3.amazonaws.com/rstudio-ide-build/session/multi/$CDN_ARCH/rsp-session-multi-linux-{{ Image.Version | replace('+', '-') }}-$CDN_ARCH.tar.gz" && \ + mkdir -p /opt/session-components && \ + tar -C /opt/session-components -xpf /pwb-staging/rsp-session-multi-linux.tar.gz && \ + chmod 755 /opt/session-components && \ + rm -rf /pwb-staging + +FROM docker.io/library/ubuntu:26.04 +LABEL org.opencontainers.image.base.name="docker.io/library/ubuntu:26.04" +COPY --from=builder /opt/session-components /opt/session-components +CMD ["/opt/session-components/bin/session-init"] diff --git a/workbench-session/matrix/Containerfile.ubuntu2604.min b/workbench-session/matrix/Containerfile.ubuntu2604.min new file mode 100644 index 00000000..f015fb57 --- /dev/null +++ b/workbench-session/matrix/Containerfile.ubuntu2604.min @@ -0,0 +1,127 @@ +# Build Python using uv in a separate stage +FROM ghcr.io/astral-sh/uv:debian-slim AS python-builder + +ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy +ENV UV_PYTHON_INSTALL_DIR=/opt/python +ENV UV_PYTHON_PREFERENCE=only-managed + +ARG PYTHON_VERSION +RUN uv python install $PYTHON_VERSION +RUN mv /opt/python/cpython-$PYTHON_VERSION-linux-*/ /opt/python/$PYTHON_VERSION + + +FROM docker.io/library/ubuntu:26.04 +LABEL org.opencontainers.image.base.name="docker.io/library/ubuntu:26.04" + +### ARG declarations ### +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILDARCH +ARG TARGETARCH=${BUILDARCH} +ARG R_VERSION +ARG PYTHON_VERSION +ARG QUARTO_VERSION + +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +### Install Apt Packages ### +RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ + apt-get update -yqq --fix-missing && \ + apt-get upgrade -yqq && \ + apt-get dist-upgrade -yqq && \ + apt-get autoremove -yqq --purge && \ + apt-get install -yqq --no-install-recommends \ + curl \ + ca-certificates \ + gnupg \ + tar && \ + apt-get install -yqq --no-install-recommends locales && \ + localedef -i en_US -f UTF-8 en_US.UTF-8 && \ + bash -c "$(curl -1fsSL 'https://dl.posit.co/public/pro/setup.deb.sh')" && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 + +COPY workbench-session/matrix/deps/ubuntu-26.04_packages.txt /tmp/ubuntu-26.04_packages.txt +RUN apt-get update -yqq && \ + xargs -a /tmp/ubuntu-26.04_packages.txt apt-get install -yqq --no-install-recommends && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* + +### Install Pro Drivers ### +RUN apt-get update -yqq && \ + apt-get install -yqq --no-install-recommends \ + rstudio-drivers && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* +RUN cp /opt/rstudio-drivers/odbcinst.ini.sample /etc/odbcinst.ini + +### Enable the pwb NSS module for rootless in-session identity resolution ### +# libnss_pwb.so is delivered at runtime by the workbench-session-init container +# into /usr/lib/rstudio-server/bin/resolute/. Create the (build-time dangling) +# multiarch symlink + nsswitch entries so glibc loads it once that volume is +# populated. Dormant-safe: with no workbench-nss.conf the module returns +# Unavail and resolution falls through to `files`. +RUN case "${TARGETARCH}" in \ + amd64) TRIPLET=x86_64-linux-gnu ;; \ + arm64) TRIPLET=aarch64-linux-gnu ;; \ + *) echo "unsupported arch ${TARGETARCH}"; exit 1 ;; \ + esac && \ + mkdir -p /usr/lib/rstudio-server/bin/resolute && \ + touch /usr/lib/rstudio-server/bin/resolute/libnss_pwb.so && \ + ln -sf /usr/lib/rstudio-server/bin/resolute/libnss_pwb.so \ + "/usr/lib/${TRIPLET}/libnss_pwb.so.2" && \ + for db in passwd group shadow; do \ + touch /etc/nsswitch.conf; \ + if grep -qE "^${db}:" /etc/nsswitch.conf; then \ + sed -i -E "/^${db}:/ {/\bpwb\b/! s/\$/ pwb/}" /etc/nsswitch.conf; \ + else \ + echo "${db}: files pwb" >> /etc/nsswitch.conf; \ + fi; \ + done + +# Install Python from previous stage +COPY --from=python-builder /opt/python /opt/python + +### Install Jupyter ### +RUN /opt/python/$PYTHON_VERSION/bin/python -m venv /opt/python/jupyter && \ + /opt/python/jupyter/bin/pip install --no-cache-dir --upgrade pip setuptools wheel && \ + /opt/python/jupyter/bin/pip install --no-cache-dir --upgrade \ + "jupyterlab<5" \ + notebook \ + "pwb_jupyterlab<2" && \ + rm -rf /opt/python/jupyter/lib/python*/site-packages/jupyterlab/tests && \ + rm -rf /opt/python/jupyter/lib/python*/site-packages/jupyterlab/galata && \ + rm -f /opt/python/jupyter/lib/python*/site-packages/jupyterlab/staging/yarn.lock && \ + ln -s /opt/python/jupyter/bin/jupyter /usr/local/bin/jupyter + +### Install Jupyter kernel ### +RUN /opt/python/$PYTHON_VERSION/bin/pip install --no-cache-dir --upgrade --break-system-packages \ + ipykernel && \ + /opt/python/$PYTHON_VERSION/bin/python -m ipykernel install --user --name python$PYTHON_VERSION --display-name "Python $PYTHON_VERSION" + +# Install R +RUN RUN_UNATTENDED=1 R_VERSION=$R_VERSION bash -c "$(curl -fsSL https://rstd.io/r-install)" && \ + find . -type f -name '[rR]-$R_VERSION.*\.(deb|rpm)' -delete + +### Install Quarto ### +RUN bash -c "$(curl -1fsSL 'https://dl.posit.co/public/open/setup.deb.sh')" && \ + apt-get install -yqq --no-install-recommends \ + quarto=$QUARTO_VERSION && \ + apt-mark hold quarto && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* + +### Install TinyTeX ### +# ADD busts the cache on new TinyTeX releases. +# HOME="/opt" workaround: https://github.com/quarto-dev/quarto-cli/issues/11800 +ADD https://github.com/rstudio/tinytex-releases/releases/latest /tmp/tinytex-release.json +RUN --mount=type=secret,id=github_token,required=false \ + GH_TOKEN="$([ -s /run/secrets/github_token ] && cat /run/secrets/github_token)" HOME="/opt" CI=true /opt/quarto/bin/quarto install tinytex --no-prompt --update-path && \ + rm -f /tmp/tinytex-release.json + +COPY workbench-session/matrix/conf/vscode.extensions.conf /etc/rstudio/vscode.extensions.conf +COPY workbench-session/matrix/conf/positron.extensions.conf /etc/rstudio/positron.extensions.conf + +EXPOSE 8788/tcp diff --git a/workbench-session/matrix/Containerfile.ubuntu2604.std b/workbench-session/matrix/Containerfile.ubuntu2604.std new file mode 100644 index 00000000..35434284 --- /dev/null +++ b/workbench-session/matrix/Containerfile.ubuntu2604.std @@ -0,0 +1,130 @@ +# Build Python using uv in a separate stage +FROM ghcr.io/astral-sh/uv:debian-slim AS python-builder + +ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy +ENV UV_PYTHON_INSTALL_DIR=/opt/python +ENV UV_PYTHON_PREFERENCE=only-managed + +ARG PYTHON_VERSION +RUN uv python install $PYTHON_VERSION +RUN mv /opt/python/cpython-$PYTHON_VERSION-linux-*/ /opt/python/$PYTHON_VERSION + + +FROM docker.io/library/ubuntu:26.04 +LABEL org.opencontainers.image.base.name="docker.io/library/ubuntu:26.04" + +### ARG declarations ### +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILDARCH +ARG TARGETARCH=${BUILDARCH} +ARG R_VERSION +ARG PYTHON_VERSION +ARG QUARTO_VERSION + +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +### Install Apt Packages ### +RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ + apt-get update -yqq --fix-missing && \ + apt-get upgrade -yqq && \ + apt-get dist-upgrade -yqq && \ + apt-get autoremove -yqq --purge && \ + apt-get install -yqq --no-install-recommends \ + curl \ + ca-certificates \ + gnupg \ + tar && \ + apt-get install -yqq --no-install-recommends locales && \ + localedef -i en_US -f UTF-8 en_US.UTF-8 && \ + bash -c "$(curl -1fsSL 'https://dl.posit.co/public/pro/setup.deb.sh')" && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 + +COPY workbench-session/matrix/deps/ubuntu-26.04_packages.txt /tmp/ubuntu-26.04_packages.txt +COPY workbench-session/matrix/deps/ubuntu-26.04_optional_packages.txt /tmp/ubuntu-26.04_optional_packages.txt +RUN apt-get update -yqq && \ + xargs -a /tmp/ubuntu-26.04_packages.txt apt-get install -yqq --no-install-recommends && \ + xargs -a /tmp/ubuntu-26.04_optional_packages.txt apt-get install -yqq --no-install-recommends && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* + + +### Install Pro Drivers ### +RUN apt-get update -yqq && \ + apt-get install -yqq --no-install-recommends \ + rstudio-drivers && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* +RUN cp /opt/rstudio-drivers/odbcinst.ini.sample /etc/odbcinst.ini + +### Enable the pwb NSS module for rootless in-session identity resolution ### +# libnss_pwb.so is delivered at runtime by the workbench-session-init container +# into /usr/lib/rstudio-server/bin/resolute/. Create the (build-time dangling) +# multiarch symlink + nsswitch entries so glibc loads it once that volume is +# populated. Dormant-safe: with no workbench-nss.conf the module returns +# Unavail and resolution falls through to `files`. +RUN case "${TARGETARCH}" in \ + amd64) TRIPLET=x86_64-linux-gnu ;; \ + arm64) TRIPLET=aarch64-linux-gnu ;; \ + *) echo "unsupported arch ${TARGETARCH}"; exit 1 ;; \ + esac && \ + mkdir -p /usr/lib/rstudio-server/bin/resolute && \ + touch /usr/lib/rstudio-server/bin/resolute/libnss_pwb.so && \ + ln -sf /usr/lib/rstudio-server/bin/resolute/libnss_pwb.so \ + "/usr/lib/${TRIPLET}/libnss_pwb.so.2" && \ + for db in passwd group shadow; do \ + touch /etc/nsswitch.conf; \ + if grep -qE "^${db}:" /etc/nsswitch.conf; then \ + sed -i -E "/^${db}:/ {/\bpwb\b/! s/\$/ pwb/}" /etc/nsswitch.conf; \ + else \ + echo "${db}: files pwb" >> /etc/nsswitch.conf; \ + fi; \ + done + +# Install Python from previous stage +COPY --from=python-builder /opt/python /opt/python + +### Install Jupyter ### +RUN /opt/python/$PYTHON_VERSION/bin/python -m venv /opt/python/jupyter && \ + /opt/python/jupyter/bin/pip install --no-cache-dir --upgrade pip setuptools wheel && \ + /opt/python/jupyter/bin/pip install --no-cache-dir --upgrade \ + "jupyterlab<5" \ + notebook \ + "pwb_jupyterlab<2" && \ + rm -rf /opt/python/jupyter/lib/python*/site-packages/jupyterlab/tests && \ + rm -rf /opt/python/jupyter/lib/python*/site-packages/jupyterlab/galata && \ + rm -f /opt/python/jupyter/lib/python*/site-packages/jupyterlab/staging/yarn.lock && \ + ln -s /opt/python/jupyter/bin/jupyter /usr/local/bin/jupyter + +### Install Jupyter kernel ### +RUN /opt/python/$PYTHON_VERSION/bin/pip install --no-cache-dir --upgrade --break-system-packages \ + ipykernel && \ + /opt/python/$PYTHON_VERSION/bin/python -m ipykernel install --user --name python$PYTHON_VERSION --display-name "Python $PYTHON_VERSION" + +# Install R +RUN RUN_UNATTENDED=1 R_VERSION=$R_VERSION bash -c "$(curl -fsSL https://rstd.io/r-install)" && \ + find . -type f -name '[rR]-$R_VERSION.*\.(deb|rpm)' -delete + +### Install Quarto ### +RUN bash -c "$(curl -1fsSL 'https://dl.posit.co/public/open/setup.deb.sh')" && \ + apt-get install -yqq --no-install-recommends \ + quarto=$QUARTO_VERSION && \ + apt-mark hold quarto && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* + +### Install TinyTeX ### +# ADD busts the cache on new TinyTeX releases. +# HOME="/opt" workaround: https://github.com/quarto-dev/quarto-cli/issues/11800 +ADD https://github.com/rstudio/tinytex-releases/releases/latest /tmp/tinytex-release.json +RUN --mount=type=secret,id=github_token,required=false \ + GH_TOKEN="$([ -s /run/secrets/github_token ] && cat /run/secrets/github_token)" HOME="/opt" CI=true /opt/quarto/bin/quarto install tinytex --no-prompt --update-path && \ + rm -f /tmp/tinytex-release.json + +COPY workbench-session/matrix/conf/vscode.extensions.conf /etc/rstudio/vscode.extensions.conf +COPY workbench-session/matrix/conf/positron.extensions.conf /etc/rstudio/positron.extensions.conf + +EXPOSE 8788/tcp diff --git a/workbench-session/matrix/deps/ubuntu-26.04_optional_packages.txt b/workbench-session/matrix/deps/ubuntu-26.04_optional_packages.txt new file mode 100644 index 00000000..cad1ff60 --- /dev/null +++ b/workbench-session/matrix/deps/ubuntu-26.04_optional_packages.txt @@ -0,0 +1,76 @@ +autoconf +automake +cmake +gfortran +make +patch +pkg-config +bzip2 +unzip +zip +libbz2-dev +liblzma-dev +zlib1g-dev +libcurl4-openssl-dev +libsodium-dev +libssh2-1-dev +libffi-dev +libpcre2-dev +libreadline-dev +libicu-dev +libxml2-dev +libxslt1-dev +default-libmysqlclient-dev +libsqlite3-dev +unixodbc-dev +libgit2-dev +openssh-client +wget +gdal-bin +libgdal-dev +libgeos-dev +libproj-dev +libudunits2-dev +fonts-dejavu-core +fonts-liberation +ghostscript +gsfonts +imagemagick +libcairo2-dev +libfontconfig1-dev +libfreetype-dev +libfribidi-dev +libharfbuzz-dev +libjpeg-dev +libmagick++-dev +libpango1.0-dev +libpng-dev +libtiff-dev +libwebp-dev +libglpk-dev +libgmp3-dev +libgsl-dev +libmpfr-dev +libabsl-dev +libnode-dev +libprotobuf-dev +libprotoc-dev +libuv1-dev +protobuf-compiler +libpoppler-cpp-dev +poppler-data +poppler-utils +libgl1-mesa-dev +libglu1-mesa-dev +libx11-dev +tcl +tk +tk-dev +tk-table +default-jdk +libkrb5-dev +libldap2-dev +libsasl2-dev +gdb +perl +strace diff --git a/workbench-session/matrix/deps/ubuntu-26.04_packages.txt b/workbench-session/matrix/deps/ubuntu-26.04_packages.txt new file mode 100644 index 00000000..268608dd --- /dev/null +++ b/workbench-session/matrix/deps/ubuntu-26.04_packages.txt @@ -0,0 +1,10 @@ +ca-certificates +curl +git +krb5-user +libpq-dev +libuser +libuser1-dev +rrdtool +subversion +xz-utils diff --git a/workbench-session/template/Containerfile.ubuntu2604.jinja2 b/workbench-session/template/Containerfile.ubuntu2604.jinja2 new file mode 100644 index 00000000..297f929c --- /dev/null +++ b/workbench-session/template/Containerfile.ubuntu2604.jinja2 @@ -0,0 +1,93 @@ +{#- +Below are imports for Bakery's macros. If any are unneeded, they can be removed. +Bakery handles bootstrapping the files into template rendering. +-#} +{%- import "apt.j2" as apt -%} +{%- import "python.j2" as python -%} +{%- import "quarto.j2" as quarto -%} +{%- import "r.j2" as r -%} + +# Build Python using uv in a separate stage +{{ python.build_stage(python.build_arg(), prerun=python.declare_build_arg()) }} + +FROM docker.io/library/ubuntu:26.04 +LABEL org.opencontainers.image.base.name="docker.io/library/ubuntu:26.04" + +### ARG declarations ### +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILDARCH +ARG TARGETARCH=${BUILDARCH} +{{ r.declare_build_arg() }} +{{ python.declare_build_arg() }} +{{ quarto.declare_build_arg() }} + +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +### Install Apt Packages ### +{{ apt.run_setup() }} + +{% if Image.Variant != "Minimal" -%} +COPY {{ Path.Version }}/deps/ubuntu-26.04_packages.txt /tmp/ubuntu-26.04_packages.txt +COPY {{ Path.Version }}/deps/ubuntu-26.04_optional_packages.txt /tmp/ubuntu-26.04_optional_packages.txt +{{ apt.run_install(files = ['/tmp/ubuntu-26.04_packages.txt', '/tmp/ubuntu-26.04_optional_packages.txt']) }} +{% else -%} +COPY {{ Path.Version }}/deps/ubuntu-26.04_packages.txt /tmp/ubuntu-26.04_packages.txt +{{ apt.run_install(files = '/tmp/ubuntu-26.04_packages.txt') }} +{%- endif %} + +### Install Pro Drivers ### +{{ apt.run_install(packages="rstudio-drivers") }} +RUN cp /opt/rstudio-drivers/odbcinst.ini.sample /etc/odbcinst.ini + +### Enable the pwb NSS module for rootless in-session identity resolution ### +# libnss_pwb.so is delivered at runtime by the workbench-session-init container +# into /usr/lib/rstudio-server/bin/resolute/. Create the (build-time dangling) +# multiarch symlink + nsswitch entries so glibc loads it once that volume is +# populated. Dormant-safe: with no workbench-nss.conf the module returns +# Unavail and resolution falls through to `files`. +RUN case "${TARGETARCH}" in \ + amd64) TRIPLET=x86_64-linux-gnu ;; \ + arm64) TRIPLET=aarch64-linux-gnu ;; \ + *) echo "unsupported arch ${TARGETARCH}"; exit 1 ;; \ + esac && \ + mkdir -p /usr/lib/rstudio-server/bin/resolute && \ + touch /usr/lib/rstudio-server/bin/resolute/libnss_pwb.so && \ + ln -sf /usr/lib/rstudio-server/bin/resolute/libnss_pwb.so \ + "/usr/lib/${TRIPLET}/libnss_pwb.so.2" && \ + for db in passwd group shadow; do \ + touch /etc/nsswitch.conf; \ + if grep -qE "^${db}:" /etc/nsswitch.conf; then \ + sed -i -E "/^${db}:/ {/\bpwb\b/! s/\$/ pwb/}" /etc/nsswitch.conf; \ + else \ + echo "${db}: files pwb" >> /etc/nsswitch.conf; \ + fi; \ + done + +# Install Python from previous stage +{{ python.copy_from_build_stage() }} + +### Install Jupyter ### +{{ python.run_install_jupyterlab_workbench(python.build_arg(), jupyterlab_version_pin = "<5", pwb_jupyterlab_version_pin = "<2") }} + +### Install Jupyter kernel ### +RUN {{ python.install_packages(python.build_arg(), "ipykernel") }} && \ + {{ python.get_version_directory(python.build_arg()) }}/bin/python -m ipykernel install --user --name python{{ python.build_arg() }} --display-name "Python {{ python.build_arg() }}" + +# Install R +{{ r.run_install(r.build_arg()) }} + +### Install Quarto ### +RUN {{ quarto.install(quarto.build_arg()) | indent(4) }} + +### Install TinyTeX ### +# ADD busts the cache on new TinyTeX releases. +# HOME="/opt" workaround: https://github.com/quarto-dev/quarto-cli/issues/11800 +ADD https://github.com/rstudio/tinytex-releases/releases/latest /tmp/tinytex-release.json +RUN {{ quarto.github_token_secret_mount() }} \ + {{ quarto.install_tinytex_command(quarto.get_directory() ~ "/bin/quarto", update_path=True, home_path="/opt") | indent(4) }} && \ + rm -f /tmp/tinytex-release.json + +COPY {{ Path.Version }}/conf/vscode.extensions.conf /etc/rstudio/vscode.extensions.conf +COPY {{ Path.Version }}/conf/positron.extensions.conf /etc/rstudio/positron.extensions.conf + +EXPOSE 8788/tcp diff --git a/workbench-session/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 b/workbench-session/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 new file mode 100644 index 00000000..3648e306 --- /dev/null +++ b/workbench-session/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 @@ -0,0 +1,102 @@ +{#- +Standard-variant optional apt packages for the workbench-session matrix +image on Ubuntu 26.04 (resolute). Mirrors the 24.04 session list - see that +template for what is included vs. dropped relative to the workbench image, +and the workbench 26.04 template for resolute-specific naming notes. +-#} +{# Build toolchain - source installs of compiled R/Python pkgs (Matrix, RcppArmadillo, scipy) -#} +autoconf +automake +cmake +gfortran +make +patch +pkg-config +{# Compression CLI tools - source archive extraction, Quarto bundles -#} +bzip2 +unzip +zip +{# Compression headers - data.table, httpuv, Pillow, scipy, lxml from source -#} +libbz2-dev +liblzma-dev +zlib1g-dev +{# TLS / HTTP / crypto - curl, httr, httr2, openssl, urllib3, cryptography, sodium, plumber -#} +libcurl4-openssl-dev +libsodium-dev +libssh2-1-dev +{# FFI / readline / regex - Python cffi/cryptography, source rebuilds of R + Python -#} +libffi-dev +libpcre2-dev +libreadline-dev +{# XML / Unicode / text - xml2, XML, stringi, lxml, arrow -#} +libicu-dev +libxml2-dev +libxslt1-dev +{# Database client headers - RPostgres, RMariaDB, odbc, DBI, psycopg2, mysqlclient, pyodbc. + NOTE: keep default-libmysqlclient-dev. Do NOT substitute libmariadb-dev-compat -- it declares + Conflicts: libmysqlclient-dev, which libgdal-dev needs, so the swap breaks the build. -#} +default-libmysqlclient-dev +libsqlite3-dev +unixodbc-dev +{# Version control / network - gert, git2r, renv from GitHub, pip git+ installs, SSH transports -#} +libgit2-dev +openssh-client +wget +{# Geospatial - sf, terra, stars, geopandas, rasterio, pyproj -#} +gdal-bin +libgdal-dev +libgeos-dev +libproj-dev +libudunits2-dev +{# Graphics / fonts / imaging - ragg, systemfonts, textshaping, magick, Cairo, Pillow, matplotlib -#} +fonts-dejavu-core +fonts-liberation +ghostscript +gsfonts +imagemagick +libcairo2-dev +libfontconfig1-dev +libfreetype-dev +libfribidi-dev +libharfbuzz-dev +libjpeg-dev +libmagick++-dev +libpango1.0-dev +libpng-dev +libtiff-dev +libwebp-dev +{# Math libraries - igraph (GLPK), gmp, Rmpfr, gsl, RcppGSL, Bioconductor numerics -#} +libglpk-dev +libgmp3-dev +libgsl-dev +libmpfr-dev +{# V8 / protobuf / arrow / httpuv source build -#} +libabsl-dev +libnode-dev +libprotobuf-dev +libprotoc-dev +libuv1-dev +protobuf-compiler +{# PDF processing - pdftools, pdfminer.six, pdf2image, magick PDF rasterization -#} +libpoppler-cpp-dev +poppler-data +poppler-utils +{# X11 / OpenGL - rgl, plotly 3D, configure-script probes that test for X libs -#} +libgl1-mesa-dev +libglu1-mesa-dev +libx11-dev +{# Tcl/Tk - tcltk R pkg, Python tkinter -#} +tcl +tk +tk-dev +tk-table +{# Java - rJava, RJDBC, xlsx, JPype1; run R CMD javareconf after install -#} +default-jdk +{# Authentication / directory - mongolite, pymongo GSSAPI, python-ldap, requests-kerberos -#} +libkrb5-dev +libldap2-dev +libsasl2-dev +{# Debug / scripting - session diagnostic flow, R configure perl scripts -#} +gdb +perl +strace diff --git a/workbench-session/template/deps/ubuntu-26.04_packages.txt.jinja2 b/workbench-session/template/deps/ubuntu-26.04_packages.txt.jinja2 new file mode 100644 index 00000000..268608dd --- /dev/null +++ b/workbench-session/template/deps/ubuntu-26.04_packages.txt.jinja2 @@ -0,0 +1,10 @@ +ca-certificates +curl +git +krb5-user +libpq-dev +libuser +libuser1-dev +rrdtool +subversion +xz-utils diff --git a/workbench/2026.08/Containerfile.ubuntu2604.min b/workbench/2026.08/Containerfile.ubuntu2604.min new file mode 100644 index 00000000..3bb39171 --- /dev/null +++ b/workbench/2026.08/Containerfile.ubuntu2604.min @@ -0,0 +1,103 @@ +FROM docker.io/library/ubuntu:26.04 +LABEL org.opencontainers.image.base.name="docker.io/library/ubuntu:26.04" + +### ARG declarations ### +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILDARCH +ARG TARGETARCH=${BUILDARCH} +ARG RSTUDIO_INSTALL_NO_LICENSE_INITIALIZATION=1 + +ENV PWB_STARTUP_DEBUG=0 +ENV PWB_LICENSE="" +ENV PWB_LICENSE_SERVER="" +ENV PWB_TESTUSER="" +ENV PWB_TESTUSER_PASSWD="" +ENV PWB_TESTUSER_UID="" +ENV PWB_LAUNCHER=true +ENV PWB_LAUNCHER_TIMEOUT=10 +ENV PWB_DIAGNOSTIC_DIR=/var/log/rstudio +ENV PWB_DIAGNOSTIC_ENABLE=false +ENV PWB_EXIT_AFTER_VERIFY=false + +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +### Pre-create rstudio-server user (uid/gid 999) before any installs ### +COPY --chmod=0755 workbench/scripts/precreate_rstudio_user.sh /tmp/precreate_rstudio_user.sh +RUN /tmp/precreate_rstudio_user.sh && \ + rm -f /tmp/precreate_rstudio_user.sh + +### Setup environment ### +RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ + apt-get update -yqq --fix-missing && \ + apt-get upgrade -yqq && \ + apt-get dist-upgrade -yqq && \ + apt-get autoremove -yqq --purge && \ + apt-get install -yqq --no-install-recommends \ + curl \ + ca-certificates \ + gnupg \ + tar && \ + apt-get install -yqq --no-install-recommends locales && \ + localedef -i en_US -f UTF-8 en_US.UTF-8 && \ + bash -c "$(curl -1fsSL 'https://dl.posit.co/public/pro/setup.deb.sh')" && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 + +## Install Apt Packages ### +COPY workbench/2026.08/deps/ubuntu-26.04_packages.txt /tmp/packages.txt +RUN apt-get update -yqq && \ + xargs -a /tmp/packages.txt apt-get install -yqq --no-install-recommends && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* + +### Install wait-for-it ### +COPY --chmod=0755 workbench/scripts/wait-for-it.sh /usr/local/bin/wait-for-it.sh + +### Install Workbench 2026.08.0+187.pro5 ### +ARG WORKBENCH_VERSION="2026.08.0+187.pro5" +COPY --chmod=0755 workbench/2026.08/scripts/install_workbench.sh /tmp/install_workbench.sh +RUN \ + /tmp/install_workbench.sh && \ + rm -f /tmp/install_workbench.sh + +### Install Quarto to PATH ### +RUN ln -s /lib/rstudio-server/bin/quarto/bin/quarto /usr/local/bin/quarto + +### Copy startup scripts ### +COPY --chmod=0775 "workbench/2026.08/scripts/startup.sh" /usr/local/bin/startup.sh +COPY "workbench/2026.08/startup/launcher" /startup/launcher +COPY "workbench/2026.08/startup/base" /startup/base +COPY "workbench/2026.08/startup/supervisord.conf" /etc/supervisor/supervisord.conf +COPY "workbench/2026.08/conf/jupyter/*" "workbench/2026.08/conf/launcher/*" "workbench/2026.08/conf/rstudio/*" "workbench/2026.08/conf/positron/*" "workbench/2026.08/conf/vscode/*" /etc/rstudio/ + +### Configure Workbench ### +RUN mkdir -p /var/lib/rstudio-server/monitor/log \ + /var/lib/rstudio-server/conf \ + /var/lib/rstudio-server/body \ + /var/lib/rstudio-server/proxy \ + /var/lib/rstudio-launcher \ + /var/log/rstudio \ + /var/run/supervisor \ + && chown -R rstudio-server:rstudio-server \ + /var/lib/rstudio-server \ + /var/lib/rstudio-launcher \ + /var/log/rstudio \ + /var/run/supervisor \ + && chmod -R g+w /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor \ + && find /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor -type d -exec chmod g+s {} + \ + && mkdir -p /var/run/rstudio-server \ + && chmod 1777 /var/run/rstudio-server \ + && mkdir -p /startup/custom/ \ + && mkdir -p /startup/user-provisioning/ \ + && printf '\n# allow home directory creation\nsession required pam_mkhomedir.so skel=/etc/skel umask=0077\n' >> /etc/pam.d/common-session \ + && echo "RSPM=https://p3m.dev/cran/__linux__/resolute/latest" > /etc/rstudio/repos.conf \ + && echo "CRAN=https://p3m.dev/cran/__linux__/resolute/latest" >> /etc/rstudio/repos.conf + +EXPOSE 8787/tcp +EXPOSE 5559/tcp +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD curl -fsS http://localhost:8787/health-check || exit 1 +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/workbench/2026.08/Containerfile.ubuntu2604.std b/workbench/2026.08/Containerfile.ubuntu2604.std new file mode 100644 index 00000000..627a6838 --- /dev/null +++ b/workbench/2026.08/Containerfile.ubuntu2604.std @@ -0,0 +1,167 @@ +# Build Python using uv in a separate stage +FROM ghcr.io/astral-sh/uv:debian-slim AS python-builder + +ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy +ENV UV_PYTHON_INSTALL_DIR=/opt/python +ENV UV_PYTHON_PREFERENCE=only-managed +RUN uv python install 3.14.7 +RUN mv /opt/python/cpython-3.14.7-linux-*/ /opt/python/3.14.7 + + +FROM docker.io/library/ubuntu:26.04 +LABEL org.opencontainers.image.base.name="docker.io/library/ubuntu:26.04" + +### ARG declarations ### +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILDARCH +ARG TARGETARCH=${BUILDARCH} +ARG RSTUDIO_INSTALL_NO_LICENSE_INITIALIZATION=1 + +ENV PWB_STARTUP_DEBUG=0 +ENV PWB_LICENSE="" +ENV PWB_LICENSE_SERVER="" +ENV PWB_TESTUSER="" +ENV PWB_TESTUSER_PASSWD="" +ENV PWB_TESTUSER_UID="" +ENV PWB_LAUNCHER=true +ENV PWB_LAUNCHER_TIMEOUT=10 +ENV PWB_DIAGNOSTIC_DIR=/var/log/rstudio +ENV PWB_DIAGNOSTIC_ENABLE=false +ENV PWB_EXIT_AFTER_VERIFY=false +ENV PWB_SSSD=true + +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +### Pre-create rstudio-server user (uid/gid 999) before any installs ### +COPY --chmod=0755 workbench/scripts/precreate_rstudio_user.sh /tmp/precreate_rstudio_user.sh +RUN /tmp/precreate_rstudio_user.sh && \ + rm -f /tmp/precreate_rstudio_user.sh + +### Setup environment ### +RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ + apt-get update -yqq --fix-missing && \ + apt-get upgrade -yqq && \ + apt-get dist-upgrade -yqq && \ + apt-get autoremove -yqq --purge && \ + apt-get install -yqq --no-install-recommends \ + curl \ + ca-certificates \ + gnupg \ + tar && \ + apt-get install -yqq --no-install-recommends locales && \ + localedef -i en_US -f UTF-8 en_US.UTF-8 && \ + bash -c "$(curl -1fsSL 'https://dl.posit.co/public/pro/setup.deb.sh')" && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 + +## Install Apt Packages ### +COPY workbench/2026.08/deps/ubuntu-26.04_packages.txt /tmp/packages.txt +COPY workbench/2026.08/deps/ubuntu-26.04_optional_packages.txt /tmp/optional_packages.txt +RUN apt-get update -yqq && \ + xargs -a /tmp/packages.txt apt-get install -yqq --no-install-recommends && \ + xargs -a /tmp/optional_packages.txt apt-get install -yqq --no-install-recommends && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* + + +### Install wait-for-it ### +COPY --chmod=0755 workbench/scripts/wait-for-it.sh /usr/local/bin/wait-for-it.sh + +### Install R ### +RUN RUN_UNATTENDED=1 R_VERSION=4.6.1 bash -c "$(curl -fsSL https://rstd.io/r-install)" && \ + find . -type f -name '[rR]-4.6.1.*\.(deb|rpm)' -delete + +### Install Python from previous stage ### +COPY --from=python-builder /opt/python /opt/python + +### Install Jupyter ### +RUN /opt/python/3.14.7/bin/python -m venv /opt/python/jupyter && \ + /opt/python/jupyter/bin/pip install --no-cache-dir --upgrade pip setuptools wheel && \ + /opt/python/jupyter/bin/pip install --no-cache-dir --upgrade \ + "jupyterlab<5" \ + notebook \ + "pwb_jupyterlab<2" && \ + rm -rf /opt/python/jupyter/lib/python*/site-packages/jupyterlab/tests && \ + rm -rf /opt/python/jupyter/lib/python*/site-packages/jupyterlab/galata && \ + rm -f /opt/python/jupyter/lib/python*/site-packages/jupyterlab/staging/yarn.lock && \ + ln -s /opt/python/jupyter/bin/jupyter /usr/local/bin/jupyter + +### Install Jupyter kernels ### +RUN /opt/python/3.14.7/bin/pip install --no-cache-dir --upgrade --break-system-packages \ + ipykernel && \ + /opt/python/3.14.7/bin/python -m ipykernel install --user --name python3.14.7 --display-name "Python 3.14.7" + +### Install Pro Drivers ### +RUN apt-get update -yqq && \ + apt-get install -yqq --no-install-recommends \ + rstudio-drivers && \ + apt-get clean -yqq && \ + rm -rf /var/lib/apt/lists/* +RUN cp /opt/rstudio-drivers/odbcinst.ini.sample /etc/odbcinst.ini + +### Install Workbench 2026.08.0+187.pro5 ### +ARG WORKBENCH_VERSION="2026.08.0+187.pro5" +COPY --chmod=0755 workbench/2026.08/scripts/install_workbench.sh /tmp/install_workbench.sh +RUN \ + /tmp/install_workbench.sh && \ + rm -f /tmp/install_workbench.sh + +### Install Quarto to PATH ### +RUN ln -s /lib/rstudio-server/bin/quarto/bin/quarto /usr/local/bin/quarto + +### Copy startup scripts ### +COPY --chmod=0775 "workbench/2026.08/scripts/startup.sh" /usr/local/bin/startup.sh +COPY --chmod=0755 workbench/scripts/entrypoint.sh /usr/local/bin/entrypoint.sh +COPY "workbench/2026.08/startup/launcher" /startup/launcher +COPY "workbench/2026.08/startup/base" /startup/base +COPY "workbench/2026.08/startup/supervisord.conf" /etc/supervisor/supervisord.conf +COPY --chmod=600 "workbench/2026.08/conf/sssd/sssd.conf" /etc/sssd/sssd.conf +COPY "workbench/2026.08/startup/user-provisioning/sssd.conf" /opt/startup-templates/sssd.conf +COPY "workbench/2026.08/conf/jupyter/*" "workbench/2026.08/conf/launcher/*" "workbench/2026.08/conf/rstudio/*" "workbench/2026.08/conf/positron/*" "workbench/2026.08/conf/vscode/*" /etc/rstudio/ + +### Configure Workbench ### +RUN mkdir -p /var/lib/rstudio-server/monitor/log \ + /var/lib/rstudio-server/conf \ + /var/lib/rstudio-server/body \ + /var/lib/rstudio-server/proxy \ + /var/lib/rstudio-launcher \ + /var/log/rstudio \ + /var/run/supervisor \ + && chown -R rstudio-server:rstudio-server \ + /var/lib/rstudio-server \ + /var/lib/rstudio-launcher \ + /var/log/rstudio \ + /var/run/supervisor \ + && chmod -R g+w /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor \ + && find /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor -type d -exec chmod g+s {} + \ + && mkdir -p /var/run/rstudio-server \ + && chmod 1777 /var/run/rstudio-server \ + && mkdir -p /startup/custom/ \ + && mkdir -p /startup/user-provisioning/ \ + && printf '\n# allow home directory creation\nsession required pam_mkhomedir.so skel=/etc/skel umask=0077\n' >> /etc/pam.d/common-session \ + && echo "RSPM=https://p3m.dev/cran/__linux__/resolute/latest" > /etc/rstudio/repos.conf \ + && echo "CRAN=https://p3m.dev/cran/__linux__/resolute/latest" >> /etc/rstudio/repos.conf + +### Install TinyTeX using Quarto ### +# Caches won't invalidate correctly on new releases for TinyTeX installs. This ADD instruction is a workaround to bust +# the cache on new releases. +# +# TinyTeX is installed under HOME="/opt" so the install lands at /opt/.TinyTeX, +# which is readable by non-root runtime users. `--update-path` makes tlmgr +# symlink the TinyTeX binaries into /usr/local/bin. +# TODO: Remove `HOME="/opt"` once Quarto supports custom install locations +# for TinyTeX, see https://github.com/quarto-dev/quarto-cli/issues/11800. +ADD https://github.com/rstudio/tinytex-releases/releases/latest /tmp/tinytex-release.json +RUN --mount=type=secret,id=github_token,required=false \ + GH_TOKEN="$([ -s /run/secrets/github_token ] && cat /run/secrets/github_token)" HOME="/opt" CI=true /lib/rstudio-server/bin/quarto/bin/quarto install tinytex --no-prompt --update-path \ + && rm -f /tmp/tinytex-release.json + +EXPOSE 8787/tcp +EXPOSE 5559/tcp +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD curl -fsS http://localhost:8787/health-check || exit 1 +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/workbench/2026.08/deps/ubuntu-26.04_optional_packages.txt b/workbench/2026.08/deps/ubuntu-26.04_optional_packages.txt new file mode 100644 index 00000000..03766c20 --- /dev/null +++ b/workbench/2026.08/deps/ubuntu-26.04_optional_packages.txt @@ -0,0 +1,85 @@ +autoconf +automake +cmake +gfortran +make +patch +pkg-config +bzip2 +unzip +xz-utils +zip +libbz2-dev +liblzma-dev +zlib1g-dev +libcurl4-openssl-dev +libsodium-dev +libssh2-1-dev +libffi-dev +libpcre2-dev +libreadline-dev +libicu-dev +libxml2-dev +libxslt1-dev +default-libmysqlclient-dev +libsqlite3-dev +unixodbc-dev +git +libgit2-dev +openssh-client +wget +gdal-bin +libgdal-dev +libgeos-dev +libproj-dev +libudunits2-dev +fonts-dejavu-core +fonts-liberation +ghostscript +gsfonts +imagemagick +libcairo2-dev +libfontconfig1-dev +libfreetype-dev +libfribidi-dev +libharfbuzz-dev +libjpeg-dev +libmagick++-dev +libpango1.0-dev +libpng-dev +libtiff-dev +libwebp-dev +libglpk-dev +libgmp3-dev +libgsl-dev +libmpfr-dev +libabsl-dev +libnode-dev +libprotobuf-dev +libprotoc-dev +libuv1-dev +protobuf-compiler +libpoppler-cpp-dev +poppler-data +poppler-utils +libgl1-mesa-dev +libglu1-mesa-dev +libx11-dev +tcl +tk +tk-dev +tk-table +default-jdk +libkrb5-dev +libldap2-dev +libsasl2-dev +python3 +python3-dev +python3-venv +libapparmor1 +libedit2 +oddjob-mkhomedir +sssd +gdb +perl +strace diff --git a/workbench/2026.08/deps/ubuntu-26.04_packages.txt b/workbench/2026.08/deps/ubuntu-26.04_packages.txt new file mode 100644 index 00000000..7586568f --- /dev/null +++ b/workbench/2026.08/deps/ubuntu-26.04_packages.txt @@ -0,0 +1,12 @@ +build-essential +libc6 +libclang-dev +libpq5 +libssl-dev +libsqlite3-0 +libxkbcommon-x11-0 +lsb-release +psmisc +rrdtool +sudo +supervisor diff --git a/workbench/template/Containerfile.ubuntu2604.jinja2 b/workbench/template/Containerfile.ubuntu2604.jinja2 new file mode 100644 index 00000000..858878b7 --- /dev/null +++ b/workbench/template/Containerfile.ubuntu2604.jinja2 @@ -0,0 +1,156 @@ +{#- +Below are imports for Bakery's macros. If any are unneeded, they can be removed. +Bakery handles bootstrapping the files into template rendering. +-#} +{%- import "apt.j2" as apt -%} +{%- import "python.j2" as python -%} +{%- import "quarto.j2" as quarto -%} +{%- import "r.j2" as r -%} +{%- if Image.Variant != "Minimal" -%} +# Build Python using uv in a separate stage +{{ python.build_stage(Dependencies.python) }} + +{% endif -%} + +FROM docker.io/library/ubuntu:26.04 +LABEL org.opencontainers.image.base.name="docker.io/library/ubuntu:26.04" + +### ARG declarations ### +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILDARCH +ARG TARGETARCH=${BUILDARCH} +ARG RSTUDIO_INSTALL_NO_LICENSE_INITIALIZATION=1 + +ENV PWB_STARTUP_DEBUG=0 +ENV PWB_LICENSE="" +ENV PWB_LICENSE_SERVER="" +ENV PWB_TESTUSER="" +ENV PWB_TESTUSER_PASSWD="" +ENV PWB_TESTUSER_UID="" +ENV PWB_LAUNCHER=true +ENV PWB_LAUNCHER_TIMEOUT=10 +ENV PWB_DIAGNOSTIC_DIR=/var/log/rstudio +ENV PWB_DIAGNOSTIC_ENABLE=false +ENV PWB_EXIT_AFTER_VERIFY=false +{%- if Image.Variant != "Minimal" %} +ENV PWB_SSSD=true +{%- endif %} + +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +### Pre-create rstudio-server user (uid/gid 999) before any installs ### +COPY --chmod=0755 {{ Path.Image }}/scripts/precreate_rstudio_user.sh /tmp/precreate_rstudio_user.sh +RUN /tmp/precreate_rstudio_user.sh && \ + rm -f /tmp/precreate_rstudio_user.sh + +### Setup environment ### +{{ apt.run_setup() }} + +## Install Apt Packages ### +{% if not Image.Variant == "Minimal" -%} +COPY {{ Path.Version }}/deps/ubuntu-26.04_packages.txt /tmp/packages.txt +COPY {{ Path.Version }}/deps/ubuntu-26.04_optional_packages.txt /tmp/optional_packages.txt +{{ apt.run_install(files = ['/tmp/packages.txt', '/tmp/optional_packages.txt']) }} +{% else -%} +COPY {{ Path.Version }}/deps/ubuntu-26.04_packages.txt /tmp/packages.txt +{{ apt.run_install(files = ['/tmp/packages.txt']) }} +{%- endif %} + +### Install wait-for-it ### +COPY --chmod=0755 {{ Path.Image }}/scripts/wait-for-it.sh /usr/local/bin/wait-for-it.sh + +{% if not Image.Variant == "Minimal" -%} +### Install R ### +{{ r.run_install(Dependencies.R) }} + +### Install Python from previous stage ### +{{ python.copy_from_build_stage() }} + +### Install Jupyter ### +{{ python.run_install_jupyterlab_workbench(Dependencies.python.0, jupyterlab_version_pin = "<5", pwb_jupyterlab_version_pin = "<2") }} + +### Install Jupyter kernels ### +{% for python_version in Dependencies.python -%} +RUN {{ python.install_packages(python_version, "ipykernel") }} && \ + {{ python.get_version_directory(python_version) }}/bin/python -m ipykernel install --user --name python{{ python_version }} --display-name "Python {{ python_version }}" + +{% endfor -%} + +### Install Pro Drivers ### +{{ apt.run_install(packages="rstudio-drivers") }} +RUN cp /opt/rstudio-drivers/odbcinst.ini.sample /etc/odbcinst.ini + +{% endif -%} + +### Install Workbench {{ Image.Version }} ### +ARG WORKBENCH_VERSION="{{ Image.Version }}" +COPY --chmod=0755 {{ Path.Version }}/scripts/install_workbench.sh /tmp/install_workbench.sh +RUN {% if Image.DownloadURL is defined %}DOWNLOAD_URL="{{ Image.DownloadURL }}" {% endif %}\ + /tmp/install_workbench.sh && \ + rm -f /tmp/install_workbench.sh + +### Install Quarto to PATH ### +RUN ln -s /lib/rstudio-server/bin/quarto/bin/quarto /usr/local/bin/quarto + +### Copy startup scripts ### +COPY --chmod=0775 "{{ Path.Version }}/scripts/startup.sh" /usr/local/bin/startup.sh +{%- if Image.Variant != "Minimal" %} +COPY --chmod=0755 {{ Path.Image }}/scripts/entrypoint.sh /usr/local/bin/entrypoint.sh +{%- endif %} +COPY "{{ Path.Version }}/startup/launcher" /startup/launcher +COPY "{{ Path.Version }}/startup/base" /startup/base +COPY "{{ Path.Version }}/startup/supervisord.conf" /etc/supervisor/supervisord.conf +{%- if Image.Variant != "Minimal" %} +COPY --chmod=600 "{{ Path.Version }}/conf/sssd/sssd.conf" /etc/sssd/sssd.conf +COPY "{{ Path.Version }}/startup/user-provisioning/sssd.conf" /opt/startup-templates/sssd.conf +{%- endif %} +COPY "{{ Path.Version }}/conf/jupyter/*" "{{ Path.Version }}/conf/launcher/*" "{{ Path.Version }}/conf/rstudio/*" "{{ Path.Version }}/conf/positron/*" "{{ Path.Version }}/conf/vscode/*" /etc/rstudio/ + +### Configure Workbench ### +RUN mkdir -p /var/lib/rstudio-server/monitor/log \ + /var/lib/rstudio-server/conf \ + /var/lib/rstudio-server/body \ + /var/lib/rstudio-server/proxy \ + /var/lib/rstudio-launcher \ + /var/log/rstudio \ + /var/run/supervisor \ + && chown -R rstudio-server:rstudio-server \ + /var/lib/rstudio-server \ + /var/lib/rstudio-launcher \ + /var/log/rstudio \ + /var/run/supervisor \ + && chmod -R g+w /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor \ + && find /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor -type d -exec chmod g+s {} + \ + && mkdir -p /var/run/rstudio-server \ + && chmod 1777 /var/run/rstudio-server \ + && mkdir -p /startup/custom/ \ + && mkdir -p /startup/user-provisioning/ \ + && printf '\n# allow home directory creation\nsession required pam_mkhomedir.so skel=/etc/skel umask=0077\n' >> /etc/pam.d/common-session \ + && echo "RSPM={{ r.get_p3m_cran_repo(Image.OS) }}" > /etc/rstudio/repos.conf \ + && echo "CRAN={{ r.get_p3m_cran_repo(Image.OS) }}" >> /etc/rstudio/repos.conf + +{%- if Image.Variant != "Minimal" %} + +### Install TinyTeX using Quarto ### +# Caches won't invalidate correctly on new releases for TinyTeX installs. This ADD instruction is a workaround to bust +# the cache on new releases. +# +# TinyTeX is installed under HOME="/opt" so the install lands at /opt/.TinyTeX, +# which is readable by non-root runtime users. `--update-path` makes tlmgr +# symlink the TinyTeX binaries into /usr/local/bin. +# TODO: Remove `HOME="/opt"` once Quarto supports custom install locations +# for TinyTeX, see https://github.com/quarto-dev/quarto-cli/issues/11800. +ADD https://github.com/rstudio/tinytex-releases/releases/latest /tmp/tinytex-release.json +RUN {{ quarto.github_token_secret_mount() }} \ + {{ quarto.install_tinytex_command("/lib/rstudio-server/bin/quarto/bin/quarto", update_path=True, home_path="/opt") }} \ + && rm -f /tmp/tinytex-release.json +{%- endif %} + +EXPOSE 8787/tcp +EXPOSE 5559/tcp +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD curl -fsS http://localhost:8787/health-check || exit 1 +{%- if Image.Variant != "Minimal" %} +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] +{%- endif %} +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/workbench/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 b/workbench/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 new file mode 100644 index 00000000..ecdde123 --- /dev/null +++ b/workbench/template/deps/ubuntu-26.04_optional_packages.txt.jinja2 @@ -0,0 +1,112 @@ +{#- +Standard-variant optional apt packages for the workbench image on Ubuntu +26.04 (resolute). Mirrors the 24.04 list - see that template for selection +rationale and the bakery-issue pointer. +-#} +{# Build toolchain - source installs of compiled R/Python pkgs (Matrix, RcppArmadillo, scipy) -#} +autoconf +automake +cmake +gfortran +make +patch +pkg-config +{# Compression CLI tools - source archive extraction, Quarto bundles, conda envs -#} +bzip2 +unzip +xz-utils +zip +{# Compression headers - data.table, httpuv, Pillow, scipy, lxml from source -#} +libbz2-dev +liblzma-dev +zlib1g-dev +{# TLS / HTTP / crypto - curl, httr, httr2, openssl, urllib3, cryptography, sodium, plumber -#} +libcurl4-openssl-dev +libsodium-dev +libssh2-1-dev +{# FFI / readline / regex - Python cffi/cryptography, source rebuilds of R + Python -#} +libffi-dev +libpcre2-dev +libreadline-dev +{# XML / Unicode / text - xml2, XML, stringi, lxml, arrow -#} +libicu-dev +libxml2-dev +libxslt1-dev +{# Database client headers - RPostgres, RMariaDB, odbc, DBI, psycopg2, mysqlclient, pyodbc. + NOTE: keep default-libmysqlclient-dev. Do NOT substitute libmariadb-dev-compat -- it declares + Conflicts: libmysqlclient-dev, which libgdal-dev needs, so the swap breaks the build. -#} +default-libmysqlclient-dev +libsqlite3-dev +unixodbc-dev +{# Version control / network - gert, git2r, renv from GitHub, pip git+ installs, SSH transports -#} +git +libgit2-dev +openssh-client +wget +{# Geospatial - sf, terra, stars, geopandas, rasterio, pyproj -#} +gdal-bin +libgdal-dev +libgeos-dev +libproj-dev +libudunits2-dev +{# Graphics / fonts / imaging - ragg, systemfonts, textshaping, magick, Cairo, Pillow, matplotlib -#} +fonts-dejavu-core +fonts-liberation +ghostscript +gsfonts +imagemagick +libcairo2-dev +libfontconfig1-dev +libfreetype-dev +libfribidi-dev +libharfbuzz-dev +libjpeg-dev +libmagick++-dev +libpango1.0-dev +libpng-dev +libtiff-dev +libwebp-dev +{# Math libraries - igraph (GLPK), gmp, Rmpfr, gsl, RcppGSL, Bioconductor numerics -#} +libglpk-dev +libgmp3-dev +libgsl-dev +libmpfr-dev +{# V8 / protobuf / arrow / httpuv source build -#} +libabsl-dev +libnode-dev +libprotobuf-dev +libprotoc-dev +libuv1-dev +protobuf-compiler +{# PDF processing - pdftools, pdfminer.six, pdf2image, magick PDF rasterization -#} +libpoppler-cpp-dev +poppler-data +poppler-utils +{# X11 / OpenGL - rgl, plotly 3D, configure-script probes that test for X libs -#} +libgl1-mesa-dev +libglu1-mesa-dev +libx11-dev +{# Tcl/Tk - tcltk R pkg, Python tkinter -#} +tcl +tk +tk-dev +tk-table +{# Java - rJava, RJDBC, xlsx, JPype1; run R CMD javareconf after install -#} +default-jdk +{# Authentication / directory - mongolite, pymongo GSSAPI, python-ldap, requests-kerberos -#} +libkrb5-dev +libldap2-dev +libsasl2-dev +{# System Python - reticulate venv probes, fallback for source-built extensions on arm64 -#} +python3 +python3-dev +python3-venv +{# Workbench-server identity / PAM / SSSD / AppArmor profiles -#} +libapparmor1 +libedit2 +oddjob-mkhomedir +sssd +{# Debug / scripting - rstudio-server diagnostic flow, R configure perl scripts -#} +gdb +perl +strace diff --git a/workbench/template/deps/ubuntu-26.04_packages.txt.jinja2 b/workbench/template/deps/ubuntu-26.04_packages.txt.jinja2 new file mode 100644 index 00000000..7586568f --- /dev/null +++ b/workbench/template/deps/ubuntu-26.04_packages.txt.jinja2 @@ -0,0 +1,12 @@ +build-essential +libc6 +libclang-dev +libpq5 +libssl-dev +libsqlite3-0 +libxkbcommon-x11-0 +lsb-release +psmisc +rrdtool +sudo +supervisor From 64dbf7737ec771aea4923cea7e3e608b13c09546 Mon Sep 17 00:00:00 2001 From: "Benjamin R. J. Schwedler" Date: Fri, 14 Aug 2026 11:07:07 -0500 Subject: [PATCH 2/2] Replace stale PTI comment with Setup environment "### Initialize PTI in container ###" dates back to an early workbench-session-init design that shelled out to a standalone PTI binary (see the removed PTI_VERSION/PTI_NO_COLOR ARGs and the FIXME about PTI not yet being public). That approach was replaced by the current apt.run_setup() + rsp-session-multi-linux download, but the comment above apt.run_setup() was never updated to match. Rename it to "Setup environment", matching the label workbench's own Containerfile uses for the identical apt.run_setup() call. Applied to the template and to every already-rendered version that still carries the stale comment (2025.09 through 2026.08). --- workbench-session-init/2025.09/Containerfile.ubuntu2404 | 2 +- workbench-session-init/2026.01/Containerfile.ubuntu2404 | 2 +- workbench-session-init/2026.04/Containerfile.ubuntu2404 | 2 +- workbench-session-init/2026.05/Containerfile.ubuntu2404 | 2 +- workbench-session-init/2026.06/Containerfile.ubuntu2404 | 2 +- workbench-session-init/2026.07/Containerfile.ubuntu2404 | 2 +- workbench-session-init/2026.08/Containerfile.ubuntu2404 | 2 +- workbench-session-init/template/Containerfile.ubuntu2404.jinja2 | 2 +- workbench-session-init/template/Containerfile.ubuntu2604.jinja2 | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/workbench-session-init/2025.09/Containerfile.ubuntu2404 b/workbench-session-init/2025.09/Containerfile.ubuntu2404 index a63eeaee..9b93183c 100644 --- a/workbench-session-init/2025.09/Containerfile.ubuntu2404 +++ b/workbench-session-init/2025.09/Containerfile.ubuntu2404 @@ -6,7 +6,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ apt-get update -yqq --fix-missing && \ apt-get upgrade -yqq && \ diff --git a/workbench-session-init/2026.01/Containerfile.ubuntu2404 b/workbench-session-init/2026.01/Containerfile.ubuntu2404 index 09d39843..064656ae 100644 --- a/workbench-session-init/2026.01/Containerfile.ubuntu2404 +++ b/workbench-session-init/2026.01/Containerfile.ubuntu2404 @@ -6,7 +6,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ apt-get update -yqq --fix-missing && \ apt-get upgrade -yqq && \ diff --git a/workbench-session-init/2026.04/Containerfile.ubuntu2404 b/workbench-session-init/2026.04/Containerfile.ubuntu2404 index a10c5c0a..0382a7fc 100644 --- a/workbench-session-init/2026.04/Containerfile.ubuntu2404 +++ b/workbench-session-init/2026.04/Containerfile.ubuntu2404 @@ -6,7 +6,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ apt-get update -yqq --fix-missing && \ apt-get upgrade -yqq && \ diff --git a/workbench-session-init/2026.05/Containerfile.ubuntu2404 b/workbench-session-init/2026.05/Containerfile.ubuntu2404 index 057c3244..31a9943b 100644 --- a/workbench-session-init/2026.05/Containerfile.ubuntu2404 +++ b/workbench-session-init/2026.05/Containerfile.ubuntu2404 @@ -6,7 +6,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ apt-get update -yqq --fix-missing && \ apt-get upgrade -yqq && \ diff --git a/workbench-session-init/2026.06/Containerfile.ubuntu2404 b/workbench-session-init/2026.06/Containerfile.ubuntu2404 index c9e400d8..8264ae42 100644 --- a/workbench-session-init/2026.06/Containerfile.ubuntu2404 +++ b/workbench-session-init/2026.06/Containerfile.ubuntu2404 @@ -6,7 +6,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ apt-get update -yqq --fix-missing && \ apt-get upgrade -yqq && \ diff --git a/workbench-session-init/2026.07/Containerfile.ubuntu2404 b/workbench-session-init/2026.07/Containerfile.ubuntu2404 index adb3ffa1..b5cfa815 100644 --- a/workbench-session-init/2026.07/Containerfile.ubuntu2404 +++ b/workbench-session-init/2026.07/Containerfile.ubuntu2404 @@ -6,7 +6,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ apt-get update -yqq --fix-missing && \ apt-get upgrade -yqq && \ diff --git a/workbench-session-init/2026.08/Containerfile.ubuntu2404 b/workbench-session-init/2026.08/Containerfile.ubuntu2404 index 80f35048..93f515a5 100644 --- a/workbench-session-init/2026.08/Containerfile.ubuntu2404 +++ b/workbench-session-init/2026.08/Containerfile.ubuntu2404 @@ -6,7 +6,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### RUN echo 'Acquire::Retries "3"; Acquire::http::Timeout "30"; Acquire::https::Timeout "30";' > /etc/apt/apt.conf.d/99-retries && \ apt-get update -yqq --fix-missing && \ apt-get upgrade -yqq && \ diff --git a/workbench-session-init/template/Containerfile.ubuntu2404.jinja2 b/workbench-session-init/template/Containerfile.ubuntu2404.jinja2 index 86d08feb..4f3c24d6 100644 --- a/workbench-session-init/template/Containerfile.ubuntu2404.jinja2 +++ b/workbench-session-init/template/Containerfile.ubuntu2404.jinja2 @@ -11,7 +11,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### {{ apt.run_setup() }} # Download the RStudio Workbench session components diff --git a/workbench-session-init/template/Containerfile.ubuntu2604.jinja2 b/workbench-session-init/template/Containerfile.ubuntu2604.jinja2 index 613f8fe0..6f1abb12 100644 --- a/workbench-session-init/template/Containerfile.ubuntu2604.jinja2 +++ b/workbench-session-init/template/Containerfile.ubuntu2604.jinja2 @@ -11,7 +11,7 @@ ARG TARGETARCH=${BUILDARCH} SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -### Initialize PTI in container ### +### Setup environment ### {{ apt.run_setup() }} # Download the RStudio Workbench session components