Containers#

Containers are a light-weight virtualized environment you can use to create ‘clean’ user spaces. They are useful for creating reproducible system environments for software to run in.

Typical container technologies we use include:

  • Docker

  • Podman

  • Apptainer - previously Singularity

Docker is the most widely used technology, however some of its associated tooling - such as Docker Desktop has recently had licensing restrictions placed around commercial use. This has led to increased adoption of Podman which has less ambiguous open-source licensing. In the majority of cases Docker and Podman are fully interchangeable - with similar image formats and commands (swapping docker with podman).

Apptainer is a container technology with a security model that is more appealing for HPC and shared systems.

Working on Mac#

Given that most of us work on Mac (and increasing the Arm MX versions) it is important to note the containers typically rely on the presence of a Linux kernel underneath - since they use Linux kernel features to provide their user-space isolation.

Since Mac doesn’t have a Linux kernel it is necessary to run containers on top of a Linux Virtual Machine. Docker and Podman provide (relatively) seamless integration for this - on the QEMU virtual machine software.

podman#

podman is a container technology with many similarities to Docker, including using Dockerfiles and with many identical commands (just switching docker with podman).

Why it is used instead of Docker#

Some of the appealing reasons for using it are:

  • clean licensing in commercial settings, Docker’s recent licensing can make using it infeasible for some.

  • easy installation with system package managers (e.g. apt install podman).

  • some nice integrations with e.g. systemd, which for some applications can make life a bit easier than Docker.

Some downsides are:

  • less broad integration with other tools

  • the need for consumers to use a potentially unfamiliar container tool.

Getting it#

Debian-like:#

sudo apt-get install podman

RHEL-like#

sudo dnf install podman

Mac:#

With Homebrew:

brew install podman

Setting it up#

Linux#

For the simple case of building and running a container from an image just switch your docker xyz command with podman xyz.

Mac Silicon#

The containers will run in a podman virtual machine. This needs some setup, and for building a bigger (e.g. C++ based) project the defaults will likely need to be changed before calling start on the machine.

Override default CPU and Memory allocation#

You can initialize the VM with specified number of CPUs and amount of memory. The defaults are low, so you will likely need to override them, so something like:

podman machine init --cpus 4 --memory 4096 -v $HOME:$HOME

The last command mounts your home directory for use in the machine, this is needed to allow mounting into individual containers later. You may need more mount points if mounting things outside of $HOME in containers, machine creation time is the time to do it!

Start the machine#

Now you can start the virtual machine:

podman machine start

You will need to do this on each system boot unless you explicitly schedule it.

Useful commands#

List all containers:

podman ps

Stop and remove all containers

podman stop --all
podman rmi --all -f

Build an image: sh

podman build -t $IMAGE_NAME .

Run an image in a container with some exposed ports, a local mount and systemd:

podman run -it -p 8000:8000 -p 8500:8500 --systemd=always -v $HOST_DIR:$CONTAINER_DIR $IMAGE_NAME

Join a running container:

podman exec -it $CONTAINER_ID /bin/bash

Apptainer#

Apptainer (previously Singularity) is a container technology similar to Docker. It has seen relatively large uptake in the HPC area due to greater security focus and controls.

In most cases you can use Apptainer as a drop-in Docker replacement, however they use a different binary image format, so you will need to rebuild (from Dockerfile) or convert any existing images.

Converting images#

You can pull an image into the directory you are in:

apptainer pull docker://nvcr.io/nvidia/pytorch:21.12-py3

This will download and cache the image, then it will convert it layer-by-layer to a SIF format.

Running with GPUs#

To run with GPUs enabled do:

apptainer run --nv docker://nvcr.io/nvidia/pytorch:21.12-py3

Or once downloaded:

apptainer run --nv FILE_NAME.sif

Repositories#

You may need to store your container images somewhere, to share with colleagues or as part of some automation.

ICHEC uses Harbor as its recommended container repository. We have an instance running on the internal network, it is accessible only when on the network in the Galway or Dublin offices.

DockerHub is a popular public repository. Harbor is preferred for anything private or running on ICHEC systems but DockerHub might be useful for more informal hosting or sharing needs.

Harbor#

Contact the Systems Team to get set up on this service and to get access keys.

DockerHub#

You can sign up for a personal account.

VERY IMPORTANT: DockerHub will host things pubically by default, including the Dockerfile - make absolutely sure neither the image nor the Dockerfile have sensitive materials, particularly credentials, in them. Remember that our internal Harbor should be preferred where you are able to use it.

You can login to the repo on your CLI with:

podman login -u $MY_USER

You will be prompted for a password - you can generate a personal access token in the DockerHub web UI for this purpose. You will need to store it somewhere safe after.

You can push an image to the hub (remember it will be public) with:

podman push local_image_name docker://docker.io/myuser/myrepo/myimage:1.0.0

Container Orchestration#

Compose Specification#

The Compose Speficiation can be used for defining web application in a cloud and platform-agnostic way. It is implemented in tools like docker-compose and podman-compose. You can use these tools to specify how your application should be launched in a container and interact with dependent services.

The Compose Speficiation can be used for defining web application in a cloud and platform-agnostic way. It is implemented in tools like docker-compose and podman-compose. You can use these tools to specify how your application should be launched in a container and interact with dependent services.

Podman Compose#

Podman Compose is a lightweight script that has some of the functionality of Docker Compose.

You can use it by creating a compose.yaml file somewhere near the top level of your application. It will look something like:

version: '3.8'

services:
  my_app:
    build:
        context: .
    volumes:
      - ./cache/:/cache
      - ./config/:/config
    ports:
      - 8080:8080
      - 8090:8090

Where context is pointing to a directory containing a Composefile (i.e. Dockerfile). Here we are exposing two ports and some volume mounts (both are just as an example).

You can then build and start your services (in this case just one) with:

podman-compose  -f compose.yaml up -d

and bring them down when finished with:

podman-compose -f compose.yaml down -v

Further Reading#

  • containers GitHub - A repo with many useful container tools, several are Red Hat projects.