Using Apptainer Containers¶
This guide provides general instructions for using Apptainer to create and manage a container-based software environments.
Overview¶
Apptainer is free and open source container solution that has been created out of necessity, for scientific and application driven workloads. Apptainer - a fork of Singularity - define the "Mobility of Compute" concept as the ability to organize, create and maintain a workflow and be confident that the workflow can be executed on different hosts, operating systems (as long as it is Linux) and service providers. Being able to contain the entire software stack, from data files to library stack, and portably move it from system to system is true mobility.
Tip
ScienceCluster users can load Apptainer with:
module load apptainer
For detailed usage instructions, see the ScienceCluster Apptainer guide.
ScienceCloud users can access Singularity (instead of Apptainer) by creating an instance using one of the latest Singularity images. The latest images have *** prefix in their names - for example, ***Singularity on Ubuntu 24.04 (2024-11-21).
Other users can check Apptainer installation directions in the Official Apptainer User Guide.
For more comprehensive information, refer to:
Building an Apptainer container¶
Apptainer allows you to create portable containers using two main approaches:
- Build directly from a container registry (e.g., Docker Hub).
- Build a custom image using a definition file.
Let’s compare these two approaches and provide detailed instructions for each.
| Feature | From Container Registry | From Definition File |
|---|---|---|
| Source Image | Docker Hub or another container registry | Docker image or another Apptainer image |
| Customization | Limited (cannot modify during build) | Full customization via %post, %environment, etc. |
| Use Case | Quick start with standard tools | Add software, configurations, or build custom environments |
| Build Command | apptainer build <output.sif> docker://<image> | sudo apptainer build <output.sif> <definition.def> |
Building from a container registry¶
Container registries such as Docker Hub offer a wide range of prebuilt images you can use with Apptainer, for example:
Once you've found the software that you want, you can build an Apptainer container in the Singularity Image Format .sif (default) from a Docker image using this syntax:
apptainer build <output.sif> docker://<image>:<tag>
If you omit the <tag>, it defaults to the latest available version.
Example 1: R and Tidyverse with Rocker container¶
For example, to build a Rocker container with the most recent version of R and the tidyverse packages:
apptainer build tidyverse.sif docker://rocker/tidyverse
If you need a specific version—for instance, R 4.3.1—you can specify the tag accordingly:
apptainer build tidyverse.sif docker://rocker/tidyverse:4.3.1
You can browse available versions (tags) on the rocker/tidyverse Tags page.
To explore container interactively run shell within a container:
apptainer shell tidyverse.sif
This command starts a shell inside the container, where you can launch R.
Example 2: CPU-only and GPU-enabled TensorFlow container¶
To build TensorFlow container from Docker Hub, you'd write:
apptainer build tf.sif docker://tensorflow/tensorflow
To build GPU-enabled TensorFlow container, use the -gpu tag in the container name:
apptainer build tf-gpu.sif docker://tensorflow/tensorflow:2.15.0-gpu
Note
The latest-gpu tag of the official TensorFlow Docker image does not currently support GPU acceleration as expected. As a workaround, we recommend using the tensorflow:2.15.0-gpu version, which recognizes and utilizes available GPU resources.
Creating a custom image from a definition file¶
If you need to add software to a pre-existing Apptainer container, you'll need to use a custom definition file to "bootstrap" from a base Apptainer or Docker image. "Bootstrapping" an image means that you will be using the image as a starting point for building a custom image with additional software or configuration. The definition file .def is a plain text file that selects the starting image that you'll bootstrap as well as additional commands that will add more software to the container.
Once you've saved your definition file as a text file with a .def extension, you can then build a container in the Singularity Image Format .sif (default) from it using the following command:
sudo apptainer build <output.sif> <definition.def>
Example 1: TensorFlow container + pandas installation¶
Create the CPU-only Apptainer definition file (e.g. tensorflow-pandas.def):
Bootstrap: docker
From: tensorflow/tensorflow
%post
pip install pandas
This example uses a TensorFlow container from Docker Hub and includes a %post section to install the pandas package. In general, %post section allows users to define specific commands that can augment the container. The pip program is available as it was already installed in the TensorFlow container.
To create an image called tensorflow.sif based on definition file tensorflow-pandas.def, you would run:
sudo apptainer build tensorflow.sif tensorflow-pandas.def
This will generate a file named tensorflow.sif, but you can choose any name you prefer for the output file.
You can test the container and the version of installed pandas library:
apptainer exec tensorflow.sif python -c "import pandas as pd; print(pd.__version__)"
pandas printed to the terminal. Example 2: GPU-enabled TensorFlow container + pandas installation¶
An equivalent GPU capable Apptainer definition file (e.g. tensorflow-pandas-gpu.def) might look like this:
Bootstrap: docker
From: tensorflow/tensorflow:2.15.0-gpu
%post
pip install pandas
Build the GPU-enabled Apptainer container:
sudo apptainer build tensorflow-gpu.sif tensorflow-pandas-gpu.def
Test the container and pandas version from shell:
apptainer exec --nv tensorflow-gpu.sif python -c "import pandas as pd; print(pd.__version__)"
--nv flag is required to enable access to NVIDIA GPU resources from within the container. Furthermore, you can check the installed GPU devices recognized inside the container environment by running:
apptainer shell --nv tensorflow-gpu.sif
nvidia-smi
python -c 'import tensorflow as tf; \
print("Built with CUDA:", tf.test.is_built_with_cuda()); \
print("Num GPUs Available:", len(tf.config.list_physical_devices("GPU"))); \
print("TF version:", tf.__version__)'
Example 3: R and Tidyverse with Rocker container + custom software installation¶
A more complex example of an Apptainer definition file (e.g. tidyverse-jags.def) might look like the following:
Bootstrap: docker
From: rocker/tidyverse:4.0.3
%post
apt-get update && . /etc/environment
wget sourceforge.net/projects/mcmc-jags/files/JAGS/4.x/Source/JAGS-4.3.0.tar.gz -O jags.tar.gz
tar -xf jags.tar.gz
cd JAGS* && ./configure && make -j4 && make install
cd ~
apt-get update && . /etc/environment
wget sourceforge.net/projects/jags-wiener/files/JAGS-WIENER-MODULE-1.1.tar.gz -O jagswiener.tar.gz
tar -xf jagswiener.tar.gz
cd JAGS-WIENER-MODULE-1.1 && ./configure && make -j4 && make install
R -e "install.packages('runjags')"
Build the container:
sudo apptainer build tidyverse-jags.sif tidyverse-jags.def
Notice that this example uses many operating system commands to prepare/install system level packages; for example, apt-get update and make install. You can use these commands because the rocker/tidyverse:4.0.3 container is built using Ubuntu 20 as its underlying operating system.
To confirm the base OS of a container, open a shell inside the container:
apptainer shell tidyverse-jags.sif
Once inside the container, run the following command to check the operating system details:
lsb_release -a
This will output information such as the distribution name, version, and codename (e.g., Ubuntu 20.04), helping you verify which system-level package manager and commands are appropriate to use in your definition file.
Note
The process of building a container from a definition file will often take a significant amount of trial and error. Be patient and persistent. Explore Apptainer container interactively using apptainer shell on each of the image files you create to open your environment and confirm whether you can load your software/packages of interest.
Exploring an Apptainer container using an interactive shell¶
It is often helpful to explore an Apptainer container's environment interactively, especially when creating or testing a container image. For example, this allows you to see what software is available inside the container. You can also refer to the container's information on Docker Hub if it was built from a Docker image.
To launch an interactive shell within the container, run:
apptainer shell <container>
For GPU-enabled containers, add --nv flag allowing the container to access GPU resources if available:
apptainer shell --nv <container>
This command opens a shell inside the <container>.
Running commands inside an Apptainer container¶
To run a specific command inside a container:
apptainer exec <container> <command>
For example, to execute command python script.py inside the tensorflow.sif container:
apptainer exec tensorflow.sif python script.py
Directory binding¶
You can make additional directories available in the container using the --bind option as follows:
apptainer exec --bind <host_directory>:<container_directory> <container> <command>
For example, if you want your project_data/ directory on your host machine to be available (mounted as /input) within the container, use:
apptainer exec --bind project_data/:/input tensorflow.sif bash
This command starts a bash shell inside the container, and ensures that /input directory inside the container mirrors the contents of project_data/ from your host machine.
Apptainer cache¶
If you frequently build containers, your $HOME folder may fill up with data due to the Apptainer cache storing reference files from the build process.
Cleaning the cache¶
To free up space by clearing cached data, run:
apptainer cache clean
Cleaning the cache does not delete built images.
For more details, refer to the official documentation:
📘 Apptainer cache clean - User Guide
Default cache directory¶
By default, Apptainer stores cached files in the following directory:
$HOME/.apptainer/cache
To verify your current cache directory, use:
echo $APPTAINER_CACHEDIR
Using a custom cache directory¶
To avoid filling up your $HOME space, you can set a custom cache directory to any other high-capacity location provided by your system:
export APPTAINER_CACHEDIR=custom_directory/
To make this change permanent, so that it is set each time you log in, add it to your .bashrc:
echo "export APPTAINER_CACHEDIR=custom_directory/" >> ~/.bashrc
And reload the .bashrc settings:
source ~/.bashrc
Then confirm the new cache path:
echo $APPTAINER_CACHEDIR
More info here: