diff --git a/.github/workflows/docker-rstudio.yml b/.github/workflows/docker-rstudio.yml new file mode 100644 index 0000000..09ae245 --- /dev/null +++ b/.github/workflows/docker-rstudio.yml @@ -0,0 +1,34 @@ +name: RStudio +on: + workflow_dispatch: null + push: + paths: ['images/*'] +jobs: + build: + runs-on: ubuntu-latest + permissions: write-all + steps: + # For biggish images, github actions runs out of disk space. + # So we cleanup some unwanted things in the disk image, and reclaim that space for our docker use + # https://github.com/actions/virtual-environments/issues/2606#issuecomment-772683150 + # and https://github.com/easimon/maximize-build-space/blob/b4d02c14493a9653fe7af06cc89ca5298071c66e/action.yml#L104 + # This gives us a total of about 52G of free space, which should be enough for now + - name: cleanup disk space + run: | + sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc + df -h + - uses: actions/checkout@v3 + - name: Login to GitHub Container Registry + if: github.repository == 'boettiger-lab/k8s' + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{github.actor}} + password: ${{secrets.GITHUB_TOKEN}} + - name: Build the Docker image + if: github.repository == 'boettiger-lab/k8s' + run: docker build images/ --tag ghcr.io/boettiger-lab/k8s-r:latest + - name: Publish + if: github.repository == 'boettiger-lab/k8s' + run: docker push ghcr.io/boettiger-lab/k8s-r:latest + diff --git a/images/Dockerfile.R b/images/Dockerfile.R new file mode 100644 index 0000000..34b1e58 --- /dev/null +++ b/images/Dockerfile.R @@ -0,0 +1,45 @@ +FROM quay.io/jupyter/pytorch-notebook:cuda12-ubuntu-24.04 +COPY jupyter-ai.yml environment.yml + +RUN conda update -n base -c conda-forge conda && \ + conda env update --file environment.yml + +USER root +RUN curl -fsSL https://code-server.dev/install.sh | sh && rm -rf .cache +RUN git config --system pull.rebase false && \ + echo '"\e[5~": history-search-backward' >> /etc/inputrc && \ + echo '"\e[6~": history-search-forward' >> /etc/inputrc + +RUN usermod -a -G staff ${NB_USER} \ + && echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \ + && locale-gen en_US.utf8 \ + && /usr/sbin/update-locale LANG=en_US.UTF-8 + +## Set some variables +ENV LC_ALL en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV DEBIAN_FRONTEND noninteractive +ENV TZ UTC + +RUN curl -fsSL https://raw.githubusercontent.com/eddelbuettel/r2u/refs/heads/master/inst/scripts/add_cranapt_noble.sh | sh +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + r-base r-base-dev r-recommended \ + r-cran-docopt r-cran-littler r-cran-remotes \ + python3-dbus python3-gi python3-apt sudo \ + && Rscript -e 'install.packages("bspm")' \ + ## Support user-level installation of R packages + && chown root:staff /usr/lib/R/site-library \ + && chmod g+ws /usr/lib/R/site-library \ + && echo "options(bspm.sudo = TRUE)" >> /usr/lib/R/etc/Rprofile.site + +## add user to sudoers +RUN echo "${NB_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +## RStudio +RUN conda install jupyter-rsession-proxy +COPY install_rstudio.sh install_rstudio.sh +RUN bash install_rstudio.sh + +USER ${NB_USER} + diff --git a/images/install_rstudio.sh b/images/install_rstudio.sh new file mode 100644 index 0000000..9e451d8 --- /dev/null +++ b/images/install_rstudio.sh @@ -0,0 +1,75 @@ +#!/bin/bash +set -e + +RSTUDIO_VERSION=${1:-${RSTUDIO_VERSION:-"stable"}} +DEFAULT_USER=${DEFAULT_USER:-"rstudio"} + +apt-get update && apt-get -y install \ + ca-certificates \ + gdebi-core \ + git \ + libclang-dev \ + libssl-dev \ + lsb-release \ + psmisc \ + pwgen \ + sudo \ + wget + +ARCH=$(dpkg --print-architecture) +UBUNTU_CODENAME="noble" + +## Download RStudio Server for Ubuntu 18+ +DOWNLOAD_FILE=rstudio-server.deb + +if [ "$RSTUDIO_VERSION" = "latest" ]; then + RSTUDIO_VERSION="stable" +fi + +if [ "$UBUNTU_CODENAME" = "focal" ]; then + UBUNTU_CODENAME="bionic" +fi + +# TODO: remove this workaround for Ubuntu 24.04 +if [ "$UBUNTU_CODENAME" = "noble" ]; then + UBUNTU_CODENAME="jammy" +fi + +if [ "$RSTUDIO_VERSION" = "stable" ] || [ "$RSTUDIO_VERSION" = "preview" ] || [ "$RSTUDIO_VERSION" = "daily" ]; then + if [ "$UBUNTU_CODENAME" = "bionic" ]; then + UBUNTU_CODENAME="focal" + fi + wget "https://rstudio.org/download/latest/${RSTUDIO_VERSION}/server/${UBUNTU_CODENAME}/rstudio-server-latest-${ARCH}.deb" -O "$DOWNLOAD_FILE" +else + wget "https://download2.rstudio.org/server/${UBUNTU_CODENAME}/${ARCH}/rstudio-server-${RSTUDIO_VERSION/"+"/"-"}-${ARCH}.deb" -O "$DOWNLOAD_FILE" || + wget "https://s3.amazonaws.com/rstudio-ide-build/server/${UBUNTU_CODENAME}/${ARCH}/rstudio-server-${RSTUDIO_VERSION/"+"/"-"}-${ARCH}.deb" -O "$DOWNLOAD_FILE" +fi + +gdebi --non-interactive "$DOWNLOAD_FILE" +rm "$DOWNLOAD_FILE" + +ln -fs /usr/lib/rstudio-server/bin/rstudio-server /usr/local/bin +ln -fs /usr/lib/rstudio-server/bin/rserver /usr/local/bin + +# https://github.com/rocker-org/rocker-versioned2/issues/137 +rm -f /var/lib/rstudio-server/secure-cookie-key + +## RStudio wants an /etc/R, will populate from $R_HOME/etc +mkdir -p /etc/R + +## Make RStudio compatible with case when R is built from source +## (and thus is at /usr/local/bin/R), because RStudio doesn't obey +## path if a user apt-get installs a package +R_BIN="$(which R)" +echo "rsession-which-r=${R_BIN}" >/etc/rstudio/rserver.conf +## use more robust file locking to avoid errors when using shared volumes: +echo "lock-type=advisory" >/etc/rstudio/file-locks + +## Prepare optional configuration file to disable authentication +## To de-activate authentication, `disable_auth_rserver.conf` script +## will just need to be overwrite /etc/rstudio/rserver.conf. +## This is triggered by an env var in the user config +cp /etc/rstudio/rserver.conf /etc/rstudio/disable_auth_rserver.conf +echo "auth-none=1" >>/etc/rstudio/disable_auth_rserver.conf + + diff --git a/jupyterhub/public-config.yaml b/jupyterhub/public-config.yaml index 64f7b89..41895b9 100644 --- a/jupyterhub/public-config.yaml +++ b/jupyterhub/public-config.yaml @@ -37,6 +37,8 @@ singleuser: # https://github.com/jupyterlab/jupyterlab/issues/11304#issuecomment-945466766 ContentsManager: allow_hidden: true + FileContentsManager: + always_delete_dir: true profileList: - display_name: "CPU" slug: rocker