Singularity: Difference between revisions

From Alliance Doc
Jump to navigation Jump to search
No edit summary
No edit summary
 
(95 intermediate revisions by 11 users not shown)
Line 1: Line 1:
{{Draft}}
<languages />
=Overview=
<translate>
Singularity<ref>http://singularity.lbl.gov/</ref> is open source software created by Berkeley Lab:
=Please use [[Apptainer]] instead= <!--T:776-->
* as a '''secure way''' to use Linux containers on Linux multi-user clusters,
<b>Much of this information is now outdated since Singularity has been deprecated in favor of Apptainer on all our clusters. Please
* as a way to enable users to have '''full control of their environment,''' and,
refer to [[Apptainer]] instead.</b>
* as a way to '''package scientific software''' and deploy such to ''different'' clusters having the ''same'' architecture.
i.e., it provides '''operating-system-level virtualization''' commonly called ''containers''.


A ''container'' is different from a ''virtual machine'' in that a container:
=Overview= <!--T:1-->
Singularity<ref>Singularity Software website: https://www.sylabs.io/docs/</ref> is open source software created by Berkeley Lab:
* as a <b>secure way</b> to use Linux containers on Linux multi-user clusters,
* as a way to enable users to have <b>full control of their environment,</b> and,
* as a way to <b>package scientific software</b> and deploy such to <i>different</i> clusters having the <i>same</i> architecture.
i.e., it provides <b>operating-system-level virtualization</b> commonly called <i>containers</i>.
 
<!--T:2-->
A <i>container</i> is different from a <i>virtual machine</i> in that a container:
* likely has less overhead, and,
* likely has less overhead, and,
* can only run programs capable of running in the same operating system (i.e., Linux when using Singularity) for the same hardware architecture.
* can only run programs capable of running in the same operating system kernel (i.e., Linux when using Singularity) for the same hardware architecture.
(Virtual machines can run different operating systems and sometimes support running software designed for foreign CPU architectures.)
(Virtual machines can run different operating systems and sometimes support running software designed for foreign CPU architectures.)


Containers use Linux '''control groups''' (cgroups), kernel '''namespaces''', and an '''overlay filesystem''' where:
<!--T:3-->
* cgroups '''limit, control, and isolate''' resource usage (e.g., RAM, disk I/O, CPU access)
Containers use Linux <b>control groups</b> (cgroups), kernel <b>namespaces</b>, and an <b>overlay filesystem</b> where:
* kernel namespaces '''virtualize and isolate''' operating system resources of a '''group of processes''', e.g., process and user IDs, filesystems, network access; and,
* cgroups <b>limit, control, and isolate</b> resource usage (e.g., RAM, disk I/O, CPU access),
* overlay filesystems can be used to enable the '''appearance''' of writing to otherwise read-only filesystems.
* kernel namespaces <b>virtualize and isolate</b> operating system resources of a <b>group of processes</b>, e.g., process and user IDs, filesystems, network access; and,
* overlay filesystems can be used to enable the <b>appearance</b> of writing to otherwise read-only filesystems.


Singularity is similar to other container solutions such as Docker<ref>https://www.docker.com/</ref> except Singularity was specifically designed to enable containers to be used securely without requiring any special permissions especially on multi-user compute clusters.<ref>http://singularity.lbl.gov/docs-security</ref>
<!--T:4-->
Singularity is similar to other container solutions such as Docker<ref>Docker Software website: https://www.docker.com/</ref> except Singularity was specifically designed to enable containers to be used securely without requiring any special permissions especially on multi-user compute clusters.<ref>Singularity Security Documentation: https://www.sylabs.io/guides/2.5.1/admin-guide/security.html</ref>


=Singularity Availability=
=Availability= <!--T:5-->


Singularity is available on Compute Canada clusters (e.g., [[Cedar]] and [[Graham]]) and some legacy cluster systems run by various Compute Canada involved members/consortia across Canada.
<!--T:6-->
Singularity is available on our clusters.


Should you wish to use Singularity on your own computer systems, you will need to download and install Singularity per its documentation.<ref>http://singularity.lbl.gov/all-releases</ref> You should be using a relatively recent version of some Linux distribution (e.g., ideally your kernel is v3.10.0 or newer).
<!--T:7-->
Should you wish to use Singularity on your own computer, you will need to download and install it per its documentation.<ref>Singularity Documentation: https://www.sylabs.io/docs/</ref> You should be using a relatively recent version of some Linux distribution (e.g., ideally your kernel is v3.10.0 or newer).


=Using Singularity On Compute Canada Systems=
=Singularity on a cluster= <!--T:8-->


==Module Loading==
==Loading a module== <!--T:9-->


<!--T:10-->
To use Singularity, first load the specific module you would like to use, e.g.,
To use Singularity, first load the specific module you would like to use, e.g.,
<source lang="console">$ module load singularity/2.4</source>
<source lang="console">$ module load singularity/2.5</source>


<!--T:11-->
Should you need to see all versions of Singularity modules that are available then run:
Should you need to see all versions of Singularity modules that are available then run:
<source lang="console">$ module spider singularity</source>
<source lang="console">$ module spider singularity</source>


==Creating Images==
==Creating images== <!--T:12-->


'''Before''' using Singularity, you will first need to '''create a (container) image'''. A Singularity image is either a file or a directory '''containing an installation of Linux'''. One can create a Singularity image by any of the following:
<!--T:13-->
* downloading a container from '''Singularity Hub'''<ref>https://singularityhub.com/</ref>
<b>Before</b> using Singularity, you will first need to <b>create a (container) image</b>. A Singularity image is either a file or a directory <b>containing an installation of Linux</b>. One can create a Singularity image using the <code>singularity build</code> command, e.g.,
* downloading a container from '''Docker Hub'''<ref>https://hub.docker.com/</ref>
* <code>singularity build WHAT-TO-WRITE SPECIAL-URI-OR-PATH</code>
* from a container you already have,
where <code>WHAT-TO-WRITE</code> is:
* from a '''tarball''' or a '''directory''' containing an installation of Linux, or,
* a filename of the singularity image file (*.sif) where the built image will be written
* from a '''Singularity recipe file'''.
* a directory if one is building a <b>sandbox</b> using the <code>--sandbox</code> option typically on one's own (Linux) computer (requiring root account access)
and <code>SPECIAL-URI-OR-PATH</code> is:
* a URI starting with <b>library://</b> to build from a Container Library,
* a URI starting with <b>docker://</b> to build from Docker Hub,
* a URI starting with <b>shub://</b> to build from Singularity Hub,
* a path to an existing container,
* a path to a directory (to build from a sandbox), or
* a path to a Singularity image file (which is a recipe on how to build the image).


===Creating an Image Using Singularity Hub===
===Warning=== <!--T:110-->


Suppose the Singularity Hub URL for a container you want to use is:
<!--T:111-->
<pre>shub://singularityhub/ubuntu</pre>
You are strongly advised to create Singularity images using a computer or virtual machine
then you would download the container by running:
* that runs Linux
<source lang="console">$ singularity pull shub://singularityhub/ubuntu</source>
* with Singularity installed
* with Internet access,
* ideally where you have root, e.g., sudo, permissions.


