Use Apptainer Containers
Introduction
HTCondor supports the use of Apptainer (formerly known as Singularity) environments for jobs on the High Throughput Computing system.
Similar to Docker containers, Apptainer environments allow users to prepare portable software and computing environments that can be sent to many jobs. This means your jobs will run in a more consistent environment that is easily reproducible by others.
Container jobs are able to take advantage of more of CHTC’s High Throughput resources because the operating system where the job is running does not need to match the operating system where the container was built.
Table of Contents
Quickstart
Use an existing container
If you or a group member have already created the Apptainer .sif
file, or are using a container from reputable sources such as the OSG, follow these steps to use it in an HTCondor job.
1. Add the container .sif
file to your submit file
If the .sif
file is in a /home
directory:
container_image = path/to/my-container.sif
If the .sif
file is in a /staging
directory:
container_image = file:///staging/path/to/my-container.sif
If the .sif
file is in a /staging
directory AND you are using +WantFlocking
or +WantGliding
:
container_image = osdf:///chtc/staging/path/to/my-container.sif
2. Test your container job
As always with the High Throughput system, submit a single test job and confirm that your job behaves as expected. If there are issues with the job, you may need to modify your executable, or even (re)build your own container.
Build your own container
If you need to create your own container for the software you want to use, follow these steps. For more information on any particular step, jump to the corresponding section later in this guide.
1. Create a definition file
The definition (.def
) file contains the instructions for what software to install while building the container.
CHTC provides example definition files in the software
folder of our Recipes GitHub repository. Choose from one of the existing examples, or create your own using the instructions later in this guide.
2. Start an interactive build job
Start an interactive build job (an example submit file build.sub
is provided below).
Be sure to include your .def
file in the transfer_input_files
line, or else create the file once the interactive job starts using a command line editor.
Then submit the interactive build job with
condor_submit -i build.sub
3. Build your container
While in an interactive build job, run the command
apptainer build my-container.sif image.def
If the container build finishes successfully, then the container image (.sif
) file is created.
This file is used for actually executing the container.
4. Test your container
While still in the interactive build job, run the command
apptainer shell -e my-container.sif
This command will start the container and log you into it, allowing you to test your software commands.
Once you are done testing the container, enter
exit
once to exit the container.
5. Move the container .sif file to staging
Once you are satisfied that your container is built correctly, copy your .sif
file to your staging directory.
mv my-container.sif /staging/$USER
Once the file has transferred, exit the interactive job with
exit
Once you’ve built the container, use the instructions above to use the container in your HTCondor job.
Create a Definition File
To create your own container using Apptainer, you will need to create a definition (.def
) file.
For the purposes of this guide, we will call the definition file image.def
.
CHTC provides example definition files in the software
folder of our Recipes GitHub repository. We strongly recommend that you use one of the existing examples as the starting point for creating your own container.
If the software you want to use is not in the CHTC Recipes repository, you can create your own container. Here is general process for creating your own definition file for building your custom container:
-
Consult your software’s documentation
Determine the requirements for installing the software you want to use. In particular you are looking for (a) the operating systems it is compatible with and (b) the prerequisite libraries or packages.
-
Choose a base container
The base container should at minimum use an operating system compatible with your software. Ideally the container you choose also has many of the prerequisite libraries/programs already installed.
-
Create your own definition file
The definition file contains the installation commands needed to set up your software. We encourage you to read our Building an Apptainer Container guide to learn more about the components of the Apptainer definition file. An advanced example of a definition file is provided in our Advanced Apptainer Example - SUMO guide.
A simple definition file
As a simple example, here is the .def
file that uses an existing container with python installed inside (python:3.11
, from DockerHub),
and furthermore installs the desired packages cowsay
and tqdm
:
Bootstrap: docker
From: python:3.11
%post
python3 -m pip install cowsay tqdm
Remember that the .def
file contains the instructions for creating your container and is not itself the container.
To use the software defined within the .def
file, you will need to first “build” the container and create the .sif
file, as described in the following sections.
Start an Interactive Build Job
Building a container can be a computationally intense process.
As such, we require that you only build containers while in an interactive build job.
On the High Throughput system, you can use the following submit file build.sub
:
# build.sub
# For building an Apptainer container
universe = vanilla
log = build.log
# In the latest version of HTCondor on CHTC, interactive jobs require an executable.
# If you do not have an existing executable, use a generic linux command like hostname as shown below.
executable = /usr/bin/hostname
# If you have additional files in your /home directory that are required for your container, add them to the transfer_input_files line as a comma-separated list.
transfer_input_files = image.def
requirements = (HasCHTCStaging == true)
+IsBuildJob = true
request_cpus = 4
request_memory = 16GB
request_disk = 16GB
queue
Note that this submit file assumes you have a definition file named image.def
in the same directory as the submit file.
Once you’ve created the submit file, you can submit an interactive job with the command
condor_submit -i build.sub
Apptainer
.sif
files can be fairly large, especially if you have a complex software stack. If your interactive job abruptly fails during the build step, you may need to increase the value ofrequest_disk
in your submit file. In this case, the.log
file should have a message about the reason the interactive job was interrupted.
Build Your Container
Once the interactive build job starts, confirm that your image.def
was transferred to the current directory.
To build a container, Apptainer uses the instructions in the .def
file to create a .sif
file. The .sif
file is the compressed collection of all the files that comprise the container.
To build your container, run this command:
apptainer build my-container.sif image.def
Feel free to rename the .sif
file as you desire; for the purposes of this guide we are using my-container.sif
.
As the command runs, a variety of information will be printed to the terminal regarding the container build process.
Unless something goes wrong, this information can be safely ignored.
Once the command has finished running, you should see INFO: Build complete: my-container.sif
.
Using the ls
command, you should now see the container file my-container.sif
.
If the build command fails, examine the output for error messages that may explain why the build was unsuccessful. Typically there is an issue with a package installation, such as a typo or a missing but required dependency. Sometimes there will be an error during an earlier package installation that doesn’t immediately cause the container build to fail. But, when you test the container, you may notice an issue with the package.
If you are having trouble finding the error message, edit the definition file and remove (or comment out) the installation commands that come after the package in question. Then rebuild the image, and now the relevant error messages should be near the end of the build output.
Once the image is built, it is important to test it to make sure you have all software, packages, and libraries installed correctly.
For more information on building Apptainer containers, see our Building an Apptainer Container guide.
Test Your Container
Once your container builds successfully, we highly encourage you to immediately test the container while still in the interactive build session.
To test your container, use the command
apptainer shell -e my-container.sif
You should see your command prompt change to Apptainer>
.
The shell
command logs you into a terminal “inside” the container, with access to the libraries, packages, and programs that were installed in the container following the instructions in your image.def
file.
(The -e
option is used to prevent this terminal from trying to use the host system’s programs.)
While “inside” the container, try to run your program(s) that you installed in the container.
Typically it is easiest to try to print your program’s “help” text, e.g., my-program --help
.
If using a programming language such as python3
or R
, try to start an interactive code session and load the packages that you installed.
If you installed your program in a custom location, consider using ls
to verify the files are in the right location.
You may need to manually set the PATH
environment variable to point to the location of your program’s executable binaries.
For example,
export PATH=/opt/my-program/bin:$PATH
Consult the “Special Considerations” section of our Building an Apptainer Container guide for additional information on setting up and testing your container.
When you are finished running commands inside the container, run the command exit
to exit the container.
Your prompt should change back to something like [username@build4000 ~]$
.
Move the Container .sif File to Staging
Since Apptainer .sif
files are routinely more than 1GB in size, we recommend that you transfer my-container.sif
to your /staging
directory.
It is usually easiest to move the container file directly to staging while still in the interactive build job:
mv my-container.sif /staging/$USER
If you do not have a /staging
directory, you can skip this step and the .sif
file will be automatically transferred back to the login server when you exit the interactive job.
We encourage you to request a /staging
directory, especially if you plan on running many jobs using this container.
See our Managing Large Data in Jobs guide for more information on using staging.
Use an Apptainer Container in HTC Jobs
Now that you have the container image saved in the form of the .sif
file, you can use it as the environment for running your HTCondor jobs.
In your submit file, specify the image file using the container_image
command.
HTCondor will automatically transfer the .sif
file and automatically execute your executable
file inside of the container; you do not need to include any apptainer
commands in your executable
file.
If the .sif
file is located on the login server, you can use
container_image = my-container.sif
although we generally don’t recommend this, since .sif
files are large and should instead be located in staging.
Therefore, we recommend using
container_image = file:///staging/path/to/my-container.sif
The full submit file otherwise looks like normal, for example:
# apptainer.sub
# Provide HTCondor with the name of your .sif file and universe information
container_image = file:///staging/path/to/my-container.sif
executable = myExecutable.sh
# Include other files that need to be transferred here.
# transfer_input_files = other_job_files
log = job.log
error = job.err
output = job.out
requirements = (HasCHTCStaging == true)
# Make sure you request enough disk for the container image in addition to your other input files
request_cpus = 1
request_memory = 4GB
request_disk = 10GB
queue
Then use condor_submit
with the name of your submit file:
condor_submit apptainer.sub
If you are using +WantFlocking
or +WantGliding
as described in our Scale Beyond Local HTC Capacity guide, then you should instead use
container_image = osdf:///chtc/staging/path/to/my-container.sif
to enable transferring of the .sif
file via the OSDF to compute capacity beyond CHTC.
From the user’s perspective, a container job is practically identical to a regular job. The main difference is that instead of running on the execute point’s default operation system, the job is run inside the container.
When you submit a job to HTCondor using a submit file with
container_image
set, HTCondor automatically handles the process of obtaining and running the container. The process looks roughly like
- Claim machine that satisifies submit file requirements
- Pull (or transfer) the container image
- Transfer input files, executable to working directory
- Run the executable script inside the container, as the submit user, with key directories mounted inside (such as the working directory, /staging directories, etc.)
- Transfer output files back to the submit server
For testing purposes, you can replicate the behavior of a container job with the following command. First, start an interactive job. Then run this command but change
my-container.sif
andmyExecutable.sh
to the names of the.sif
and.sh
files that you are using:apptainer exec \ --scratch /tmp \ --scratch /var/tmp \ --workdir $(pwd) \ --pwd $(pwd) \ --bind $(pwd) \ --no-home \ --containall \ my-container.sif \ /bin/bash myExecutable.sh 1> job.out 2> job.err