Customize Your R Apptainer

Other than using the Apptainer container we provide (.sif), you can customize it on top of that.

To create an Apptainer container you first need to prepare the definition file, and then just use this definition file to generate the SIF container file on the Discovery compute node.

Prepare the definition file

This section will use r_jag.def as an example.

The full r_jag.def file can be found at the end of this page, and you can modify it to suit your needs.

To learn more about the Header and Sections of the definition file, check out the Build Recipe.

In order to avoid problems related to Discovery settings, we recommend to use our container as base image.

Our containers typically provide a generic environment on which you can install more of what you need.

You can follow the workflow below.

Find the SIF file provided by the HPC team on Discovery

The first step is to find the file path of the container SIF file which you want to use as base image.

--- 1. Use module spider learn how to load the SIF file

module spider r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF
-----------------------------------------------
  r: r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF
-----------------------------------------------

    You will need to load all module(s) on any one of the lines below before the "r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF" module is available to load.

      custom/2024a

    Help:
      For help contact your site administrators.

--- 2. Load the module

module load custom/2024a
module load r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF

--- 3. Get the path

After it’s loaded, its path is stored in the $SIF variable.

echo $SIF
/fs1/software/sstack/rhel_8/stacks/custom/2024a/packages/r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF/R.sif

Use SIF file provided by the HPC team on Discovery as base image

With the file path, here is an example of using r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF as base image:

At the very beginning of the definition file, you need to set up the BootStrap and From.

BootStrap: localimage
From: /fs1/software/sstack/rhel_8/stacks/custom/2024a/packages/r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF/R.sif
  • Bootstrap: This field indicates which bootstrap the Apptainer uses to build the container. In this example, localimage indicates that a local container image is used as the base image.

  • From: Specifies the location of the base image.

Install what you need

You can check out the Build Recipe for more information about different sections in .def file.

The %post section contains the scripts that need to be executed when building the container.

For example, if you want to install another R package 'CausalImpact', you can add:

R -e "install.packages('CausalImpact', dependencies=TRUE)"
  • R: This is the command to start the R command line interface.

  • -e:This allows you to run R code directly from a terminal or script without going to R’s interactive command-line interface.

In r_jag.def, we are trying to install JAGS and additional R packages needed.

%post
# Install Additional System Packages
dnf install -y gdal gdal-devel lapack lapack-devel proj proj-devel sqlite sqlite-devel geos geos-devel

# Install JAGS
JAGS_BRANCH=4.x
JAGS_VERSION=4.3.2
curl -OL https://sourceforge.net/projects/mcmc-jags/files/JAGS/${JAGS_BRANCH}/Source/JAGS-${JAGS_VERSION}.tar.gz
tar -xzf JAGS-${JAGS_VERSION}.tar.gz
pushd  JAGS-${JAGS_VERSION}
./configure
make
make check
make install
make installcheck
popd
rm -rf JAGS-${JAGS_VERSION}.tar.gz JAGS-${JAGS_VERSION}

# Install Additional R Packages
R -e "install.packages(c('boot', 'raster', 'Rbeast', 'R2jags', 'coda', 'rjags', 'jagsUI'), dependencies = TRUE)"

