Skip to content

Software Containers#

Overview#

Apptainer (formerly Singularity) is a container solution designed for high-performance computing systems. A container is a collection of application and dependency files, which is packaged as a single portable image file. Containers are independent from the host operating system, allowing applications that are not natively supported to run on a variety of HPC resources. They are conceptually similar to Docker, but focus more on HPC. Apptainer containers can be shared and distributed to support reproducible research and can be run on most HPC systems without modification as long as Apptainer is installed.

Apptainer Commands#

Apptainer uses a series of subcommands and options controlled by a wrapper script called apptainer. The -h option displays the command-line help documentation:

$ module load apptainer
$ apptainer -h

Linux container platform optimized for High Performance Computing (HPC) and
Enterprise Performance Computing (EPC)

Usage:
  apptainer [global options...]

Description:
  Apptainer containers provide an application virtualization layer enabling
  mobility of compute via both application and environment portability. With
  Apptainer one is capable of building a root file system that runs on any
  other Linux system where Apptainer is installed.

Options:
      --build-config    use configuration needed for building containers
  -c, --config string   specify a configuration file (for root or
                        unprivileged installation only) (default
                        "/hpc/apps/apptainer/1.3.0/etc/apptainer/apptainer.conf")
  -d, --debug           print debugging information (highest verbosity)
  -h, --help            help for apptainer
      --nocolor         print without color output (default False)
  -q, --quiet           suppress normal output
  -s, --silent          only print errors
  -v, --verbose         print additional information
      --version         version for apptainer

Available Commands:
  build       Build an Apptainer image
  cache       Manage the local cache
  capability  Manage Linux capabilities for users and groups
  checkpoint  Manage container checkpoint state (experimental)
  completion  Generate the autocompletion script for the specified shell
  config      Manage various apptainer configuration (root user only)
  delete      Deletes requested image from the library
  exec        Run a command within a container
  help        Help about any command
  inspect     Show metadata for an image
  instance    Manage containers running as services
  key         Manage OpenPGP keys
  keyserver   Manage apptainer keyservers
  oci         Manage OCI containers
  overlay     Manage an EXT3 writable overlay image
  plugin      Manage Apptainer plugins
  pull        Pull an image from a URI
  push        Upload image to the provided URI
  registry    Manage authentication to OCI/Docker registries
  remote      Manage apptainer remote endpoints
  run         Run the user-defined default command within a container
  run-help    Show the user-defined help for an image
  search      Search a Container Library for images
  shell       Run a shell within a container
  sif         Manipulate Singularity Image Format (SIF) images
  sign        Add digital signature(s) to an image
  test        Run the user-defined tests within a container
  verify      Verify digital signature(s) within an image
  version     Show the version for Apptainer

Examples:
  $ apptainer help <command> [<subcommand>]
  $ apptainer help build
  $ apptainer help instance start


For additional help or support, please visit https://apptainer.org/help/

For more information see the Apptainer Quick Start guide.

Download Pre-built Containers#

Many software packages already have containers built by developers. These containers are available from external sites such as Docker Hub or ghcr.io. With apptainer you can use the pull or build commands to download containers.

The apptainer pull command will download a OCI image from a remote repository, combining the layers to a usable SIF image.

$ apptainer pull docker://ghcr.io/apptainer/lolcow
INFO:    Converting OCI blobs to SIF format
INFO:    Starting build...
INFO:    Creating SIF file...
$ ./lolcow_latest.sif
 ______________________________
<                              >
 ------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

The apptainer build command can also be used to download existing containers. The build command has many more uses for building containers from scratch or converting formats, which we cover later. For the purpose of downloading a pre-built container, build differs from pull by converting the image to the latest Apptainer image format after downloading it. Further, build allows for custom naming of the downloaded container.

$ apptainer build my_lolcow.sif docker://ghcr.io/apptainer/lolcow
INFO:    Starting build...
INFO:    Creating SIF file...
INFO:    Build complete: my_lolcow.sif
$ ./my_lolcow.sif
 ______________________________
<                              >
 ------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Build a Container#

The build command is used to create new containers either from scratch or based on existing containers. It can also used to convert between container formats. As an example, we'll discuss the process of building custom Python container from scratch.

Please see the Apptainer docs for more info.

Definition File#

First we write a definition file for the new container. A definition file defines the container build process including software installation, runtime functionality, etc. This file can be named how you like, but it is recommended to denote definition files with the .def extension. We will call our definition file py_container.def.

Bootstrap: docker
From: ubuntu:20.04

%help
# Add information describing your container.
This container includes Python.

