Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Containers: Docker and Apptainer

The fundamental problems that containerization tools like Docker and Apptainer (formerly Singularity) solve for researchers primarily revolve around reproducibility, dependency management, and environment consistency.

What are containers?

1. Ensuring Reproducibility and Managing Dependencies

One of the central problems solved by containerization is the difficulty of replicating software environments, both for sharing and for future use.

2. Isolation and System Integrity

Containerization solves problems related to maintaining a clean and functional host system:

3. Solving Security and Deployment Challenges in High-Performance Computing (HPC)

For researchers utilizing supercomputers or shared clusters, Apptainer (Singularity) addresses specific security and deployment hurdles that traditional container solutions like Docker cannot:

Getting Started with Docker

The basic process for working with Docker involves interacting with two main components: Docker Images (read-only snapshots of the environment) and Docker Containers (live instances of those images). This process can generally be broken down into three phases: running existing containers, building custom images, and managing data persistence.

1. Running Existing Containers (Using Images from a Registry)

The most common starting point is running a container based on an image found in a repository like Docker Hub. The Docker Engine, a command line program, is used to manage these steps.

  1. Find the Image: Locate the desired Docker image (often specifying an image tag or version) on a central registry, such as Docker Hub.

  2. Retrieve the Image (Pull): You can retrieve the image using the docker pull command. Alternatively, the necessary image layers are often downloaded automatically if the image is not found locally when executing the run command.

  3. Run the Container: Use the docker run command to create and start a live instance (a container) from the image.

    • Example syntax: docker run [options-for-docker] <imagename> <command>.

    • Using docker run -it allows connecting to an interactive shell inside the container.

    • You can configure services inside the container, such as mapping a port on the host machine to a port inside the container using the -p option, for example: -p 8889:8888.

  4. View and Stop: Running containers can be viewed using the docker ps command. To stop a running container, you can use the docker stop <container-id> command or press Ctrl+C if it was run interactively.

2. Creating Custom Images

Researchers often need to create customized environments. This is achieved by writing a Dockerfile and building a new image.

  1. Define the Environment (Dockerfile): A Dockerfile is a text file that contains instructions detailing how to assemble the image.

    • A Dockerfile must begin with the FROM instruction, which specifies the base image (the foundation of the environment).

    • Instructions like RUN are used to execute commands (e.g., installing packages or compiling code) to create a new layer on top of the base image.

    • Instructions like COPY or ADD are used to copy files or directories from the local machine (the build context) into the image filesystem.

  2. Build the Image: Use the docker build command, typically with the -t option to assign a name and tag to the resulting image.

    • Example: $ docker build -t my-jupyter-image ..

  3. Share the Image: After building, the custom image can be shared by pushing it to a repository like Docker Hub using the docker push command.

3. Managing Data and Persistence

By default, the container has its own isolated filesystem, and any files written directly into the container are tied to that instance (meaning they are lost when the container is deleted). To work with external data or save results persistently, you must connect the container to the host filesystem.

Build your own container

The basic steps in building a Docker container involve creating a Dockerfile to define the environment, running the Docker build command to generate a Docker image from that file, and then running the image to create a live Docker container.

Here is a breakdown of the steps for building and using a custom Docker container:

1. Defining the Environment with a Dockerfile

The core of building a custom container is defining its environment using a text file called a Dockerfile. The Dockerfile contains instructions that detail how to assemble the image.

2. Building the Docker Image

Once the Dockerfile is ready, you use the Docker Engine to build the image.

3. Running the Image as a Container

The custom image can then be launched as a live container.

4. Sharing the Built Image

After building the image, you can share it by pushing it to a registry like Docker Hub.

Dockerhub - Sharing Containers

Docker Hub is a crucial component of the Docker ecosystem, serving as a central repository for container images.

Key facts about Docker Hub:

Apptainer - using containers on Compute Canada and HPC

Your familiarity with Docker provides an excellent starting point for using Apptainer (formerly Singularity) on a High-Performance Computing (HPC) system, as Apptainer is specifically the container solution used in environments where Docker is often unavailable or prohibited due to security concerns.

The transition involves understanding that while you typically build your environment using Docker locally, you must run it using Apptainer on the shared HPC resource.

Here is a step-by-step guide detailing how to get started with Apptainer, drawing parallels to Docker concepts where applicable:

1. Initial Setup and Access

Before running any commands, you generally need to load the Apptainer software module on the HPC cluster:

2. Image Acquisition: Converting Docker Images to Apptainer Files (SIF)

On HPC systems, you generally cannot run Docker directly, but Apptainer can easily convert images from Docker Hub into its native format, the Singularity Image File (SIF), which is a compressed, read-only file.

Docker Command/ActionApptainer EquivalentDescription
Pulling an Image (docker pull)Building an Image (apptainer build)You use the apptainer build command to pull the Docker layers from Docker Hub (or another OCI registry) and assemble them into a local SIF file.
Example:$ apptainer build bb.sif docker://busyboxThis command pulls the busybox image layers from Docker Hub and saves the resulting container image as a local SIF file named bb.sif.
Building from a Dockerfile (Locally)Using the Dockerfile URI (Off-Cluster)If you only have a Dockerfile, you must generally build the Docker image on a system where you have appropriate privileges (like your local machine), save it as a tarball, and then convert that tarball to a SIF file. Note that building images that require root/sudo access usually will not work on compute clusters.

3. Running the Container

Once you have a SIF file (e.g., myimage.sif), you use Apptainer commands instead of docker run.

Docker Goal/CommandApptainer CommandDescription
Run a command in the container (docker run)apptainer runRuns the container using the defined runscript. We suggest you always use apptainer run.
Execute a specific command (docker run <image> <command>)apptainer execExecutes a command inside the container without running the defined runscript.
Connect to an interactive shell (docker run -it)apptainer shellAllows you to run commands interactively while remaining inside the container, typically resulting in an Apptainer> prompt.

4. Handling Files and Persistent Data (Bind Mounts)

In Docker, you use the -v or --mount option to expose directories on the host to the container filesystem. Apptainer uses the -B or --bind option for bind mounts.

5. Essential Command Line Options for HPC Systems

When running Apptainer on a shared cluster, you need to add specific flags, usually following the run, shell, or exec command, to ensure security and resource management:

Summary of Workflow Translation

Docker ConceptApptainer Approach (HPC)Typical Command Component
Build (Dockerfile)Build/Convert to SIF (locally or on head node)apptainer build <name>.sif docker://<image>
Run (Command)Run or Executeapptainer run/exec
Bind Mount (-v)Bind Mount-B /host/path:/cont/path
Interactive (-it)Shellapptainer shell
Security/IsolationContainment-C or -e
Temp FilesDedicated Work Directory-W ${SLURM\_TMPDIR}

References