Apptainer

The latest version of Apptainer is installed directly on the host operating system of both the login and compute nodes. We recommend using this system-wide version and advise against attempting to load Apptainer via environment modules. Loading the Apptainer module will trigger a message stating: "The Apptainer environment module has been removed since the system Apptainer is now just as recent
Description¶
Apptainer (formerly Singularity) simplifies the creation and execution of containers, ensuring software components are encapsulated for portability and reproducibility
Home page : https://apptainer.org
Github : https://github.com/apptainer/apptainer
License¶
Apptainer is open source software, distributed under the BSD License.
How to pull
/ build
/ inspect
/ execute a container with shell
, exec
, run
¶
Set up APPTAINER_TMPDIR and APPTAINER_CACHEDIR before using Apptainer to avoid using your home directory for temporary and cache operations
By default, Apptainer will attempt to use your home directory for all operations, creating a hidden directory ~/.apptainer for this purpose. Since home directories are limited to 20GB, we recommend redirecting these operations to the nobackup filesystem. This can be achieved by setting the following environment variables before running Apptainer ( we are using the hypothetical path /nesi/nobackup/nesi12345/apptainer-cache
to demonstrate this. Please make sure to replace nesi12345
with your project code and then apptainer-cache
with a valid directory)
export APPTAINER_CACHEDIR="/nesi/nobackup/nesi12345/apptainer-cache"
export APPTAINER_TMPDIR=${APPTAINER_CACHEDIR}
Add those environment variables to your ~/.bashrc
for future use
We recommend adding those environment variables to your ~/.bashrc
to make the future use cases of Apptainer. Please make sure to replace /nesi/nobackup/nesi12345/apptainer-cache
with your nobackup directory.
echo 'export APPTAINER_CACHEDIR="/nesi/nobackup/nesi12345/apptainer-cache"' >> ~/.bashrc
echo 'export APPTAINER_TMPDIR=${APPTAINER_CACHEDIR}' >> ~/.bashrc
1. How to pull a container image from an upstream registry such as docker hub
Docker containers ( primarily stored in https://hub.docker.com/) can be pulled as Apptainer container images. For an example, if we want to pull the latest version of Tensorflow (GPU) container provided by the Tensorflow developers
-
Search and find the container registry for TF in https://hub.docker/com.
- image we are after in this instance is https://hub.docker.com/r/tensorflow/tensorflow/tags
-
Copy tthe version you prefer with blue Copy button next to the corresponding tag. We will use
latest-gpu
as an example- It will be in the form of
docker pull tensorflow/tensorflow:latest-gpu
- IN order to pull this as an apptainer, remove the word
pull
and create a URL asdocker://tensorflow/tensorflow:latest-gpu
- It will be in the form of
- Then pull it with
apptainer pull nameforthelocalimage.aif docker://tensorflow/tensorflow:latest-gpu
nameforthelocalimage.aif
is the name of the file to be saved once pulled. File extension can be anything but it is ideal to use.aif
making it easier to idenity the container image
apptainer pull tensorflow-latest-gpu.aif docker://tensorflow/tensorflow:latest-gpu
2. How to build a container with apptainer build --force --fakeroot
Although we do not have a dedicated sandbox to build containers at the moment, fakeroot
is enabled in both the login nodes and compute nodes allowing researchers to build containers as needed
- Since some container builds can consume a reasonable amount of CPUS and memory, our recommendation is to do this via a Slurm job ( interactive or batch queue). We will demonstrate this via the latter option
- You will be required to prepare your container definition file ( It will be difficult for NeSI support to provide extensive support on writing container definition files but there are a number of online resources/tutorials with instructions/templates)
- To illustrate this functionality, create an example container definition file my_container.def from a shell session on NeSI as follows:
cat << EOF > my_container.def
BootStrap: docker
From: ubuntu:20.04
%post
apt-get -y update
apt-get install -y wget
EOF
- Then submit the following Slurm job submission script to build the container:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
- If you encounter the following error when using a base Docker image in your Apptainer definition file
While making image from oci registry: error fetching image to cache: while building SIF from layers: conveyor failed to get: unsupported image-specific operation on artifact with type "application/vnd.docker.container.image.v1+json"
- Other limitations
- This method, using
fakeroot
, is known to not work for all types of Apptainer/Singularity containers. If you encounter an issue, please Contact our Support Team
- This method, using
3. Running a container, both interactively ( only the shell
or inspect
) and via Slurm
-
To have a look at the contents of your container, you can "shell" into it using
apptainer shell containername
.Note - Above shell command will enter the shell within the container image. Note the prompt is now prefixed with "Apptainer",apptainer shell my_container.aif
Exit the container by running the commandApptainer>
exit
which will bring you back to the host systemApptainer> exit
-
To view metadata and configuration details about an Apptainer container image, use
apptainer inspect containername
apptainer inspect my_container.aif
-
apptainer exec
command- The
apptainer exec
command allows you to run a specific command inside an Apptainer container, making it ideal for executing scripts, tools, or workflows within the container’s environment. For example, you can run a Python script or query the container’s filesystem without entering an interactive shell. Let't say you have a python script ( let's call it my_tensorflow.py) using Tensorflow libraries with a help menu and assuming you have Tensorflow container with all required libraries
apptainer exec tensorflow-latest-gpu.aif my_tensorflow.py --help
- The
-
The apptainer
run
command, on the other hand, is designed to execute the default process defined in the container (such as its runscript), providing a convenient way to start the container’s main application or service as intended by its creator. This is commonly used when you want to use the container as a standalone executable.
Slurm tempalte
#!/bin/bash -e
#SBATCH --job-name=tensorflow-via-apptainer
#SBATCH --time=01:00:00
#SBATCH --mem=4G
#SBATCH --ntasks=
#SBATCH --cpus-per-task=4
# Run container %runscript
apptainer exec tensorflow-latest-gpu.aif my_tensorflow.py some_argument
4. Accessing a GPU via Appptainer
-
If your Slurm job has requested access to an NVIDIA GPU (see GPU use on NeSI to learn how to request a GPU), an Apptainer container can transparently access it using the --nv flag:
apptainer exec --nv my_container.sif
-
For an example,
apptainer exec --nv tensorflow-latest-gpu.aif my_tensorflow.py some_argument
5. Network isolation
-
Apptainer allows you to configure network isolation for containers using the
--net
flag with commands likeapptainer exeec --net
. By default, this isolates the container’s network to a loopback interface, meaning it cannot communicate with the host or external networks unless additional network types are specified. Administrators can enable advanced network types (such as bridge or ptp) for privileged users, but for most users,--net
alone provides strong network isolation for security and reproducibilityapptainer exec --nv --net --network=none tensorflow-latest-gpu.aif
Tips & Tricks
- Try to configure all software to run in user space without requiring privilege escalation via "sudo" or other privileged capabilities such as reserved network ports - although Singularity supports some of these features inside a container on some systems, they may not always be available on the HPC or other platforms, therefore relying on features such as Linux user namespaces could limit the portability of your container
- If your container runs an MPI application, make sure that the MPI distribution that is installed inside the container is compatible with Intel MPI
- Write output data and log files to the HPC file system using a directory that is bound into the container - this helps reproducibility of results by keeping the container image immutable, it makes sure that you have all logs available for debugging if a job crashes, and it avoids inflating the container image file