%environment
    # Set useful environment variables here. This section is used only at runtime, not during build.
    export PATH=/opt/python/bin:$PATH
    export LD_LIBRARY_PATH=/opt/python/lib:$LD_LIBRARY_PATH

%post
    # Add build commands here. These commands are only run at build time.

    # Create useful bind points for needed file systems. The following are set by default in RCC and should always be included for containers used in RCC.
    mkdir -p /scratch /hpc

    # Install necessary packages.
    apt-get update && apt-get install -y --no-install-recommends \
        build-essential \
        gcc-multilib \
        ca-certificates \
        zlib1g-dev \
        libssl-dev \
        curl
    apt-get clean
    rm -rf /var/lib/apt/lists/*

    # Install Python from source.
    export PATH=/opt/python/bin:$PATH
    curl https://www.python.org/ftp/python/2.7.15/Python-2.7.15.tgz -o Python-2.7.15.tgz
    tar -xvf Python-2.7.15.tgz && cd Python-2.7.15
    ./configure --prefix=/opt/python && make && make install
    rm -rf Python-2.7.15*

    # Install pip package manager.
    curl https://bootstrap.pypa.io/get-pip.py | python

    # Install some useful Python packages.
    pip install --upgrade numpy scipy matplotlib 

%test
    /opt/python/bin/python --version

Full documentation of definition files at Apptainer Docs.

Build#

Build the container using the definition file:

sudo apptainer build py_container.sif py_container.def

The syntax is always apptainer build followed by the new container name, denoted by the .sif extension, and the corresponding definition file.

root or sudo required

Building from a definition file requires root or sudo permissions. This is not possible on the HPC cluster. Instead we recommend to use a virtual machine running on your desktop or send a container build request to help-rcc@mcw.edu.

Test#

Copy your container file to your RCC home directory and run a test:

$ srun --ntasks=1 --mem-per-cpu=4GB --time=01:00:00 --job-name=interactive --account={PI_NetID} --pty bash
$ module load apptainer
$ apptainer exec py_container.sif python --version
Python 2.7.15

Here we print the version of Python installed in the container. The exec command executes a command (i.e., python --version) within the container.

Containers in Jobs#

Apptainer containers were designed to be run on HPC systems. RCC maintains containers for several software packages on the clusters. The following examples show an RCC built container which can be run in an interactive or batch job.

Example Interactive job#

Start an interactive job on the cluster:

srun --ntasks=1 --mem-per-cpu=4GB --time=01:00:00 --job-name=interactive --account={PI_NetID} --pty bash

Load the Apptainer module:

module load apptainer

Run a command in your container:

$ apptainer exec  py_container.sif python hello_world.py
Hello, World!

The exec command is used to execute the hello_world.py script within the container.

Alternatively, shell into the container and run a command:

$ apptainer shell  py_container.sif 
Apptainer> python hello_world.py 
Hello, World!

If your container has a %runscript section defined, then you could also use the apptainer run command. Choose the method that works best for you.

Example Batch Job#

#!/bin/bash
#SBATCH --job-name=Testing
#SBATCH --ntasks=1
#SBATCH --time=00:01:00
#SBATCH --account=<PI_NetID>
#SBATCH --output=%x-%j.out

module load apptainer
apptainer exec py_container.sif python hello_world.py

Submit the job:

sbatch container.sh

This job will execute the hello_world.py script within the py_container.sif container on a compute node. The output file should contain Hello, World!.

Apptainer on RCC#

RCC uses Apptainer to install and maintain software packages that would not otherwise be available on the compute clusters. This is often due to incompatible libraries or unsupported operating system. In some cases Apptainer is used to control access or functionality of an application. RCC-built containers are designed to interact with RCC clusters. They include necessary file mount points, special libraries (e.g., CUDA), and custom wrapper commands. Here we will discuss the elements needed to make your containers compatible with RCC systems.

A set of useful directories are mounted by default on RCC clusters. The following file mounts should be included for non-GPU containers:

/hpc
/scratch

Add to the %post section of your definition file:

mkdir -p /hpc /scratch

Apptainer and Docker#

Apptainer is conceptually similar to Docker and easily supports Docker images. We've shown above that Apptainer can be used to download and Apptainer-ize Docker images. It can also be used to build containers starting from a Docker image base (RCC does this). This allows RCC to support a wide variety of software that is already containerized with Docker. If you can find a container on Docker Hub, chances are that it will be supported through Apptainer. If you already use Docker to containerize your software, then you can continue developing in Docker knowing that Apptainer will easily import your images.

Full information on Apptainer and Docker at Apptainer Docs.

Getting Help#

Contact help-rcc@mcw.edu for assistance with containers.