| name | singularity-apptainer |
| description | HPC containerization with Singularity/Apptainer including definition files, .sif image management, MPI integration, GPU passthrough, Slurm job integration, and Docker image conversion. |
| metadata | {"references":["references/definition-files.md","references/mpi-containers.md","references/hpc-workflow-patterns.md"],"assets":["assets/basic-definition.def","assets/mpi-definition.def","assets/gpu-definition.def"]} |
Singularity/Apptainer
A comprehensive guide to HPC containerization with Singularity and Apptainer. This skill covers definition file authoring, building and managing .sif images, MPI integration for multi-node workloads, GPU passthrough for accelerated computing, Slurm job integration, and converting Docker images for use on HPC clusters. These patterns help researchers run reproducible, portable workloads on shared computing infrastructure where Docker is typically unavailable.
Resources in This Skill
This skill includes supporting materials for HPC container tasks:
References (detailed guides -- consult the table of contents in each file and read specific sections as needed):
references/definition-files.md - Complete definition file syntax: all sections (%labels through %startscript), bootstrap sources (docker, library, localimage, shub, oras), multi-stage builds, build arguments, and image signing
references/mpi-containers.md - MPI container patterns: bind model vs hybrid model, OpenMPI/MPICH/Intel MPI setup, PMIx integration, multi-node execution, performance tuning, and troubleshooting fabric issues
references/hpc-workflow-patterns.md - HPC workflow integration: Slurm job scripts with containers, array jobs, GPU jobs, interactive sessions, filesystem performance, pulling images on compute nodes, shared .sif storage, and PBS/SGE integration
Assets (ready-to-use definition file templates):
assets/basic-definition.def - Basic Ubuntu-based Apptainer definition file with common scientific packages and explanatory comments
assets/mpi-definition.def - MPI-enabled definition file with OpenMPI, including comments on bind vs hybrid model tradeoffs
assets/gpu-definition.def - CUDA-enabled definition file for GPU workloads, with comments covering both NVIDIA and AMD paths
Quick Reference Card
Key Apptainer Commands
| Command | Purpose | Example |
|---|
apptainer build | Build .sif from def file or URI | apptainer build image.sif definition.def |
apptainer pull | Pull image from registry | apptainer pull docker://ubuntu:24.04 |
apptainer exec | Run a command inside container | apptainer exec image.sif python script.py |
apptainer run | Execute the default runscript | apptainer run image.sif |
apptainer shell | Open interactive shell | apptainer shell image.sif |
apptainer instance start | Start a background instance | apptainer instance start image.sif myservice |
apptainer instance stop | Stop a background instance | apptainer instance stop myservice |
apptainer inspect | View image metadata | apptainer inspect --labels image.sif |
apptainer overlay create | Create writable overlay | apptainer overlay create --size 500 overlay.img |
apptainer sign | Sign an image | apptainer sign image.sif |
apptainer verify | Verify image signature | apptainer verify image.sif |
apptainer cache clean | Remove cached images | apptainer cache clean |
Definition File Structure at a Glance
Bootstrap: docker # Where to get the base image
From: ubuntu:24.04 # Base image URI
%labels # Image metadata (key-value pairs)
Author Jane Doe
%files # Copy files from host into container at build time
data/input.csv /opt/data/
%post # Commands to run during build (install packages, etc.)
apt-get update && apt-get install -y python3
%environment # Environment variables set at runtime
export PATH="/opt/software/bin:$PATH"
%runscript # Default command when container is "run"
python3 "$@"
%startscript # Command for background instances
python3 -m http.server 8000
%test # Validation commands run after build
python3 --version
When to Use
Use this skill when you need to:
- Run containers on HPC clusters where Docker is not available
- Write Apptainer/Singularity definition files for research software
- Build .sif images from definition files or Docker images
- Run MPI-parallel workloads across multiple nodes using containers
- Enable GPU acceleration (NVIDIA or AMD) inside containers
- Integrate containerized applications with Slurm, PBS, or SGE schedulers
- Convert existing Docker images for use on HPC systems
- Create reproducible computational environments for shared clusters
- Set up writable overlays for persistent modifications to read-only images
- Manage container image storage and distribution on cluster filesystems
Singularity vs Apptainer
Naming and History
Singularity was the original HPC container runtime, created in 2015 at Lawrence Berkeley National Laboratory. In November 2021, the project joined the Linux Foundation and was renamed to Apptainer. The commercial fork by Sylabs retained the Singularity name as SingularityCE (Community Edition).
| Project | Maintainer | Command Prefix | Status |
|---|
| Apptainer | Linux Foundation | apptainer | Active, recommended for new deployments |
| SingularityCE | Sylabs | singularity | Active, commercially supported |
| Singularity (original) | -- | singularity | Superseded by the above two |
Compatibility
Apptainer provides a singularity compatibility symlink, so existing scripts using singularity exec, singularity run, etc. continue to work without modification. The .sif image format is identical across both projects.
Migration
For clusters migrating from Singularity to Apptainer:
- Replace
singularity with apptainer in scripts (or rely on the compatibility symlink)
- Replace
SINGULARITY_ environment variable prefixes with APPTAINER_ (the old prefixes are still honored but deprecated)
- Definition file syntax is unchanged
- Existing .sif images work without rebuilding
Throughout this document, commands use the apptainer prefix. Substitute singularity if your cluster has not yet migrated.
Definition File Structure
Definition files (.def) are the Apptainer equivalent of Dockerfiles. They describe how to build a container image.
Header
The header specifies the bootstrap agent and base image:
Bootstrap: docker
From: ubuntu:24.04
Common bootstrap agents: docker (Docker Hub or registry), library (Sylabs Cloud Library), localimage (existing .sif), oras (OCI registry), shub (Singularity Hub, deprecated).
%labels
Metadata stored in the image, retrievable with apptainer inspect --labels:
%labels
Author Jane Doe
Version 1.0.0
Description Molecular dynamics simulation environment
org.opencontainers.image.source https://github.com/org/repo
%post
Commands executed during the build, running as root inside the container. This is where you install packages and compile software:
%post
apt-get update && apt-get install -y --no-install-recommends \
python3 \
python3-pip \
python3-venv && \
rm -rf /var/lib/apt/lists/*
python3 -m pip install --no-cache-dir numpy scipy matplotlib
%environment
Environment variables set every time the container runs:
%environment
export LC_ALL=C
export PATH="/opt/software/bin:$PATH"
export PYTHONPATH="/opt/software/lib/python3/site-packages:$PYTHONPATH"
%runscript
The default command executed when the container is invoked with apptainer run or called as an executable:
%runscript
echo "Container was called with arguments: $@"
python3 "$@"
%test
Validation commands run automatically after a successful build (skipped with --notest):
%test
python3 -c "import numpy; print(f'NumPy {numpy.__version__}')"
python3 -c "import scipy; print(f'SciPy {scipy.__version__}')"
%files
Copy files from the host into the container at build time. Format is <source> <destination>:
%files
requirements.txt /opt/
scripts/run_analysis.py /opt/scripts/
%startscript
Command executed when the container runs as a background instance via apptainer instance start:
%startscript
python3 -m http.server 8000
See references/definition-files.md for complete syntax coverage including multi-stage builds, build arguments, and image signing.
Building .sif Images
From a Definition File
sudo apptainer build simulation.sif simulation.def
apptainer build --fakeroot simulation.sif simulation.def
apptainer build --sandbox simulation_sandbox/ simulation.def
From Docker Hub or a Registry
apptainer pull docker://python:3.12-slim
apptainer pull output.sif docker://nvcr.io/nvidia/pytorch:24.01-py3
apptainer build myimage.sif docker://ubuntu:24.04
From Sylabs Cloud Library
apptainer pull library://ubuntu:24.04
Running Containers
exec -- Run a Specific Command
apptainer exec image.sif python3 analysis.py --input data.csv
apptainer exec image.sif bash -c "echo Hello from the container"
run -- Execute the Default Runscript
apptainer run image.sif arg1 arg2
./image.sif arg1 arg2
shell -- Interactive Session
apptainer shell image.sif
apptainer shell --overlay my_overlay.img image.sif
instance -- Background Services
apptainer instance start image.sif webserver
apptainer exec instance://webserver curl localhost:8000
apptainer instance stop webserver
apptainer instance list
Bind Mounts and Filesystem Access
By default, Apptainer automatically binds $HOME, /tmp, /proc, /sys, and /dev. Additional directories must be explicitly bound.
apptainer exec --bind /scratch/data:/data image.sif python3 process.py /data
apptainer exec --bind /scratch/data:/data,/project/config:/config image.sif ./run.sh
apptainer exec --bind /reference/genome:/genome:ro image.sif analyze.sh
export APPTAINER_BIND="/scratch/data:/data,/project/shared:/shared"
apptainer exec image.sif python3 pipeline.py
Key differences from Docker:
- The host user's identity is preserved inside the container (no root by default)
- Home directory is mounted automatically (disable with
--no-home)
- The current working directory is preserved (disable with
--no-mount cwd)
MPI Integration
Apptainer supports MPI workloads through two models. The choice depends on your cluster's MPI installation and performance requirements.
Host MPI Bind Model (Recommended for Most Clusters)
The host's MPI installation is bind-mounted into the container at runtime. The container needs compatible MPI headers and libraries at build time, but the host's optimized MPI stack (with InfiniBand, OmniPath, or other fabric support) is used at runtime.
mpirun -np 4 apptainer exec --bind /opt/openmpi:/opt/openmpi image.sif ./my_mpi_app
srun --mpi=pmix apptainer exec image.sif ./my_mpi_app
Hybrid Model
The container ships its own MPI installation. Simpler to set up but may not leverage high-speed interconnects unless network drivers are bind-mounted.
apptainer exec image.sif mpirun -np 4 ./my_mpi_app
See references/mpi-containers.md for detailed setup guides for OpenMPI, MPICH, and Intel MPI, plus PMIx configuration and troubleshooting.
GPU Support
NVIDIA GPUs
Use the --nv flag to expose NVIDIA GPU devices and driver libraries inside the container:
apptainer exec --nv gpu_image.sif python3 train_model.py
apptainer exec --nv gpu_image.sif nvidia-smi
The --nv flag automatically:
- Binds the host NVIDIA driver libraries into the container
- Makes GPU device files (
/dev/nvidia*) available
- Sets
LD_LIBRARY_PATH to include driver libraries
The container must include CUDA toolkit libraries (matching or compatible with the host driver version).
AMD GPUs
Use the --rocm flag for AMD GPU passthrough:
apptainer exec --rocm gpu_image.sif python3 train_model.py
apptainer exec --rocm gpu_image.sif rocm-smi
See assets/gpu-definition.def for a complete CUDA-enabled definition file template.
Slurm Integration
Apptainer integrates naturally with Slurm because it runs as a regular user process (no daemon required).
Basic Slurm Job
#!/bin/bash
apptainer exec --bind /scratch/$USER:/scratch image.sif \
python3 analysis.py --threads $SLURM_CPUS_PER_TASK
MPI Slurm Job
#!/bin/bash
srun --mpi=pmix apptainer exec --bind /scratch:/scratch image.sif ./my_mpi_app
GPU Slurm Job
#!/bin/bash
apptainer exec --nv --bind /scratch/$USER:/scratch gpu_image.sif \
python3 train.py --gpus 4
See references/hpc-workflow-patterns.md for array jobs, interactive sessions, PBS/SGE examples, and filesystem performance patterns.
Docker-to-Singularity Conversion
Converting Docker images to .sif format is straightforward:
apptainer pull docker://tensorflow/tensorflow:2.16.1-gpu
apptainer pull docker://registry.example.com/myproject/myimage:latest
apptainer build local_image.sif docker-daemon://myimage:latest
docker save myimage:latest -o myimage.tar
apptainer build local_image.sif docker-archive://myimage.tar
Key considerations when converting:
- Docker
ENTRYPOINT maps to %runscript
- Docker
ENV statements are preserved
- Docker
VOLUME directives are ignored (use --bind instead)
- Docker
USER is ignored (Apptainer uses the host user's identity)
- Multi-layer Docker images are flattened into a single squashfs filesystem
Overlay and Writable Containers
SIF images are read-only by default. Use overlays to add a writable layer.
Writable Overlay
apptainer overlay create --size 500 my_overlay.img
apptainer exec --overlay my_overlay.img image.sif pip install <package-name>
apptainer shell --overlay my_overlay.img image.sif
Writable Sandbox
apptainer build --sandbox my_sandbox/ docker://ubuntu:24.04
apptainer shell --fakeroot --writable my_sandbox/
apptainer build final_image.sif my_sandbox/
Embedded Overlay
apptainer overlay create --size 200 image.sif
apptainer exec --writable image.sif pip install <package-name>
Common Mistakes
-
Building without fakeroot or sudo -- Definition file builds that install packages require root-like privileges. Use --fakeroot if your admin has configured it, or sudo apptainer build. Pulling pre-built images does not require elevated privileges.
-
Mismatched MPI versions -- The container's MPI version must be ABI-compatible with the host's MPI when using the bind model. A mismatch causes segfaults or "MPI_Init failed" errors. Check with mpirun --version on both host and container.
-
Forgetting --nv for GPU jobs -- Without --nv, the container cannot see GPU devices even if CUDA is installed inside. The error typically manifests as "no CUDA-capable device is detected."
-
Assuming root inside the container -- Unlike Docker, Apptainer preserves the host user's identity. apt-get install inside a running container fails unless you used --fakeroot or --writable with appropriate permissions.
-
Not binding scratch/project filesystems -- HPC data directories like /scratch, /project, or /work are not mounted by default. Jobs fail with "file not found" if you forget --bind.
-
Using Docker VOLUME expectations -- Docker volumes do not translate to Apptainer. Data persistence is handled through bind mounts and overlays.
-
Large .sif images on shared filesystems -- Building or pulling large images in $HOME can exceed quotas. Use APPTAINER_CACHEDIR and APPTAINER_TMPDIR to redirect to scratch.
-
Ignoring %test -- Skipping the %test section means build problems are discovered at runtime. Add basic import checks and version validation.
-
Hardcoding paths in def files -- Use %environment to set PATH and other variables rather than hardcoding absolute paths in %runscript, making the container more flexible.
-
Not cleaning up package caches -- Just like Dockerfiles, run rm -rf /var/lib/apt/lists/* after apt-get install and use --no-cache-dir with to avoid bloating the image.
Best Practices
Resources
Official Documentation
MPI and HPC
Registries and Distribution
Tutorials and Community