Skip to content

Using containers

Running commands inside a container

The apptainer exec command will allow you to execute any program within a given container. The apptainer run command performs the action defined by the %runscript section, which is the primary task of the container. Using the apptainer run command is the simpler approach for job submissions.

You can even "execute" a container, which performs the same action as the apptainer run command. For example, the following demonstrates how to inspect the runscript and execute the /share/apps/rocky9/containers/public/python3_helloworld.sif container:

$ apptainer inspect -r /share/apps/rocky9/containers/public/python3_helloworld.sif
#!/bin/sh
  python3 -c 'print("Hello, World!")'

$ /share/apps/rocky9/containers/public/python3_helloworld.sif
Hello, World!

$ apptainer run /share/apps/rocky9/containers/public/python3_helloworld.sif
Hello, World!

Execute a script from outside the container

Using on the cluster

For typical use, you should use the apptainer run or apptainer exec commands, especially when submitting the work via the scheduler.

The following example runs a python script hello_world2.py from the current directory using the /share/apps/rocky9/containers/public/python3_helloworld.sif container:

$ apptainer exec /share/apps/rocky9/containers/public/python3_helloworld.sif \
  python3 ./hello_world2.py
Hello, World!
Hello, World (again)!

The file hello_world2.py contains the following code:

print("Hello, World!")
print("Hello, World (again)!")

If command apptainer exec was replaced by apptainer run, the runscript would be called, ignoring any parameters after the container name.

Customised Environments

While we encourage users to customise their Apocrita environment to make their workflow easier, please be aware that customisations which change the user's environment for example by setting variables in the ~/.bash_profile file, or by using python's pip to create a ~/.local folder, may cause problems with Apptainer which can be difficult to troubleshoot.

Using containers with Slurm

One of the major benefits of Apptainer is the simplicity with which it can be used in an HPC environment. Your Slurm submission script may not require any modules loading to run your container. The resource requirements should be very similar to native code.

Simple example

#!/bin/bash
#SBATCH -n 1                # Request 1 core
#SBATCH -t 1:0:0            # Request 1 hour runtime
#SBATCH --mem-per-cpu=1G    # Request 1GB RAM per core

apptainer run /share/apps/rocky9/containers/public/python3_helloworld.sif

Modules example

Applications installed within Apptainer containers may also be provided as a module to abstract the container invocation commands (apptainer run and apptainer exec). In these cases, the container name will match the runscript command. For example, to use Pandoc as a module, simply load the pandoc module to use the application.

#!/bin/bash
#SBATCH -n 1                # Request 1 core
#SBATCH -t 1:0:0            # Request 1 hour runtime
#SBATCH --mem-per-cpu=1G    # Request 1GB RAM per core

module load pandoc
pandoc --help

Shell access to the container

It is possible to launch a shell within the container using the shell command. Interacting directly with a shell inside the container can be useful for code debugging and running multiple commands in a single interactive session, as an alternative to writing a single script. Below demonstrates how to invoke python3 from inside the /share/apps/rocky9/containers/public/python3_helloworld.sif container using an interactive shell:

$ apptainer shell /share/apps/rocky9/containers/public/python3_helloworld.sif
Apptainer> python3
Python 3.12.3 (main, Feb  4 2025, 14:48:35) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Running containers from external sources

Use of external containers for Research

For long term reproducibility of containers, we recommend that you build your own native Apptainer containers from definition files instead of relying on 3rd party containers for your research. Using containers from external sources may produce undesirable results if the container is rebuilt after upstream changes such as updated or obsoleted packages.

Use a compute node for pulling large containers

Pulling large containers is best done on a compute node. Please request an interactive salloc session with an appropriate resource request for large containers, remembering to follow the APPTAINERENV_SLURM_NTASKS=${SLURM_NTASKS} advice covered in Building containers to ensure all cores are used correctly.

Containers created elsewhere can be copied or imported, and run on the cluster. The following example demonstrates how to import and run the latest Ubuntu official image stored in the Docker Hub:

$ apptainer pull ubuntu.sif docker://ubuntu:latest
$ apptainer exec ubuntu.sif cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.3 LTS"