[https://singularityhub.com/ Singularity Hub] allows one to search for images.
<!--T:112-->
If you do not have root permissions to create your images, be aware that <b>all permissions (user and group) inside the image will be set to those of the account the image is made under</b>. In general, it is not easy to re-establish proper permissions, thus, depending on the image content, you may not be able to upgrade it later.


===Creating an Image Using Docker Hub===
<!--T:116-->
For example, Debian and Ubuntu images <code>dpkg</code>, <code>apt-get</code>, and <code>apt</code> commands all require root to upgrade/install packages. Thus, if the ability to install and upgrade software in the future is important, then create the image on a Linux system where you have root permissions.


Suppose the Docker Hub URL for a container you want to use is:
<!--T:113-->
<pre>docker://ubuntu</pre>
<b>NOTE:</b> Any image you create on your own computer needs to be uploaded to the cluster before you can use that image.
then you would download the container by running:
<source lang="console">$ singularity pull docker://ubuntu</source>


[https://hub.docker.com/ Docker Hub] allows one to search for images.
====Build error when building on a Linux distribution==== <!--T:122-->
When building on certain Linux distributions, you may get this error despite having enough memory on your device.


===Creating a Tarball of Your Own Linux System===
<!--T:123-->
<source>$ WARNING: 'nodev' mount option set on /tmp, it could be a source of failure during build process
$FATAL: no memory left on device</source>


If you already have a configured Intel-CPU-based 64-bit version of Linux installed, then you can create a tarball of your system using the <code>tar</code> similar to this:
<!--T:124-->
<source lang="console">$ sudo tar -cvpf -C / my-system.tar --exclude=/dev --exclude=/proc --exclude=/sys</source>
Many modern Linux distributions, use an in-memory <code>tmpfs</code> filesystem, which may limit the size of the container you can build.
although you may probably want to exclude additional directories.
The [https://sylabs.io/guides/3.6/user-guide/build_env.html#temporary-folders Singularity Documentation] gives a more detailed explanation.


The created tarball will need to be converted into a Singularity image which is discussed [[#Creating an Image From a Tarball|later on this page]].
<!--T:125-->
If that is the case, you can solve the problem by setting the SINGULARITY_TMPDIR environment variable so that it points to a local disk.


===Creating an Image From a Tarball===
<!--T:126-->
<source>$ SINGULARITY_TMPDIR="disk/location" singularity build IMAGE_NAME.sif docker://DOCKER-IMAGE-NAME</source>


If you have a tarball or a gzip-compressed tarball, a Singularity image can be made from it by using the Singularity '''build''' command:
===Creating images on our clusters=== <!--T:114-->
<source lang="console">$ sudo singularity build my-image.simg my-system.tar</source>
if you are using your own system, or,
<source lang="console">$ singularity build my-image.simg my-system.tar</source>
if you are using a Compute Canada system.


The structure of the build command used to build an image from a tarball can be any one of the following:
<!--T:115-->
<pre>singularity build IMAGE_FILE_NAME TARBALL_FILE_NAME
If you decide to create an image on a cluster, be aware of the fact that you will <b>never</b> have <code>sudo</code> access and so the caveats of the previous section apply. Images can be created on any Alliance cluster or on a visualization computer, e.g., <code>gra-vdi.computecanada.ca</code>. Our image creation advice differs depending on which machine you use:
singularity build [OPTIONS] IMAGE_FILE_NAME TARBALL_FILE_NAME</pre>
* <code>beluga.computecanada.ca</code>: Connect using [[SSH]]. Use a login node to create the image.
* <code>cedar.computecanada.ca</code>: Connect using [[SSH]] Create the image in an interactive job. Do <b>not</b> use a login node.
* <code>graham.computecanada.ca</code>: Connect using [[SSH]] Use a login node to create the image.
* <code>gra-vdi.computecanada.ca</code>: Connect using [[VNC]]. Use a terminal window to create the image.
* <code>niagara.computecanada.ca</code>: Connect using [[SSH]] Use a login node to create the image.
** <b>IMPORTANT:</b> Do not bind to <code>/localscratch</code> on Niagara as it does not exist!
Among these options, <code>gra-vdi.computecanada.ca</code> is the <b>best</b> choice for creating images. The others have issues such as:
* <code>beluga</code>, <code>graham</code>, and <code>niagara</code>:
** fix the maximum amount of RAM that can be used on login nodes, and,
** there is no Internet access on compute nodes.
* <code>cedar</code>:
** login nodes cannot be used and,
** compute node jobs require specifying the amount of RAM needed but this is very difficult to know what is required in advance, thus if an error occurs, exit the interactive job and try again requesting more memory.


The full syntax of the build command can be obtained by running:
===Creating an image using Docker Hub and Dockerfile=== <!--T:16-->
<source lang="console">$ singularity build --help</source>


Singularity single-file images filenames typically have a <code>.simg</code> extension.
<!--T:17-->
[https://hub.docker.com/ Docker Hub] provides an interface to search for images. Docker also requires authentication at times to download images. If, when using Singularity, you get errors similar to these:
* <code>requested access to the resource is denied</code>
* <code>unauthorized: authentication required</code>
then this might have occurred for either or both of these reasons:
* your Docker URL is incorrect, and/or,
** NOTE: You can verify the Docker URL by using [https://hub.docker.com/ Docker Hub] and searching for the specific image you want.
* you need to [https://sylabs.io/guides/3.7/user-guide/singularity_and_docker.html?highlight=docker_password#authentication-via-interactive-login authenticate with Docker] in order to download the image.
** e.g., you need to add <code>--docker-login</code> after the Singularity <code>build</code> or <code>pull</code> command.


===Creating an Image From a Singularity Recipe===
<!--T:18-->
 
Suppose the Docker Hub URL for a container you want is <code>docker://ubuntu</code>,
'''NOTE:''' Singularity recipes require <code>root</code> permissions, thus, recipes can only be run on a computer where you can be the <code>root</code> user, e.g., your own Linux computer.
then you would download the container by running:
 
<source lang="console">$ singularity build myubuntuimage.sif docker://ubuntu</source>
====Recipe: Creating a Singularity Image of the Local Filesystem====


If the following:
<!--T:117-->
<pre>Bootstrap: self
This command will work on a Cedar compute node but not on Béluga or Graham, where compute nodes can not access the internet. We don't recommend building large Singularity images on login nodes because this process will affect other users and likely fail due to the high CPU and RAM usage. The following two-step process can solve the problem.
Exclude: /boot /dev /home /lost+found /media /mnt /opt /proc /run /sys</pre>
# Download a Docker image without converting it to Singularity. The [https://raw.githubusercontent.com/moby/moby/master/contrib/download-frozen-image-v2.sh download-frozen-image] tool from the [https://github.com/moby/moby/ Moby Project] can be used to do this. This step is not computationally intensive and can be done on any data transfer or login node.  
is placed in a file, e.g., <code>copy-drive-into-container-recipe</code> then it can be used to copy one's Linux system directly into a container (except for the excluded directories listed) by running:
# Convert the downloaded Docker image to Singularity image. This step is computationally intensive and so should be done on a compute node with a suitable allocation of memory and CPU.
<source lang="console">$ sudo singularity build self.simg copy-drive-into-container-recipe</source>
(Clearly such has to be run on your own Linux system and Singularity must already be installed on that system.)


If you had the need to periodically re-generate your Singularity image from a script, then you might write a Singularity recipe such as this:
<!--T:118-->
<pre>Bootstrap: localimage
As an example, let's download and build a Singularity image for the package [https://gqcg.github.io/GQCP/ GQCP].
From: ubuntu-16.04-x86_64.simg


%help
<!--T:119-->
This is a modified Ubuntu 16.06 x86_64 Singularity container image.
On a data transfer node or a login node download the Docker image:
<source>$ cd ~/scratch
$ wget https://raw.githubusercontent.com/moby/moby/master/contrib/download-frozen-image-v2.sh
$ sh download-frozen-image-v2.sh gqcp gqcg/gqcp:latest
$ cd gqcp && tar cf ../gqcp.tar * && cd ..</source>


%post
<!--T:120-->
  sudo apt-get -y update
Start an [[Running_jobs#Interactive_jobs|interactive job]]:
  sudo apt-get -y upgrade
<source>$ cd ~/scratch
  sudo apt-get -y install build-essential git
$ salloc --mem-per-cpu=2000 --cpus-per-task=4 --time=2:0:0</source>
  sudo apt-get -y install python-dev python-pip python-virtualenv python-numpy python-matplotlib
  sudo apt-get -y install vim
  sudo apt-get clean</pre>
The above recipe allows one to update-regenerate a Singularity image from an existing Singularity image. In the above example, the recipe ensures all security updates are applied and that certain software programs are installed. If this script was in a file called <code>update-existing-container-recipe</code> ''and'' the image <code>ubuntu-16.04-x86_64.simg</code> already exists in the current directory, then the image can be updated by running:
<source lang="console">$ sudo singularity build new-ubuntu-image.simg update-existing-container-recipe</source>


====Recipe: Creating a Singularity Image From a Docker URL====
<!--T:121-->
On the allocated compute node, build the Singularity image:
<source>$ module load singularity
$ singularity build gqcp.sif docker-archive://gqcp.tar</source>


The following Singularity recipe will download the latest [https://fenicsproject.org/ FEniCS] docker image and then run a series of installation commands to install a number of Python packages:
<!--T:133-->
One can also use a <b>Dockerfile</b> to create Singularity images, but this is a two step process.
* The first step is to create a Docker image with the Dockerfile. This step should be executed on your VM or Linux machine, where you have sudo access. Go to the directory which contains the Dockerfile and run the command <code>sudo docker build -t CC:latest .</code>. By passing '.' as a parameter we are asking Docker to search for the Dockerfile in the current directory. This command will create a Docker image with the name <b>CC</b> and assign the image a tag with the value </b>latest</b>. Remember that latest is the default tag that Docker assigns to an image, so if you don't provide a tag, the image will use the default tag value <b>latest</b>.
* The second step is to use the Docker image created above as the source for Singularity. The following command will create a Singularity image <b>cc_image_latest.sif</b> from the Docker image <b>CC:latest</b>,
<source>sudo singularity build cc_image_latest.sif docker-daemon://CC:latest</source>
You don't need to provide a path to the Docker image as the Docker daemon will automatically pick the image specified though the Docker registry, but we have to ensure that we use the correct image name and tag value.


{{
===Creating a custom image with sandbox=== <!--T:127-->
File
  |name=FEniCS-From-Docker-With-Python-Tools-Singularity-Recipe
  |lang="text"
  |contents=
Bootstrap: docker
From: quay.io/fenicsproject/stable:latest


%post
<!--T:128-->
  sudo apt-get -qq update
The <code>--sandbox</code> flag allows you to create a container within a writable directory.
  sudo apt-get -y upgrade
this allows for easy modifications of existing containers.
  sudo apt-get -y install python-bitstring python3-bitstring
<source>
  sudo apt-get -y install python-certifi python3-certifi
$ singularity build --sandbox IMAGE_NAME/ docker://DOCKER-IMAGE-NAME
  sudo apt-get -y install python-cryptography python3-cryptography
</source>
  sudo apt-get -y install python-cycler python3-cycler
Changes can be made within the container with the <code>--writable</code> flag.
  sudo apt-get -y install cython cython3
<source>
  sudo apt-get -y install python-dateutil python3-dateutil
$ singularity shell --writable IMAGE_NAME/
  sudo apt-get -y install python-deap python3-deap
</source>
  sudo apt-get -y install python-decorator python3-decorator
A sandbox directory can be converted into a <code>sif</code> file with the build command.
  sudo apt-get -y install python-ecdsa python3-ecdsa
<source>
  sudo apt-get -y install python-ecdsa python3-ecdsa
$ singularity build production.sif IMAGE_NAME/
  sudo apt-get -y install python-enum34
</source>
  sudo apt-get -y install python-funcsigs python3-funcsigs
  sudo apt-get -y install ipython ipython3 python-ipython-genutils python3-ipython-genutils
  sudo apt-get -y install python-jinja2 python3-jinja2
  sudo apt-get -y install python-jsonschema python3-jsonschema
  sudo apt-get -y install python-lockfile python3-lockfile
  sudo apt-get -y install python-markupsafe python3-markupsafe
  sudo apt-get -y install python-matplotlib python3-matplotlib
  sudo apt-get -y install python-mistune python3-mistune
  sudo apt-get -y install python-mock python3-mock
  sudo apt-get -y install python-mpmath python3-mpmath
  sudo apt-get -y install python-netaddr python3-netaddr
  sudo apt-get -y install python-netifaces python3-netifaces
  sudo apt-get -y install python-nose python3-nose
  sudo apt-get -y install ipython-notebook ipython3-notebook
  sudo apt-get -y install python-numpy python3-numpy
  sudo apt-get -y install python-pandas python3-pandas
  sudo apt-get -y install python-paramiko python3-paramiko
  sudo apt-get -y install python-path python3-path
  sudo apt-get -y install python-pathlib
  sudo apt-get -y install python-pbr python3-pbr
  sudo apt-get -y install python-pexpect python3-pexpect
  sudo apt-get -y install python-pickleshare python3-pickleshare
  sudo apt-get -y install python-prompt-toolkit python3-prompt-toolkit
  sudo apt-get -y install python-ptyprocess python3-ptyprocess
  sudo apt-get -y install python-pycryptopp
  sudo apt-get -y install python-pygments python3-pygments
  sudo apt-get -y install python-pyparsing python3-pyparsing
  sudo apt-get -y install python-zmq python3-zmq
  sudo apt-get -y install python-requests python3-requests
  sudo apt-get -y install python-scipy python3-scipy
  sudo apt-get -y install python-setuptools python3-setuptools
  sudo apt-get -y install python-simplegeneric python3-simplegeneric
  sudo apt-get -y install python-singledispatch python3-singledispatch
  sudo apt-get -y install python-six python3-six
  sudo apt-get -y install python-sympy python3-sympy
  sudo apt-get -y install python-terminado python3-terminado
  sudo apt-get -y install python-tornado python3-tornado
  sudo apt-get -y install python-traitlets python3-traitlets
  sudo apt-get clean
  sudo rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
}}


This recipe would be executed by running:
===Is sudo needed or not needed?=== <!--T:39-->


{{Command|sudo singularity build an-image-name.simg FEniCS-From-Docker-With-Python-Tools-Singularity-Recipe}}
<!--T:40-->
The Singularity documentation on [https://sylabs.io/guides/3.5/user-guide/build_a_container.html building a container] uses the <code>sudo</code> command. This is because, in general, many uses of the <code>build</code> command requires root, i.e., superuser, access on the system it is run. On a cluster, regular users do not have root account access so the <code>sudo</code> command cannot be used. If you are building a pre-built image from Singularity or Docker Hub, you typically will not need <code>sudo</code> access. If you do need root access to build an image, then you will either need to [[Technical support|ask support]] for help, or install Linux and Singularity on your own computer to have root account access.


and illustrates how one can easily make new images at later points-in-time.
<!--T:41-->
 
Many users don't need to use the <b>sudo</b> command to build their images from Singularity or Docker Hub. If <code>sudo</code> is not used, then the following will happen when you <b>build</b> the image:
===Creating/Updating an Image Interactively and Manually===
 
This section is incomplete and will be completed later.
 
===Is sudo Needed or Not Needed?===
 
Notice the different between the two commands is whether or not <code>'''sudo'''</code> appears. The <code>sudo</code> command runs the command after it as the '''root''' user (i.e., superuser) of that system. On Compute Canada systems, no users have such access so the '''sudo''' command cannot be used there. Presumably you do have '''root''' access on your own computer so you can use '''sudo''' on it.
 
It is entirely possible that you will not need to use the '''sudo''' command with your image. If <code>sudo</code> is not used, then the following will happen when you '''build''' the image:
* Singularity will output a warning that such may result in an image that does not work. This message is only a warning though --the image will still be created.
* Singularity will output a warning that such may result in an image that does not work. This message is only a warning though --the image will still be created.
* All filesystem permissions will be collapsed to be the permissions of the Linux user and group that is running '''singularity build'''. (This is normally the user and group you are logged in as.)
* All filesystem permissions will be collapsed to be the permissions of the Linux user and group that is running <code>singularity build</code>. (This is normally the user and group you are logged in as.)
If <code>sudo</code> is used, then all filesystem permissions will be kept as they are in the tarball.


<!--T:42-->
Typically one will not need to be concerned with retaining all filesystem permissions unless:
Typically one will not need to be concerned with retaining all filesystem permissions unless:
* one needs to regularly update/reconfigure the contents of the image, and,
* one needs to regularly update/reconfigure the contents of the image, and,
* tools used to update/reconfigure the contents of the image '''require''' those permissions to be retained.
* tools used to update/reconfigure the contents of the image <b>require</b> those permissions to be retained.
For example, many Linux distributions make it easy to update or install new software using commands such as:
For example, many Linux distributions make it easy to update or install new software using commands such as:
* <code>apt-get update && apt-get upgrade</code>
* <code>apt-get update && apt-get upgrade</code>
Line 213: Line 202:
* <code>dnf install some-software-package</code>
* <code>dnf install some-software-package</code>
* etc.
* etc.
It is possible that these and other commands may not run successfully unless filesystem permissions are retained. If this is of concern, then:
It is possible that these and other commands may not run successfully unless filesystem permissions are retained.
# Install Singularity on your own computer.
# Always build the Singularity image on your own computer using '''sudo'''.
If this is not a concern, then you may be able to build the Singularity image on a Compute Canada system without '''sudo''', however, be aware that such might fail for any of the following reasons:
* When using Lustre filesystems, e.g., <code>/project</code>, you may run out of quota. If this occurs, it is likely because there are too many small files causing all of your quota to be used. (Lustre is excellent for large files but stores small files very inefficiently.)
* Sometimes image creation will fail due to various user restrictions placed on the node you are using. The login nodes, in particular, have a number of restrictions which may prevent one from successfully building an image.
If such occurs, then you will need to create your image using your own computer. If this is an issue, then request assistance to create the Singularity image you want by creating a Compute Canada ticket by sending an email to [mailto:support@computecanada.ca].


==Using Singularity==
<!--T:109-->
Sometimes image creation will fail due to various user restrictions placed on the node you are using. The login nodes, in particular, have a number of restrictions which may prevent one from successfully building an image. If this is an issue, then request assistance to create the Singularity image by contacting [[Technical support]].


'''NOTE:''' The discussion below does not describe how to use Slurm to run interactive or batch jobs --it only describes how to use Singularity. For interactive and batch job information see the [[Running jobs]] page.
==Using Singularity== <!--T:43-->


Unlike perhaps when you created your Singularity image, you will never use, don't need to use, and cannot use <code>sudo</code> to run programs in your image on Compute Canada systems. There are a number of ways to run programs in your image:
<!--T:44-->
# Running '''commands''' interactively in one Singularity session.
<b>NOTE:</b> The discussion below does not describe how to use Slurm to run interactive or batch jobs --it only describes how to use Singularity. For interactive and batch job information see the [[Running jobs]] page.
# Run a '''single command''' which executes and then stops running.
# Run a container instance in order to run '''daemons''' which may have '''backgrounded processes'''.


===Running Commands Interactively===
<!--T:45-->
Unlike perhaps when you created your Singularity image, you cannot use <code>sudo</code> to run programs in your image on a cluster. There are a number of ways to run programs in your image:
# Running <b>commands</b> interactively in one Singularity session.
# Run a <b>single command</b> which executes and then stops running.
# Run a container instance in order to run <b>daemons</b> which may have <b>backgrounded processes</b>.


This section is incomplete and will be completed later.
===Running commands interactively=== <!--T:46-->


===Running a Single Command===
<!--T:47-->
Singularity can be used interactively by using its shell command, e.g.,


This section is incomplete and will be completed later.
<!--T:48-->
<source lang="console">$ singularity shell --help</source>


===Running Container Instances===
<!--T:49-->
will give help on shell command usage. The following:


This section is incomplete and will be completed later.
<!--T:50-->
<source lang="console">$ singularity shell -B /home -B /project -B /scratch -B /localscratch myimage.simg</source>


===Bind Mounts===
<!--T:51-->
will do the following within the container image <code>myimage.simg</code>:
* bind mount <code>/home</code> so that all home directories can be accessed (subject to your account's permissions)
* bind mount <code>/project</code> so that project directories can be accessed (subject to your account's permissions)
* bind mount <code>/scratch</code> so that the scratch directory can be accessed (subject to your account's permissions)
* bind mount <code>/localscratch</code> so that the localscratch directory can be accessed (subject to your account's permissions)
* run a shell (e.g., <code>/bin/bash</code>)


This section is incomplete and will be completed later.
<!--T:52-->
If this command is successful, you can interactively run commands from within your container while still being able to access your files in home, project, scratch, and localscratch. :-)
* NOTE: When done, type "exit" to exit the shell.


==HPC Issues With Singularity==
<!--T:53-->
In some cases, you will not want the pollution of environment variables from your shell. You can run a "clean environment" shell by adding a <code>-e</code> option, e.g.,


This section is incomplete and will be completed later.
<!--T:54-->
<source lang="console">$ singularity shell -e -B /home -B /project -B /scratch -B /localscratch myimage.simg</source>


=See Also=
<!--T:55-->
but know you may need to define some shell environment variables such as <code>$USER</code>.
 
<!--T:56-->
Finally, if you are using Singularity interactively on your own machine, in order for your changes to the image to be written to the disk, you must:
 
<!--T:57-->
* be using a Singularity "sandbox" image (i.e., be using a directory not the read-only .simg file)
* be using the <code>-w</code> option, and,
* be using <code>sudo</code>
 
<!--T:58-->
e.g., first create your sandbox image:
 
<!--T:59-->
<source lang="console">$ sudo singularity build -s myimage-dir myimage.simg</source>
 
<!--T:60-->
and then engage with Singularity interactively:
 
<!--T:61-->
<source lang="console">$ sudo singularity shell -w myimage-dir</source>
 
<!--T:62-->
When done, you can build a new/updated simg file, with the command:
 
<!--T:63-->
<source lang="console">$ sudo singularity build myimage-new.simg myimage-dir/</source>
 
<!--T:64-->
and upload myimage-new.simg to a cluster in order to use it.
 
===Running a single command=== <!--T:65-->
 
<!--T:66-->
When submitting jobs that invoke commands in Singularity containers, one will either use Singularity's <code>exec</code> or <code>run</code> commands.
* The <code>exec</code> command does not require any configuration.
* The <code>run</code> command requires configuring an application within a Singularity recipe file and this is not discussed on this page.
 
<!--T:67-->
The Singularity <code>exec</code> command's options are almost identical to the <code>shell</code> command's options, e.g.,
 
<!--T:68-->
<source lang="console">$ singularity exec --help</source>
 
<!--T:69-->
When not asking for help, the <code>exec</code> command runs the command you specify within the container and then leaves the container, e.g.,
 
<!--T:70-->
<source lang="console">$ singularity exec -B /home -B /project -B /scratch -B /localscratch myimage.simg ls /</source>
 
<!--T:71-->
which will output the contents of the root directory within the container. The version of <code>ls</code> is the one installed within the container!
For example, should GCC's <code>gcc</code> be installed in the myimage.simg container, then this command:
 
<!--T:72-->
<source lang="console">$ singularity exec -B /home -B /project -B /scratch -B /localscratch myimage.simg gcc -v</source>
 
<!--T:73-->
will output the version information of what is installed within the container whereas running at the normal shell prompt:
 
<!--T:74-->
<source lang="console">$ gcc -v</source>
 
<!--T:75-->
will output the version of GCC currently loaded on the cluster.
 
 
<!--T:76-->
If you need to run a single command from within your Singularity container in a job, then the <code>exec</code> command will suffice.
Remember to [[#Bind Mounts|bind mount]] the directories you will need access to in order for your job to run successfully.
 
<!--T:771-->
Singularity can also accept user defined environment variables. This can be achieved via <code>--env-file</code> flag. We pass path of the file that define all the variables which we want to use inside the singularity context as an argument to the <code>--env-file</code> flag. The <code>--env-file</code> flag is especially useful for the scenarios when we want to use the <code>-e</code> flag with <code>singularity exec</code> which forces a "clean environment".
For example, if we want to use the <code>PYSPARK_SUBMIT_ARGS</code> environment variable inside the singularity context, we will create a file, for example <code>envfile</code>, and define the variable <code>PYSPARK_SUBMIT_ARGS</code> in it. We can define more than one variable inside the file.
<source lang="console">PYSPARK_SUBMIT_ARGS='--driver-memory 96g  --driver-java-options "-verbose:gc  -XX:+UseSerialGC  -XX:-UseGCOverheadLimit" pyspark-shell'</source>
 
<!--T:772-->
And then we pass the  path of file to the singularity command via <code>--env-file</code> flag.
 
<!--T:773-->
<source lang="console">$ singularity exec --env-file envfile  myimage.simg gcc -v</source>
 
<!--T:774-->
In the above example we assume that <code>envfile</code> is present at the same location from where we execute the singularity command and thus we passed just the filename rather than the path to the file.
 
 
===Running container instances=== <!--T:77-->
 
<!--T:78-->
Should you need to run daemons and backgrounded processes within your container, then do <b>not</b> use the Singularity <code>exec</code> command!
Instead you want to use Singularity's <code>instance.start</code> and <code>instance.stop</code> commands to create and destroy sessions (i.e., container instances).
By using sessions, Singularity will ensure that all programs running within the instance are terminated when your job ends, unexpectedly dies, is killed, etc.
 
<!--T:79-->
To start a Singularity session instance, decide on a name for this session, e.g., <code>quadrat5run</code>, and run the <code>instance.start</code> command
specifying the image name, e.g., <code>myimage.simg</code>, and your session name:
 
<!--T:80-->
<source lang="console">$ singularity instance.start myimage.simg quadrat5run</source>
 
<!--T:81-->
A session (and all associated programs that are running) can be stopped (i.e., destroyed/killed) by running the <code>instance.stop</code> command, e.g.,
 
<!--T:82-->
<source lang="console">$ singularity instance.stop myimage.simg quadrat5run</source>
 
<!--T:83-->
At any time you can obtain a list of all sessions you currently have running by running:
 
<!--T:84-->
<source lang="console">$ singularity instance.list</source>
 
<!--T:85-->
which will list the daemon name, its PID, and the path to the container's image.
 
<!--T:86-->
With a session started, programs can be run using Singularity's <code>shell</code>, <code>exec</code>, or <code>run</code> commands by specifying
the name of the session immediately after the image name prefixed with <code>instance://</code>, e.g.,
 
<!--T:87-->
<source lang="console">$ singularity instance.start mysessionname
$ singularity exec myimage.simg instance://mysessionname ps -eaf
$ singularity shell myimage.simg instance://mysessionname
nohup find / -type d >dump.txt
exit
$ singularity exec myimage.simg instance://mysessionname ps -eaf
$ singularity instance.stop mysessionname
</source>
 
===Bind mounts=== <!--T:88-->
 
<!--T:89-->
When running a program within a Singularity container, by default, it can only see the files within the container image and the current directory.
Realistically your Singularity jobs will need to mount the various filesystems where your files are. This is done using the <code>-B</code> option
to the Singularity <code>shell</code>, <code>exec</code>, or <code>run</code> commands, e.g.,
 
<!--T:90-->
<source lang="console">$ singularity shell -B /home -B /project -B /scratch -B /localscratch myimage.simg</source>
<source lang="console">$ singularity exec -B /home -B /project -B /scratch -B /localscratch myimage.simg ls /</source>
<source lang="console">$ singularity run -B /home -B /project -B /scratch -B /localscratch:/temp myimage.simg some-program</source>
 
<!--T:91-->
The previous three commands show how to bind mount the various filesystems on our clusters, i.e., within the container image <code>myimage.simg</code> these commands bind mount:
* <code>/home</code> so that all home directories can be accessed (subject to your account's permissions)
* <code>/project</code> so that project directories can be accessed (subject to your account's permissions)
* <code>/scratch</code> so that the scratch directory can be accessed (subject to your account's permissions)
* <code>/localscratch</code> so that the localscratch directory can be accessed (subject to your account's permissions)
In the final item we demonstrate how we can change the mount name that is visible within the Singularity container, so that <code>/localscratch</code> will be seen as <code>/temp</code> inside the container. This can be useful when you want to use storage like <code>$SLURM_TMPDIR</code> which is attached directly to the compute node and available inside a job. The program itself can abstract away the details by always using <code>/temp</code>.
 
<!--T:92-->
In most cases, it is not recommended to directly mount each directory you need as this can cause access issues. Instead, mount the top directory of the filesystem as shown above.
 
==HPC issues== <!--T:93-->
 
===Running MPI programs from within a container=== <!--T:94-->
 
<!--T:95-->
If you are running MPI programs nothing special needs to be done for jobs running on a single node.
 
<!--T:97-->
To run jobs across nodes with MPI requires:
 
<!--T:101-->
* Ensuring your MPI program is compiled using the OpenMPI installed inside your Singularity container.
** Ideally the version of OpenMPI inside the container is version 3 or 4. Version 2 may or may not work. Version 1 will not work.
* Ensure the MPI installation in the container can use the same process-management interface library as the MPI version on the cluster, e.g. PMI-2 or PMIx.
* Ensuring your SLURM job script uses <code>srun</code> to run the MPI program, and have srun use a pmi library that is supported by the MPI implementation in the container. Do not use <code>mpirun</code> or <code>mpiexec</code>, e.g.,
<source lang="bash">
srun --mpi=pmi2 singularity exec /path/to/your/singularity/image.sif /path/to/your-program
</source>
if the MPI implementation in the container only supports PMI-2 (use <code>--mpi=pmix</code> for PMIx).
* Ensure there are no module load commands in your job script.
* Install the <code>slurm-client</code> package from your distribution within your container to enable interaction(s) with the Slurm scheduler.
* Before submitting the job using <code>sbatch</code>, in the CC shell environment, module load the following:
** <code>singularity</code>
** <code>openmpi</code> (This does not need to match the OpenMPI version installed inside the container. Ideally use version 4 or version 3; version 2 may or may not work; version 1 will not work.)
 
<!--T:102-->
Finally, ensure that a high performance interconnect package is also installed in your image, i.e.,
* clusters using OmniPath need libpsm2, and,
* clusters using Infiniband need UCX.
 
<!--T:775-->
To see which libraries MPI was configured with on the cluster, use the command:
* <code> ompi_info --config</code> for OpenMPI
* <code> mpiexec -info</code> for MPICH
The information from these commands will provide information about which libraries to use when installing MPI within the Singularity container.
 
=== Using CUDA on a cluster === <!--T:129-->
 
<!--T:130-->
If you are running programs which use the CUDA library, you must make sure that your Singularity container has CUDA installed.
 
<!--T:131-->
The <code>--nv</code> flag needs to be added to make CUDA work.
 
<!--T:132-->
<source>
$ srun singularity run --nv container-name.sif [job to do]
</source>
 
==Changing Singularity default directories== <!--T:103-->
 
<!--T:104-->
You can override Singularity's default temporary and cache directories by setting these environment variables before running <code>singularity</code>:
 
<!--T:105-->
* <code>SINGULARITY_CACHEDIR</code>: the directory where singularity will download (and cache) files
* <code>SINGULARITY_TMPDIR</code>: the directory where singularity will write temporary files including when building (squashfs) images
 
<!--T:106-->
For example, to tell singularity to use your scratch space for its cache and temporary files, one might run:
 
<!--T:107-->
<source lang="console">$ mkdir -p /scratch/$USER/singularity/{cache,tmp}
$ export SINGULARITY_CACHEDIR="/scratch/$USER/singularity/cache"
$ export SINGULARITY_TMPDIR="/scratch/$USER/singularity/tmp"
</source>
 
<!--T:108-->
before running singularity.
 
=See also= <!--T:98-->
* SHARCNET General Interest Webinar, "Singularity", presented by Paul Preney on Feb. 14, 2018. See this [https://www.youtube.com/watch?v=C4va7d7GxjM YouTube Video] as well as the [https://www.sharcnet.ca/help/index.php/Online_Seminars SHARCNET Online Seminars] page for slides.
* SHARCNET General Interest Webinar, "Singularity", presented by Paul Preney on Feb. 14, 2018. See this [https://www.youtube.com/watch?v=C4va7d7GxjM YouTube Video] as well as the [https://www.sharcnet.ca/help/index.php/Online_Seminars SHARCNET Online Seminars] page for slides.


=References=
=References= <!--T:99-->
<references/>
<references/>
<!--T:100-->
[[Category:Pages with video links]]
</translate>

Latest revision as of 21:10, 19 May 2023

Other languages:

Please use Apptainer instead[edit]

Much of this information is now outdated since Singularity has been deprecated in favor of Apptainer on all our clusters. Please refer to Apptainer instead.

Overview[edit]

Singularity[1] is open source software created by Berkeley Lab:

  • as a secure way to use Linux containers on Linux multi-user clusters,
  • as a way to enable users to have full control of their environment, and,
  • as a way to package scientific software and deploy such to different clusters having the same architecture.

i.e., it provides operating-system-level virtualization commonly called containers.

A container is different from a virtual machine in that a container:

  • likely has less overhead, and,
  • can only run programs capable of running in the same operating system kernel (i.e., Linux when using Singularity) for the same hardware architecture.

(Virtual machines can run different operating systems and sometimes support running software designed for foreign CPU architectures.)

Containers use Linux control groups (cgroups), kernel namespaces, and an overlay filesystem where:

  • cgroups limit, control, and isolate resource usage (e.g., RAM, disk I/O, CPU access),
  • kernel namespaces virtualize and isolate operating system resources of a group of processes, e.g., process and user IDs, filesystems, network access; and,
  • overlay filesystems can be used to enable the appearance of writing to otherwise read-only filesystems.

Singularity is similar to other container solutions such as Docker[2] except Singularity was specifically designed to enable containers to be used securely without requiring any special permissions especially on multi-user compute clusters.[3]

Availability[edit]

Singularity is available on our clusters.

Should you wish to use Singularity on your own computer, you will need to download and install it per its documentation.[4] You should be using a relatively recent version of some Linux distribution (e.g., ideally your kernel is v3.10.0 or newer).

Singularity on a cluster[edit]

Loading a module[edit]

To use Singularity, first load the specific module you would like to use, e.g.,

$ module load singularity/2.5

Should you need to see all versions of Singularity modules that are available then run:

$ module spider singularity

Creating images[edit]

Before using Singularity, you will first need to create a (container) image. A Singularity image is either a file or a directory containing an installation of Linux. One can create a Singularity image using the singularity build command, e.g.,

  • singularity build WHAT-TO-WRITE SPECIAL-URI-OR-PATH

where WHAT-TO-WRITE is:

  • a filename of the singularity image file (*.sif) where the built image will be written
  • a directory if one is building a sandbox using the --sandbox option typically on one's own (Linux) computer (requiring root account access)

and SPECIAL-URI-OR-PATH is:

  • a URI starting with library:// to build from a Container Library,
  • a URI starting with docker:// to build from Docker Hub,
  • a URI starting with shub:// to build from Singularity Hub,
  • a path to an existing container,
  • a path to a directory (to build from a sandbox), or
  • a path to a Singularity image file (which is a recipe on how to build the image).

Warning[edit]

You are strongly advised to create Singularity images using a computer or virtual machine

  • that runs Linux
  • with Singularity installed
  • with Internet access,
  • ideally where you have root, e.g., sudo, permissions.

If you do not have root permissions to create your images, be aware that all permissions (user and group) inside the image will be set to those of the account the image is made under. In general, it is not easy to re-establish proper permissions, thus, depending on the image content, you may not be able to upgrade it later.

For example, Debian and Ubuntu images dpkg, apt-get, and apt commands all require root to upgrade/install packages. Thus, if the ability to install and upgrade software in the future is important, then create the image on a Linux system where you have root permissions.

NOTE: Any image you create on your own computer needs to be uploaded to the cluster before you can use that image.

Build error when building on a Linux distribution[edit]

When building on certain Linux distributions, you may get this error despite having enough memory on your device.

$ WARNING: 'nodev' mount option set on /tmp, it could be a source of failure during build process
$FATAL: no memory left on device

Many modern Linux distributions, use an in-memory tmpfs filesystem, which may limit the size of the container you can build. The Singularity Documentation gives a more detailed explanation.

If that is the case, you can solve the problem by setting the SINGULARITY_TMPDIR environment variable so that it points to a local disk.

$ SINGULARITY_TMPDIR="disk/location" singularity build IMAGE_NAME.sif docker://DOCKER-IMAGE-NAME

Creating images on our clusters[edit]

If you decide to create an image on a cluster, be aware of the fact that you will never have sudo access and so the caveats of the previous section apply. Images can be created on any Alliance cluster or on a visualization computer, e.g., gra-vdi.computecanada.ca. Our image creation advice differs depending on which machine you use:

  • beluga.computecanada.ca: Connect using SSH. Use a login node to create the image.
  • cedar.computecanada.ca: Connect using SSH Create the image in an interactive job. Do not use a login node.
  • graham.computecanada.ca: Connect using SSH Use a login node to create the image.
  • gra-vdi.computecanada.ca: Connect using VNC. Use a terminal window to create the image.
  • niagara.computecanada.ca: Connect using SSH Use a login node to create the image.
    • IMPORTANT: Do not bind to /localscratch on Niagara as it does not exist!

Among these options, gra-vdi.computecanada.ca is the best choice for creating images. The others have issues such as:

  • beluga, graham, and niagara:
    • fix the maximum amount of RAM that can be used on login nodes, and,
    • there is no Internet access on compute nodes.
  • cedar:
    • login nodes cannot be used and,
    • compute node jobs require specifying the amount of RAM needed but this is very difficult to know what is required in advance, thus if an error occurs, exit the interactive job and try again requesting more memory.

Creating an image using Docker Hub and Dockerfile[edit]

Docker Hub provides an interface to search for images. Docker also requires authentication at times to download images. If, when using Singularity, you get errors similar to these:

  • requested access to the resource is denied
  • unauthorized: authentication required

then this might have occurred for either or both of these reasons:

  • your Docker URL is incorrect, and/or,
    • NOTE: You can verify the Docker URL by using Docker Hub and searching for the specific image you want.
  • you need to authenticate with Docker in order to download the image.
    • e.g., you need to add --docker-login after the Singularity build or pull command.

Suppose the Docker Hub URL for a container you want is docker://ubuntu, then you would download the container by running:

$ singularity build myubuntuimage.sif docker://ubuntu

This command will work on a Cedar compute node but not on Béluga or Graham, where compute nodes can not access the internet. We don't recommend building large Singularity images on login nodes because this process will affect other users and likely fail due to the high CPU and RAM usage. The following two-step process can solve the problem.

  1. Download a Docker image without converting it to Singularity. The download-frozen-image tool from the Moby Project can be used to do this. This step is not computationally intensive and can be done on any data transfer or login node.
  2. Convert the downloaded Docker image to Singularity image. This step is computationally intensive and so should be done on a compute node with a suitable allocation of memory and CPU.

As an example, let's download and build a Singularity image for the package GQCP.

On a data transfer node or a login node download the Docker image:

$ cd ~/scratch
$ wget https://raw.githubusercontent.com/moby/moby/master/contrib/download-frozen-image-v2.sh
$ sh download-frozen-image-v2.sh gqcp gqcg/gqcp:latest
$ cd gqcp && tar cf ../gqcp.tar * && cd ..

Start an interactive job:

$ cd ~/scratch
$ salloc --mem-per-cpu=2000 --cpus-per-task=4 --time=2:0:0

On the allocated compute node, build the Singularity image:

$ module load singularity
$ singularity build gqcp.sif docker-archive://gqcp.tar

One can also use a Dockerfile to create Singularity images, but this is a two step process.

  • The first step is to create a Docker image with the Dockerfile. This step should be executed on your VM or Linux machine, where you have sudo access. Go to the directory which contains the Dockerfile and run the command sudo docker build -t CC:latest .. By passing '.' as a parameter we are asking Docker to search for the Dockerfile in the current directory. This command will create a Docker image with the name CC and assign the image a tag with the value latest. Remember that latest is the default tag that Docker assigns to an image, so if you don't provide a tag, the image will use the default tag value latest.
  • The second step is to use the Docker image created above as the source for Singularity. The following command will create a Singularity image cc_image_latest.sif from the Docker image CC:latest,
sudo singularity build cc_image_latest.sif docker-daemon://CC:latest

You don't need to provide a path to the Docker image as the Docker daemon will automatically pick the image specified though the Docker registry, but we have to ensure that we use the correct image name and tag value.

Creating a custom image with sandbox[edit]

The --sandbox flag allows you to create a container within a writable directory. this allows for easy modifications of existing containers.

$ singularity build --sandbox IMAGE_NAME/ docker://DOCKER-IMAGE-NAME

Changes can be made within the container with the --writable flag.

$ singularity shell --writable IMAGE_NAME/

A sandbox directory can be converted into a sif file with the build command.

$ singularity build production.sif IMAGE_NAME/

Is sudo needed or not needed?[edit]

The Singularity documentation on building a container uses the sudo command. This is because, in general, many uses of the build command requires root, i.e., superuser, access on the system it is run. On a cluster, regular users do not have root account access so the sudo command cannot be used. If you are building a pre-built image from Singularity or Docker Hub, you typically will not need sudo access. If you do need root access to build an image, then you will either need to ask support for help, or install Linux and Singularity on your own computer to have root account access.

Many users don't need to use the sudo command to build their images from Singularity or Docker Hub. If sudo is not used, then the following will happen when you build the image:

  • Singularity will output a warning that such may result in an image that does not work. This message is only a warning though --the image will still be created.
  • All filesystem permissions will be collapsed to be the permissions of the Linux user and group that is running singularity build. (This is normally the user and group you are logged in as.)

Typically one will not need to be concerned with retaining all filesystem permissions unless:

  • one needs to regularly update/reconfigure the contents of the image, and,
  • tools used to update/reconfigure the contents of the image require those permissions to be retained.

For example, many Linux distributions make it easy to update or install new software using commands such as:

  • apt-get update && apt-get upgrade
  • apt-get install some-software-package
  • yum install some-software-package
  • dnf install some-software-package
  • etc.

It is possible that these and other commands may not run successfully unless filesystem permissions are retained.

Sometimes image creation will fail due to various user restrictions placed on the node you are using. The login nodes, in particular, have a number of restrictions which may prevent one from successfully building an image. If this is an issue, then request assistance to create the Singularity image by contacting Technical support.

Using Singularity[edit]

NOTE: The discussion below does not describe how to use Slurm to run interactive or batch jobs --it only describes how to use Singularity. For interactive and batch job information see the Running jobs page.

Unlike perhaps when you created your Singularity image, you cannot use sudo to run programs in your image on a cluster. There are a number of ways to run programs in your image:

  1. Running commands interactively in one Singularity session.
  2. Run a single command which executes and then stops running.
  3. Run a container instance in order to run daemons which may have backgrounded processes.

Running commands interactively[edit]

Singularity can be used interactively by using its shell command, e.g.,

$ singularity shell --help

will give help on shell command usage. The following:

$ singularity shell -B /home -B /project -B /scratch -B /localscratch myimage.simg

will do the following within the container image myimage.simg:

  • bind mount /home so that all home directories can be accessed (subject to your account's permissions)
  • bind mount /project so that project directories can be accessed (subject to your account's permissions)
  • bind mount /scratch so that the scratch directory can be accessed (subject to your account's permissions)
  • bind mount /localscratch so that the localscratch directory can be accessed (subject to your account's permissions)
  • run a shell (e.g., /bin/bash)

If this command is successful, you can interactively run commands from within your container while still being able to access your files in home, project, scratch, and localscratch. :-)

  • NOTE: When done, type "exit" to exit the shell.

In some cases, you will not want the pollution of environment variables from your shell. You can run a "clean environment" shell by adding a -e option, e.g.,

$ singularity shell -e -B /home -B /project -B /scratch -B /localscratch myimage.simg

but know you may need to define some shell environment variables such as $USER.

Finally, if you are using Singularity interactively on your own machine, in order for your changes to the image to be written to the disk, you must:

  • be using a Singularity "sandbox" image (i.e., be using a directory not the read-only .simg file)
  • be using the -w option, and,
  • be using sudo

e.g., first create your sandbox image:

$ sudo singularity build -s myimage-dir myimage.simg

and then engage with Singularity interactively:

$ sudo singularity shell -w myimage-dir

When done, you can build a new/updated simg file, with the command:

$ sudo singularity build myimage-new.simg myimage-dir/

and upload myimage-new.simg to a cluster in order to use it.

Running a single command[edit]

When submitting jobs that invoke commands in Singularity containers, one will either use Singularity's exec or run commands.

  • The exec command does not require any configuration.
  • The run command requires configuring an application within a Singularity recipe file and this is not discussed on this page.

The Singularity exec command's options are almost identical to the shell command's options, e.g.,

$ singularity exec --help

When not asking for help, the exec command runs the command you specify within the container and then leaves the container, e.g.,

$ singularity exec -B /home -B /project -B /scratch -B /localscratch myimage.simg ls /

which will output the contents of the root directory within the container. The version of ls is the one installed within the container! For example, should GCC's gcc be installed in the myimage.simg container, then this command:

$ singularity exec -B /home -B /project -B /scratch -B /localscratch myimage.simg gcc -v

will output the version information of what is installed within the container whereas running at the normal shell prompt:

$ gcc -v

will output the version of GCC currently loaded on the cluster.


If you need to run a single command from within your Singularity container in a job, then the exec command will suffice. Remember to bind mount the directories you will need access to in order for your job to run successfully.

Singularity can also accept user defined environment variables. This can be achieved via --env-file flag. We pass path of the file that define all the variables which we want to use inside the singularity context as an argument to the --env-file flag. The --env-file flag is especially useful for the scenarios when we want to use the -e flag with singularity exec which forces a "clean environment".

For example, if we want to use the PYSPARK_SUBMIT_ARGS environment variable inside the singularity context, we will create a file, for example envfile, and define the variable PYSPARK_SUBMIT_ARGS in it. We can define more than one variable inside the file.

PYSPARK_SUBMIT_ARGS='--driver-memory 96g  --driver-java-options "-verbose:gc  -XX:+UseSerialGC  -XX:-UseGCOverheadLimit" pyspark-shell'

And then we pass the path of file to the singularity command via --env-file flag.

$ singularity exec --env-file envfile  myimage.simg gcc -v

In the above example we assume that envfile is present at the same location from where we execute the singularity command and thus we passed just the filename rather than the path to the file.


Running container instances[edit]

Should you need to run daemons and backgrounded processes within your container, then do not use the Singularity exec command! Instead you want to use Singularity's instance.start and instance.stop commands to create and destroy sessions (i.e., container instances). By using sessions, Singularity will ensure that all programs running within the instance are terminated when your job ends, unexpectedly dies, is killed, etc.

To start a Singularity session instance, decide on a name for this session, e.g., quadrat5run, and run the instance.start command specifying the image name, e.g., myimage.simg, and your session name:

$ singularity instance.start myimage.simg quadrat5run

A session (and all associated programs that are running) can be stopped (i.e., destroyed/killed) by running the instance.stop command, e.g.,

$ singularity instance.stop myimage.simg quadrat5run

At any time you can obtain a list of all sessions you currently have running by running:

$ singularity instance.list

which will list the daemon name, its PID, and the path to the container's image.

With a session started, programs can be run using Singularity's shell, exec, or run commands by specifying the name of the session immediately after the image name prefixed with instance://, e.g.,

$ singularity instance.start mysessionname
$ singularity exec myimage.simg instance://mysessionname ps -eaf
$ singularity shell myimage.simg instance://mysessionname 
nohup find / -type d >dump.txt
exit
$ singularity exec myimage.simg instance://mysessionname ps -eaf
$ singularity instance.stop mysessionname

Bind mounts[edit]

When running a program within a Singularity container, by default, it can only see the files within the container image and the current directory. Realistically your Singularity jobs will need to mount the various filesystems where your files are. This is done using the -B option to the Singularity shell, exec, or run commands, e.g.,

$ singularity shell -B /home -B /project -B /scratch -B /localscratch myimage.simg
$ singularity exec -B /home -B /project -B /scratch -B /localscratch myimage.simg ls /
$ singularity run -B /home -B /project -B /scratch -B /localscratch:/temp myimage.simg some-program

The previous three commands show how to bind mount the various filesystems on our clusters, i.e., within the container image myimage.simg these commands bind mount:

  • /home so that all home directories can be accessed (subject to your account's permissions)
  • /project so that project directories can be accessed (subject to your account's permissions)
  • /scratch so that the scratch directory can be accessed (subject to your account's permissions)
  • /localscratch so that the localscratch directory can be accessed (subject to your account's permissions)

In the final item we demonstrate how we can change the mount name that is visible within the Singularity container, so that /localscratch will be seen as /temp inside the container. This can be useful when you want to use storage like $SLURM_TMPDIR which is attached directly to the compute node and available inside a job. The program itself can abstract away the details by always using /temp.

In most cases, it is not recommended to directly mount each directory you need as this can cause access issues. Instead, mount the top directory of the filesystem as shown above.

HPC issues[edit]

Running MPI programs from within a container[edit]

If you are running MPI programs nothing special needs to be done for jobs running on a single node.

To run jobs across nodes with MPI requires:

  • Ensuring your MPI program is compiled using the OpenMPI installed inside your Singularity container.
    • Ideally the version of OpenMPI inside the container is version 3 or 4. Version 2 may or may not work. Version 1 will not work.
  • Ensure the MPI installation in the container can use the same process-management interface library as the MPI version on the cluster, e.g. PMI-2 or PMIx.
  • Ensuring your SLURM job script uses srun to run the MPI program, and have srun use a pmi library that is supported by the MPI implementation in the container. Do not use mpirun or mpiexec, e.g.,
srun --mpi=pmi2 singularity exec /path/to/your/singularity/image.sif /path/to/your-program

if the MPI implementation in the container only supports PMI-2 (use --mpi=pmix for PMIx).

  • Ensure there are no module load commands in your job script.
  • Install the slurm-client package from your distribution within your container to enable interaction(s) with the Slurm scheduler.
  • Before submitting the job using sbatch, in the CC shell environment, module load the following:
    • singularity
    • openmpi (This does not need to match the OpenMPI version installed inside the container. Ideally use version 4 or version 3; version 2 may or may not work; version 1 will not work.)

Finally, ensure that a high performance interconnect package is also installed in your image, i.e.,

  • clusters using OmniPath need libpsm2, and,
  • clusters using Infiniband need UCX.

To see which libraries MPI was configured with on the cluster, use the command:

  • ompi_info --config for OpenMPI
  • mpiexec -info for MPICH

The information from these commands will provide information about which libraries to use when installing MPI within the Singularity container.

Using CUDA on a cluster[edit]

If you are running programs which use the CUDA library, you must make sure that your Singularity container has CUDA installed.

The --nv flag needs to be added to make CUDA work.

$ srun singularity run --nv container-name.sif [job to do]

Changing Singularity default directories[edit]

You can override Singularity's default temporary and cache directories by setting these environment variables before running singularity:

  • SINGULARITY_CACHEDIR: the directory where singularity will download (and cache) files
  • SINGULARITY_TMPDIR: the directory where singularity will write temporary files including when building (squashfs) images

For example, to tell singularity to use your scratch space for its cache and temporary files, one might run:

$ mkdir -p /scratch/$USER/singularity/{cache,tmp}
$ export SINGULARITY_CACHEDIR="/scratch/$USER/singularity/cache"
$ export SINGULARITY_TMPDIR="/scratch/$USER/singularity/tmp"

before running singularity.

See also[edit]

References[edit]

  1. Singularity Software website: https://www.sylabs.io/docs/
  2. Docker Software website: https://www.docker.com/
  3. Singularity Security Documentation: https://www.sylabs.io/guides/2.5.1/admin-guide/security.html
  4. Singularity Documentation: https://www.sylabs.io/docs/