# cleanup dnf
dnf clean all
rm -rf /var/cache/dnf/*

Build the Container

Reminder

First as a reminder, if you want to build an Apptainer container, please don’t do it on the Login Node.

You should build it on a Compute Node by running an interactive job, or even simpler: using Open OnDemand’s Interactive Shell App.

The second reminder is, you may need more memory than you think to build a container. You will see the error message if the memory is not enough:

While performing build: while creating squashfs: create command failed: signal: killed:

How to build the container using base image

Go to the location of your definition file, run:

apptainer build --bind="/fs1" r_jag.sif r_jag.def
  • --bind="/fs1" is required so that we can use the local repository mirror r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF.

  • r_jag.sif is the output SIF file. You can name it whatever you like.

  • r_jag.def is the definition file we just prepared.

Note that --bind="/fs1" is required because the base image we used needs it. If you use other container as base image, it may not be needed.

Now you only need to wait, until you see:

INFO:    Adding testscript
INFO:    Running testscript
INFO:    Creating SIF file...
INFO:    Build complete: r_jag.sif

You will find R_4.3.2_custom.sif in the current folder.

Build a Container with New R Version Using Rocky Linux Base Image

Use SIF file provided by the HPC team on Discovery as base image to customize your own container is intuitive and convenient, but what if the R version you need is not provided?

You can create a definition file from scratch, but since Discovery requires some specific system-level settings, we recommend using the Rocky Linux Base Image to avoid problems related to Discovery settings.

You can find our Rocky Linux base image under /fs1/software/containers/.

An example of creating an R 4.3.2 Apptainer container using rocky9.sif as base image:

BootStrap: localimage
From: /fs1/software/containers/rocky_9/rocky9.sif

The full R_4.3.2.def file can be found at the end of this page, and you can modify it to suit your needs.

Definition File "r_jag.def"

BootStrap: localimage
From: /fs1/software/sstack/rhel_8/stacks/custom/2024a/packages/r/4.3.2-RStudio_Server-VSCode-Jupyter-SIF/R.sif

%post
# Install Additional System Packages
dnf install -y gdal gdal-devel lapack lapack-devel proj proj-devel sqlite sqlite-devel geos geos-devel

# Install JAGS
JAGS_BRANCH=4.x
JAGS_VERSION=4.3.2
curl -OL https://sourceforge.net/projects/mcmc-jags/files/JAGS/${JAGS_BRANCH}/Source/JAGS-${JAGS_VERSION}.tar.gz
tar -xzf JAGS-${JAGS_VERSION}.tar.gz
pushd  JAGS-${JAGS_VERSION}
./configure
make
make check
make install
make installcheck
popd
rm -rf JAGS-${JAGS_VERSION}.tar.gz JAGS-${JAGS_VERSION}

# Install Additional R Packages
R -e "install.packages(c('boot', 'raster', 'Rbeast', 'R2jags', 'coda', 'rjags', 'jagsUI'), dependencies = TRUE)"

# cleanup dnf
dnf clean all
rm -rf /var/cache/dnf/*

%test
command -v jags &>/dev/null || exit 11

Definition File "R_4.3.2.def"

BootStrap: localimage
From: /fs1/software/containers/rocky_9/rocky9.sif

%runscript
exec "$@"

%environment
export CPATH=$CPATH:/usr/include/openmpi-x86_64
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/cuda/lib64:$LD_LIBRARY_PATH
export http_proxy="http://192.168.211.16:3128/"
export PATH=/usr/lib/rstudio-server/bin:/usr/local/cuda/bin:${PATH}
export NVIDIA_CUDNN="/usr"

%post
# Setup Environment
export CPATH=$CPATH:/usr/include/openmpi-x86_64
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/cuda/lib64:$LD_LIBRARY_PATH
export http_proxy="http://192.168.211.16:3128/"
export PATH=/usr/lib/rstudio-server/bin:/usr/local/cuda/bin:${PATH}
export NVIDIA_CUDNN="/usr"

# Set Nvida Vars
rocky_os="9"
cuda_ver="11.8"
cuda_dash="11-8"
cudnn_ver="8.8.1.3"
cudnn_ver_short="8.8.1"

# Install Additional Repos
cp -f /fs1/software/containers/rocky_${rocky_os}/nvidia/cuda/localrepo-cuda${cuda_ver}.repo /etc/yum.repos.d
cp -f /fs1/software/containers/rocky_${rocky_os}/nvidia/cudnn/localrepo-cudnn${cudnn_ver}-cuda${cuda_ver}.repo /etc/yum.repos.d

# Install Known Required Dev Tools
dnf install --refresh -y \
        "@Development Tools" \
        "@Scientific Support" \
        ca-certificates \
        cuda-toolkit-${cuda_dash} \
        curl-devel \
        fontconfig-devel \
        libcudnn8 \
        libcudnn8-devel \
        libgit2-devel \
        libxml2-devel \
        llvm llvm-devel \
        llvm-static \
        llvm-toolset \
        mariadb-connector-c-devel \
        opencv \
        opencv-devel \
        openssl-devel \
        python3-devel \
        python3-pip \
        python3-wheel \
        wget

# Install Additional Common Packages Used By R Packages
## https://clint.id.au/?p=1428
dnf module enable -y nodejs:20
dnf install -y wget nodejs nodejs-devel npm openblas java-1.8.0-openjdk-devel zlib-devel libicu-devel libpng-devel libcurl-devel libxml2-devel openssl-devel openmpi-devel netcdf4-python3 netcdf-devel netcdf proj-devel gdal-devel monitorix gnuplot ImageMagick librsvg2-devel libsodium-devel libwebp-devel cairo-devel hunspell-devel openssl-devel poppler-cpp-devel protobuf-devel mariadb-devel redland-devel cyrus-sasl-devel libtiff-devel tcl-devel tk-devel xauth mesa-libGLU-devel glpk-devel libXt-devel gsl-devel fftw-devel bzip2-devel geos-devel gtk2-devel gtk3-devel libjpeg-turbo-devel blas-devel lapack-devel mpfr-devel unixODBC-devel libsndfile-devel udunits2-devel postgresql-devel libRmath-devel qt5-devel libdb-devel octave-devel hiredis-devel poppler-glib-devel boost-devel czmq-devel ImageMagick-c++-devel file-devel opencl-headers sqlite-devel

# Handle OpenMPI ldconfig
echo "/usr/lib64/openmpi/lib" > /etc/ld.so.conf.d/openmpi.conf
ldconfig

# Install Code-Server
curl -fsSL https://code-server.dev/install.sh | sh

# Setup: Control Variables
DISTRO="el9"
R_VERSION="4.3.2"
R_SVER="$(echo $R_VERSION | cut -d '.' -f 1,2 )"
RSTUDIO_VERSION="2023.12.0-369"

# R: Install R (https://docs.rstudio.com/resources/install-r/)
curl -O https://cdn.rstudio.com/r/rhel-9/pkgs/R-${R_VERSION}-1-1.x86_64.rpm
dnf install -y R-${R_VERSION}-1-1.x86_64.rpm
rm -f R-${R_VERSION}-1-1.x86_64.rpm
ln -s /opt/R/${R_VERSION}/bin/R /usr/local/bin/R
ln -s /opt/R/${R_VERSION}/bin/Rscript /usr/local/bin/Rscript

# RStudio: Install R Studio Server
curl -O https://download2.rstudio.org/server/rhel9/x86_64/rstudio-server-rhel-${RSTUDIO_VERSION}-x86_64.rpm
dnf install -y rstudio-server-rhel-${RSTUDIO_VERSION}-x86_64.rpm
rm -f rstudio-server-rhel-${RSTUDIO_VERSION}-x86_64.rpm

# Python: Install Python Packages for Jupyter, R, and VSCode
python3 -m pip install --upgrade \
        basemap \
        ipykernel \
        ipywidgets \
        jupyterlab \
        jupyterlab-pygments \
        jupyterlab-widgets \
        matplotlib \
        notebook \
        numpy \
        opencv-contrib-python \
        opencv-python \
        pandas \
        pyqt5 \
        qtconsole \
        radian

# R: Site Profile - Add a default CRAN mirror
echo "options(repos = c(CRAN = 'https://cran.rstudio.com/'), download.file.method = 'libcurl')" >> /opt/R/${R_VERSION}/lib/R/etc/Rprofile.site

# R: Site ENV - Add Timezone
echo "TZ='$TZ'" >> /opt/R/${R_VERSION}/lib/R/etc/Renviron

# R: Site ENV - Adjust Platform and Libs
sed -i "/^R_PLATFORM=/ c\R_PLATFORM=\${R_PLATFORM-'$DISTRO-x86_64-apptainer'}" /opt/R/${R_VERSION}/lib/R/etc/Renviron
sed -i "/^R_LIBS_USER=/ c\R_LIBS_USER=\${R_LIBS_USER-'~/R/$DISTRO-x86_64-apptainer-library/$R_SVER'}" /opt/R/${R_VERSION}/lib/R/etc/Renviron

# R: Site ENV - Add Aditional Custom Vars
echo "DOWNLOAD_STATIC_LIBV8='1'" >> /opt/R/${R_VERSION}/lib/R/etc/Renviron

# R: Install Additional R Packages
R -e "install.packages(c('devtools', 'tidyverse', 'V8', 'rmarkdown', 'distill','IRkernel', 'languageserver', 'lintr', 'httpgd', 'remotes', 'BiocManager'), dependencies = TRUE)"
R -e "remotes::install_github('nx10/unigd')"
#devtools::install_github("ManuelHentschel/vscDebugger")
R -e "IRkernel::installspec(user = FALSE)"

# Cleanup Temporary Files
dnf clean all
rm -rf /var/cache/dnf/*
python3 -m pip cache purge