Apptainer (formerly Singularity) is a container runtime designed for HPC clusters. Unlike Docker, it does not require a daemon or root privileges to run containers, making it the standard choice on shared systems where users lack admin access.
Key Concepts
- Image — a single immutable
.siffile (Singularity Image Format) that contains the entire container filesystem - Definition file — a plain-text recipe (
.def) that describes how to build an image, similar to aDockerfile - Bind mount — a way to expose host directories inside the container at runtime
Essential Commands
| Command | What it does |
|---|---|
apptainer build image.sif image.def |
Build an image from a definition file (requires root or --fakeroot) |
apptainer shell image.sif |
Open an interactive shell inside the container |
apptainer exec image.sif <cmd> |
Run a single command inside the container |
apptainer run image.sif |
Run the container’s default %runscript |
apptainer pull docker://ubuntu:22.04 |
Pull a Docker image and convert it to .sif |
apptainer inspect image.sif |
Show metadata and labels |
Definition File Structure
Bootstrap: docker
From: ubuntu:22.04
%post
apt-get update && apt-get install -y curl
%environment
export PATH=/opt/myapp/bin:$PATH
%runscript
exec myapp "$@"
%labels
Author your.name@example.com
Version 1.0
Example: Miniconda Container
Bootstrap: docker
From: ubuntu:22.04
%post
apt-get update && apt-get install -y wget bzip2 ca-certificates && \
wget -q https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \
-O /tmp/miniconda.sh && \
bash /tmp/miniconda.sh -b -p /opt/conda && \
rm /tmp/miniconda.sh && \
/opt/conda/bin/conda clean -afy
%environment
export PATH=/opt/conda/bin:$PATH
export CONDA_DEFAULT_ENV=base
%runscript
exec /opt/conda/bin/conda "$@"
%labels
Description Miniconda3 on Ubuntu 22.04
Build and test:
apptainer build --fakeroot miniconda.sif miniconda.def
apptainer exec miniconda.sif conda --version
apptainer exec miniconda.sif python --version
To create an environment inside the container at build time, add to %post:
/opt/conda/bin/conda create -n myenv python=3.11 numpy pandas -y
Example: PostgreSQL Container
Bootstrap: docker
From: postgres:16
%post
mkdir -p /var/run/postgresql && \
chown -R postgres:postgres /var/run/postgresql
%environment
export PGDATA=/var/lib/postgresql/data
export POSTGRES_USER=postgres
%startscript
postgres -D $PGDATA
%labels
Description PostgreSQL 16
Build and initialize a database:
apptainer build --fakeroot postgres.sif postgres.def
# Initialize a data directory on the host
mkdir -p $HOME/pgdata
apptainer exec \
--env POSTGRES_PASSWORD=secret \
--bind $HOME/pgdata:/var/lib/postgresql/data \
postgres.sif initdb -D /var/lib/postgresql/data
# Start the server
apptainer instance start \
--bind $HOME/pgdata:/var/lib/postgresql/data \
postgres.sif pgserver
# Connect
apptainer exec instance://pgserver psql -U postgres
# Stop
apptainer instance stop pgserver
Example: Emacs Container
Bootstrap: docker
From: ubuntu:22.04
%post
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
emacs-nox \
git \
ripgrep \
fd-find && \
apt-get clean && rm -rf /var/lib/apt/lists/*
%environment
export TERM=xterm-256color
%runscript
exec emacs "$@"
%labels
Description Emacs (no-X) on Ubuntu 22.04
Build and run:
apptainer build --fakeroot emacs.sif emacs.def
# Open a file
apptainer run --bind $HOME:/home/$USER emacs.sif myfile.txt
# Or via exec
apptainer exec --bind $HOME:/home/$USER emacs.sif emacs --batch --eval "(message \"hello\")"
Bind-mount your home directory so Emacs can read your ~/.emacs.d config.
Further Reading
- Apptainer documentation
- Definition file reference
man apptaineron any system with Apptainer installed