Apptainer

Apptainer (formerly Singularity) is the standard container runtime on HPC clusters. PETFit’s Apptainer definition file lives in the apptainer/ directory of the repository.

Building the container

Prerequisites

  • Apptainer installed (or Singularity, which uses the same commands)

  • Internet access during the build

Quickest path: pull from Docker Hub

apptainer build petfit_latest.sif docker://mathesong/petfit:latest

This converts the published Docker image into a SIF file. No local definition file is needed.

Build from the definition file

If you need to customise the build (e.g. specific user/group IDs, work offline, modify dependencies):

apptainer build petfit_latest.sif apptainer/petfit.def

To pass build arguments such as a non-default user ID:

apptainer build \
  --build-arg USER_ID=1001 \
  --build-arg GROUP_ID=1001 \
  petfit_latest.sif apptainer/petfit.def

Simplified workflow: the petfit alias

Apptainer auto-mounts your $HOME, $PWD, and /tmp, and runs as your own user. So for data under your home directory you need no -B flags at all. Define an alias once (in ~/.bashrc):

alias petfit='apptainer run petfit_latest.sif'

then run with bare host paths:

petfit --func modelling_plasma --bids_dir ~/data/bids --blood_dir ~/data/blood

For data outside $HOME (e.g. /scratch), add an explicit -B /scratch:/scratch, or ask your admin to add bind path = /scratch to /etc/apptainer/apptainer.conf. Otherwise, the explicit -B examples below work everywhere.

Interactive mode

Interactive mode launches a Shiny web app accessible in your browser.

# Region definition
apptainer run --cleanenv \
  -B /path/to/bids:/data/bids_dir:ro \
  -B /path/to/derivatives:/data/derivatives_dir:rw \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func regiondef

# Plasma input modelling
apptainer run --cleanenv \
  -B /path/to/bids:/data/bids_dir:ro \
  -B /path/to/derivatives:/data/derivatives_dir:rw \
  -B /path/to/blood:/data/blood_dir:ro \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func modelling_plasma

# Reference tissue modelling
apptainer run --cleanenv \
  -B /path/to/bids:/data/bids_dir:ro \
  -B /path/to/derivatives:/data/derivatives_dir:rw \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func modelling_ref

Then open the address the container prints in your browser — http://localhost:3838 by default. Because Apptainer shares the host network, if port 3838 is already in use on the node the container automatically scans upward for the next free port (3838–3858) and prints a line such as:

Requested Shiny port 3838 is in use. Using 3839 instead.

On a remote HPC, use SSH port forwarding first in order to be able to access the browser interface on your local machine. Forward whichever port the container reports:

ssh -L 3838:localhost:3838 username@servername

To request a specific starting port instead of 3838, set SHINY_PORT (with --cleanenv you must pass it explicitly):

apptainer run --cleanenv --env SHINY_PORT=8080 \
  -B /path/to/derivatives:/data/derivatives_dir:rw \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func regiondef

Automatic mode

# Region definition
apptainer run --cleanenv \
  -B /path/to/derivatives:/data/derivatives_dir:rw \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func regiondef --mode automatic

# Modelling pipeline (plasma input)
apptainer run --cleanenv \
  -B /path/to/bids:/data/bids_dir:ro \
  -B /path/to/derivatives:/data/derivatives_dir:rw \
  -B /path/to/blood:/data/blood_dir:ro \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func modelling_plasma --mode automatic

# Single step (e.g. weights)
apptainer run --cleanenv \
  -B /path/to/derivatives:/data/derivatives_dir:rw \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func modelling_plasma --mode automatic --step weights

HPC integration

SLURM

Interactive job (for GUI usage):

#!/bin/bash
#SBATCH --job-name=petfit-interactive
#SBATCH --time=04:00:00
#SBATCH --mem=8G
#SBATCH --cpus-per-task=2

module load apptainer

apptainer run --cleanenv \
  -B /scratch/project/bids_data:/data/bids_dir:ro \
  -B /scratch/project/derivatives:/data/derivatives_dir:rw \
  -B /scratch/project/blood:/data/blood_dir:ro \
  -B /tmp:/tmp \
  petfit_latest.sif \
  --func modelling_plasma

Volume mounting

Apptainer uses --bind (or -B) instead of Docker’s -v:

--bind /host/path:/container/path

# Multiple mounts
--bind /data/bids:/data/bids_dir \
--bind /analysis:/data/derivatives_dir \
--bind /blood:/data/blood_dir

Troubleshooting

Directory not found

# Verify bind mount paths exist
ls -la /host/path/to/data

# Check inside the container
apptainer exec petfit_latest.sif ls -la /data/bids_dir

Port already in use

Apptainer shares the host network, so a busy port 3838 on the node would otherwise clash. The container detects this automatically and binds the next free port in the range 3838–3858, printing the address to use (e.g. Requested Shiny port 3838 is in use. Using 3839 instead.). Set up SSH forwarding to whichever port it reports (ssh -L <port>:localhost:<port>). To choose the starting port yourself, pass --env SHINY_PORT=<port>.

No internet on compute nodes

Build the SIF on a login node, then copy the .sif file to your project space.

Home directory size limits

Build in a scratch directory and set the cache location:

export APPTAINER_CACHEDIR=/scratch/$USER/apptainer_cache
apptainer build petfit_latest.sif docker://mathesong/petfit:latest

Module loading

Common module names across HPC systems:

module load apptainer
module load singularity
module load singularity-ce