Totorial: Conda in an Apptainer Container
Running a Conda Environment in a Container
Sometimes a piece of software is published only as a conda package, with no module, no Python-only equivalent and no ready-made image. Building it into a container is the cleanest way to run it on Anunna: the environment is created once, on a compute node, and afterwards it is a single file that behaves the same way every time you use it.
Read Python/Conda first if you have not already. This tutorial is the last resort described at the end of that page, not the recommended route.
Important: Before you begin, make sure the following are in place:
- You are running on a compute node, not a login node. Request an interactive session first — see Interactive Jobs.
- Your
.sifimage files should be stored on Lustre, not in your home directory. SIF files can be large and will eat through your home quota fast. - Set your Apptainer cache to Lustre as well. Add this to your session (or your
.bashrc):
export APPTAINER_CACHEDIR=$myScratch/apptainer_cache
Getting Started
Load the required modules:
module reset
module load utilities Apptainer
Three things to know first
- A container should not be your first move. Always prefer software we already provide as modules, or a virtual environment built on one of our Python modules. Those are compiled for this machine and we are far better placed to help you when something goes wrong. Ask us if what you need is missing.
- This tutorial uses micromamba, not conda. Micromamba is a single small program that installs conda packages, and it takes them from conda-forge and bioconda rather than from Anaconda's own repository. That keeps you clear of the licensing conditions described in Python/Conda#How they differ.
- The image we build is read-only. Everything the environment needs is decided up front and baked in. Do not try to install software interactively inside a running container: the changes will not survive, and you lose the one real advantage of doing this, which is that the result is reproducible.
Step 1: Describe the environment
Create a file called environment.yml. This is where you name the environment, list the packages you want, and say which repositories to take them from.
name: base
channels:
- conda-forge
- bioconda
dependencies:
- python
- pip
- star
- bwa
- multiqc
Two notes on this file. Keep the name as base, because that is the environment micromamba's image already has and installing into it saves a step. And for real work, pin your versions — multiqc=1.29 rather than multiqc — otherwise rebuilding the image in six months will quietly give you different software.
Step 2: Write the definition file
A definition file describes how the container is built, step by step. Create image.def:
Bootstrap: docker
From: mambaorg/micromamba:latest
%files
environment.yml /environment.yml
%post
micromamba install -n base --file /environment.yml && \
micromamba clean --all --yes
Each part in turn:
Bootstrap and From
Start from a Docker image that already has micromamba installed, so we do not have to install it ourselves.
%files
Copy environment.yml from your directory on Anunna into the container, so the next step can read it.
%post
Run micromamba inside the container to install everything listed in the file, then delete its download cache. That last part matters: without clean, the cache is baked into the image and can easily double its size.
Step 3: Build the image
apptainer build image.sif image.def
This takes a few minutes and produces a single file, image.sif, containing the whole environment.
If the build fails complaining about directories from the host, clear Apptainer's bind list for the duration of the build:
APPTAINER_BIND=' ' apptainer build image.sif image.def
Testing the image
Check that the software is really there:
apptainer run image.sif multiqc --help
You should see MultiQC's own help text, beginning with its version number and a usage line. If instead you get an error saying the command was not found, read the note below.
Use run, not exec. The micromamba image activates the environment as it starts up, and apptainer run goes through that startup step while apptainer exec skips it. With exec you will most likely be told the command cannot be found, even though it is installed.
Using it in a job
#!/bin/bash
#SBATCH --job-name=multiqc
#SBATCH --time=1:00:00
#SBATCH --cpus-per-task=4
#SBATCH --mem=16G
module load utilities Apptainer
apptainer run --bind /lustre $myNobackup/images/image.sif multiqc /path/to/results
Apptainer does not automatically make every filesystem visible inside the container, so --bind /lustre ensures your data can be read.
Where to keep your images
Image files are large. Keep them on Lustre, under $myNobackup, and not in your home directory.
If several people in your group use the same software, put one copy somewhere shared instead of each keeping their own — see Shared Storage. A container is a single file and is identical for everyone who runs it, which is precisely what makes sharing it worthwhile.
One habit worth forming: identify an image by what is inside it, using apptainer inspect, rather than by trusting its file name.
Summary
| Step | Command |
|---|---|
| Load Apptainer | module reset && module load utilities Apptainer
|
| Describe the environment | Write environment.yml
|
| Describe the container | Write image.def
|
| Build the image | apptainer build image.sif image.def
|
| Run something in it | apptainer run image.sif <command>
|
| Inspect it | apptainer inspect image.sif
|
See also
- Python/Conda
- Apptainer
- Tutorials/Apptainer-Introduction
- Tutorials/Apptainer-DefinitionFiles
- Interactive Jobs
- Batch Jobs
- Shared Storage