Apptainer Guide
Apptainer is the most widely used container system for HPC. It is a replacement (or next generation) for Singularity supported by the Linux Foundation.
Containers are a way to isolate your software and make it portable and reproducible. It is a valuable asset for reproducible science and, in addition, Its use is especially recommended when
Users rely on “old” libraries (e.g., HDF4);
Users need to update their library constantly;
It also makes the user more independent of the cluster admins.
In this tutorial, we will show how to build your own containers on the cluster and submit jobs using containers.
Instructions
The steps to build (or submit a job using) a container always start with loading the apptainer
module as follows
module load apptainer
For the next step, we have two options: 1) to just use a prebuilt image, or 2) to use a .def
file (called recipe) that will contain the instructions to build the container. When using the latter option, we can build our container on top of another prebuilt image.
An image in the context of containers is a snapshot of an operating system (OS) along with a set of tools. For instance, an specific compiler. More information about the differences between containers and images can be found here.
Building the container takes only one line of code, the structure (when building directly from a prebuilt image) is as follows
apptainer build [OPTION] <name-for-the-container> <library>://<prebuilt-image>
In order to know all the available “options”, one can run apptainer build --help
. For the <library>
part, usually we rely on DockerHub (for more options see the apptainer documentation). In general, we are interested in building a container image that is a single .sif
file that can be transferred between computers. However, there is an interesting option called --sandbox
, which creates an expandable container image. Sandboxes will be useful when trying to build a custom image. However, this type of container has two side effects. First, these containers take up more space. Secondly, they are not reproducible.
Building a container from a prebuilt image - sf
and R
In the first example, we will build a container from a prebuilt image made available by the Rocker project https://rocker-project.org/images/versioned/rstudio.html.
module load apptainer/1.1.3
apptainer build --force geospatial.sif docker://rocker/geospatial
There are many ways to interact with a built image. The most commonly used are shell
and exec
. The former is useful to check if “everything is in place”, while the latter is employed to execute commands within the container. Typically, we will use the exec
command within sbatch
scripts.
Below we are using shell
to check whether sf
and terra
are among the installed packages.
Submitting a job using the newly created container
We can execute our own scripts within the container as follows:
For instance, consider creating a script called my-script.R
with the content below
Now, let’s create a file to submit our job using sbatch
. Create a file called submit.sh
containing the code provided below.
This submission file will run on the debug
partition. Errors and warnings will be saved on the job_%A.err
file, while the output will be written into the job_%A.out
file. So, to make it clear, we are running our script called my-script.R
using the command Rscript --vanilla
from within the container called geospatial.sif
. Run sbatch submit.sh
to submit the job.