Using Containers in HPC with Apptainer (formerly Singularity)
Quick Start
After having successfully installed Apptainer on your system the initial step is to run your first container.
apptainer run docker://ghcr.io/apptainer/lolcow
Output
INFO: Converting OCI blobs to SIF format
INFO: Starting build...
Copying blob 5ca731fc36c2 done |
Copying blob 16ec32c2132b done |
Copying config fd0daa4d89 done |
Writing manifest to image destination
2025/06/12 09:20:29 info unpack layer: sha256:16ec32c2132b43494832a05f2b02f7a822479f8250c173d0ab27b3de78b2f058
2025/06/12 09:20:30 info unpack layer: sha256:5ca731fc36c28789c5ddc3216563e8bfca2ab3ea10347e07554ebba1c953242e
INFO: Creating SIF file...
_______________________________
< Thu Jun 12 09:20:33 CEST 2025 >
-------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
The leading docker://
part instructs Apptainer to look for the image in
Docker Hub.
With a leading library://
in the image name Apptainer looks for the image in
the Singularity Cloud Library.
This is the equivalent to Docker Hub in the
Apptainer world.
Let's try another example by running an Ubuntu image using Apptainer. Therefore, let us use the
apptainer run docker://ubuntu:24.04
Output
INFO: Converting OCI blobs to SIF format
INFO: Starting build...
Copying blob d9d352c11bbd done |
Copying config bf16bdcff9 done |
Writing manifest to image destination
2025/06/12 09:21:11 info unpack layer: sha256:d9d352c11bbd3880007953ed6eec1cbace76898828f3434984a0ca60672fdf5a
INFO: Creating SIF file...
Apptainer>
Using this command we are presented a shell inside the Ubuntu Apptainer container.
Usually, we are logged in as the same user as you are on the host system
inside a container.
Let's look at the python
example again, run a container and execute a shell
to illustrate this:
apptainer run docker://python:latest sh
Output
INFO: Converting OCI blobs to SIF format
INFO: Starting build...
Copying blob 77a6ac598bc1 done |
Copying blob 20d0b4e6a2e6 done |
Copying blob 48b8862a18fa skipped: already exists
Copying blob 5cc4a19fbac0 done |
Copying blob b1b8a0660a31 skipped: already exists
Copying blob 0c01110621e0 skipped: already exists
Copying blob 3b1eb73e9939 skipped: already exists
Copying config 3b29f43b7f done |
Writing manifest to image destination
2025/06/13 08:16:41 info unpack layer: sha256:0c01110621e0ec1eded421406c9f117f7ae5486c8f7b0a0d1a37cc7bc9317226
2025/06/13 08:16:42 info unpack layer: sha256:3b1eb73e993990490aa137c00e60ff4ca9d1715bafb8e888dbb0986275edb13f
2025/06/13 08:16:42 info unpack layer: sha256:b1b8a0660a31403a35d70b276c3c86b1200b8683e83cd77a92ec98744017684a
2025/06/13 08:16:43 info unpack layer: sha256:48b8862a18fa961ebfbac8484877dd4894e96ee88177d8c4f1f54d9727262b7d
2025/06/13 08:16:45 info unpack layer: sha256:20d0b4e6a2e6295e295119126082b4f39882f50278611e48580e8fbef730b08a
2025/06/13 08:16:45 info unpack layer: sha256:77a6ac598bc154025b4b2e393a3ca959116e0d8af9c31659a857ac05ab34ccbb
2025/06/13 08:16:45 info unpack layer: sha256:5cc4a19fbac0d0fb7423535182443188713730a05b7ab1104f2116055472c13e
INFO: Creating SIF file...
Apptainer>
Apptainer> whoami
hueser93
Apptainer automatically makes the current directory available as the home
directory (/home/$USER
) in the container.
Unlike with Podman, it is not necessary to explicitly mount the directories.
They are made available by default.
Apptainer> touch foo
Apptainer> exit
$ ls
foo
As you already saw in the examples above, with Apptainer, you can easily reuse existing
images from Docker Hub and run them as an Apptainer container.
Let us run a specific python:3.13
Docker Hub
image as an Apptainer container.
Therefore, we pull
the image first.
apptainer pull docker://python:3.13
Output
INFO: Converting OCI blobs to SIF format
INFO: Starting build...
Copying blob 77a6ac598bc1 skipped: already exists
Copying blob 3b1eb73e9939 skipped: already exists
Copying blob 0c01110621e0 skipped: already exists
Copying blob b1b8a0660a31 skipped: already exists
Copying blob 48b8862a18fa skipped: already exists
Copying blob 20d0b4e6a2e6 skipped: already exists
Copying blob 5cc4a19fbac0 skipped: already exists
Copying config 3b29f43b7f done |
Writing manifest to image destination
2025/06/13 08:29:00 info unpack layer: sha256:0c01110621e0ec1eded421406c9f117f7ae5486c8f7b0a0d1a37cc7bc9317226
2025/06/13 08:29:00 info unpack layer: sha256:3b1eb73e993990490aa137c00e60ff4ca9d1715bafb8e888dbb0986275edb13f
2025/06/13 08:29:01 info unpack layer: sha256:b1b8a0660a31403a35d70b276c3c86b1200b8683e83cd77a92ec98744017684a
2025/06/13 08:29:01 info unpack layer: sha256:48b8862a18fa961ebfbac8484877dd4894e96ee88177d8c4f1f54d9727262b7d
2025/06/13 08:29:04 info unpack layer: sha256:20d0b4e6a2e6295e295119126082b4f39882f50278611e48580e8fbef730b08a
2025/06/13 08:29:04 info unpack layer: sha256:77a6ac598bc154025b4b2e393a3ca959116e0d8af9c31659a857ac05ab34ccbb
2025/06/13 08:29:04 info unpack layer: sha256:5cc4a19fbac0d0fb7423535182443188713730a05b7ab1104f2116055472c13e
INFO: Creating SIF file...
This command downloads the image from Docker Hub (docker://
) and converts it
into the Apptainer specific image format called SIF file
.
A file called python_3.13.sif
was created in your current directory.
Run it as shown below.
apptainer run python_3.13.sif
Output
Python 3.13.5 (main, Jun 12 2025, 22:47:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Apptainer Definition Files
As demonstrated in the Podman build lesson we want to build our first custom
Apptainer image as well.
Therefore, we need to create the Apptainer definition file, i.e. the
equivalent to Dockerfile
.
We will recreate the lolcow image used for the first run
command in this episode.
Therefore, we create a file called lolcow.def
using the editor of your choice.
This file contains the construction manual for the Apptainer image.
Bootstrap: docker
From: ubuntu:24.04
%post
apt-get -qy update
apt-get -qy install fortune cowsay lolcat
%environment
export LC_ALL=C
export PATH=/usr/games:$PATH
%runscript
fortune | cowsay | lolcat
Build the image using the apptainer build
command.
apptainer build lolcow.sif lolcow.def
Output
INFO: Starting build...
Copying blob d9d352c11bbd done |
Copying config bf16bdcff9 done |
Writing manifest to image destination
2025/06/13 08:31:43 info unpack layer: sha256:d9d352c11bbd3880007953ed6eec1cbace76898828f3434984a0ca60672fdf5a
INFO: Running post scriptlet
+ apt-get -qy update
[...]
+ apt-get -qy install fortune cowsay lolcat
[...]
INFO: Adding environment to container
INFO: Adding runscript
INFO: Creating SIF file...
INFO: Build complete: lolcow.sif
This command creates the file lolcow.sif
.
It is run using the apptainer run
command.
apptainer run lolcow.sif
Output
_________________________________________
/ Of course you have a purpose -- to find \
\ a purpose. /
-----------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Let's take apart the Apptainer definition file.
Header
Each Apptainer definition file needs to start with the header part consisting
of at least the Bootstrap
keyword.
In our example we use the docker
bootstrap agent telling Apptainer to
get the image from a Docker registry.
This agent needs to be combined with the From
keyword to let Apptainer know,
which base image to use.
Bootstrap: docker
From: ubuntu:24.04
Usage of Other Registries
If you want to use another registry, e.g. the Helmholtz Codebase GitLab Container Registry, it is easily possible. Specify the full name of the image according to the GitLab Container Registry naming convention as described in the documentation.
Generic example:
Bootstrap: docker
From: <registry URL>/<namespace>/<project>/<image>
Helmholtz Codebase GitLab example:
Bootstrap: docker
From: hcr.helmholtz.cloud/hueser93/my-helloworld-image-project
apptainer remote login -u hueser93 docker://hcr.helmholtz.cloud
apptainer build hello.sif hello.def
apptainer run hello.sif
A list of preferred bootstrap agents is available here.
Sections
The main content of the definition file is broken into sections. In our example we used three different sections:
%post
- In this section you can download files from the internet with tools like
git
,wget
orpip
, - You can install new software and libraries,
- Create configuration files,
- Create files and directories, etc.
- In this section you can download files from the internet with tools like
%environment
- This section allows you to define environment variables which are set at runtime.
- These variables are not set at build time,
when running the
apptainer build
command.
%runscript
- The commands specified in this section are executed when the container
image is run. (
apptainer run
)
- The commands specified in this section are executed when the container
image is run. (
Please refer to the official documentation for a complete list of available sections and their usage.
Apptainer vs. Podman
Podman | Apptainer | |
---|---|---|
Isolation from host | Shares little by default. | Isolation not the primary focus. By default shares most everything. |
Supported Host Operating Systems (OS) | Windows, Mac, Linux | Linux |
Data Persistence | No host filesystem available by default. | Writable bind-mounts of the user home directory are automatically created. |
Primary target group | Developers, DevOps | Scientific Application Users/Developers |
HPC | Not suitable for HPC: requires elevated permissions | Integrates well with MPI, GPUs, Infiniband and Schedulers (e.g. SLURM) |
Ecosystem | Larger ecosystem; more sophisticated registries and preconfigured images | Smaller ecosystem; is able to use Docker images. |