Building OCI container images on Alps vClusters is supported through Podman, an open-source container engine that adheres to OCI standards and supports rootless containers by leveraging Linux user namespaces. Its command-line interface (CLI) closely mirrors Docker’s, providing a consistent and familiar experience for users of established container tools.
Preliminary step: configuring Podman's storage
The first step in order to use Podman on Alps is to create a valid Container Storage configuration file at $HOME/.config/containers/storage.conf
(or at $XDG_CONFIG_HOME/containers/storage.conf
if XDG_CONFIG_HOME
is set), according to the following minimal template:
[storage] driver = "overlay" runroot = "/dev/shm/$USER/runroot" graphroot = "/dev/shm/$USER/root" [storage.options.overlay] mount_program = "/usr/bin/fuse-overlayfs-1.13"
/dev/shm
is used to store the container images. /dev/shm
is the mount point of a tmpfs filesystem and is compatible with the user namespaces used by Podman. The limitation of this approach is that container images created during a job allocation are deleted when the job ends. Therefore, the image needs to either be pushed to a container registry or imported by the Container Engine before the job allocation finishes.Building images with Podman
It is strongly recommended to perform image builds with Podman on compute nodes, mainly for 2 reasons:
- the filesystem currently supported for building images (/dev/shm) is an in-memory shared resource on the node; therefore, building and storing images on login nodes reduces the overall amount of RAM available to other users on the node;
- the Slurm workload manager automatically cleans up /dev/shm after a job completes on a compute node; conversely, there is no automatic cleanup on login nodes
The easiest way to build a container image is to rely on a Containerfile (a more generic name for a container image recipe, but essentially equivalent to Dockerfile):
# Allocate a compute node and open an interactive terminal on it srun --pty --partition=<partition> bash # Change to the directory containing the Containerfile/Dockerfile and build the image podman build -t <image:tag> .
In general, podman build
follows the Docker options convention.
Importing images in the Container Engine
An image built using Podman can be easily imported as a squashfs archive in order to be used with our Container Engine solution.
/dev/shm
.To import the image:
enroot import -x mount -o <image_name.sqsh> podman://<image:tag>
The resulting <image_name.sqsh> can used directly as an explicitly pulled container image, as documented in Container Engine. An example Environment Definition File (EDF) using the imported image looks as follows:
image = "/<path to image directory>/<image_name.sqsh>" mounts = ["/capstor/scratch/cscs/<username>:/capstor/scratch/cscs/<username>"] workdir = "/capstor/scratch/cscs/<username>"
Pushing Images to a Container Registry
In order to push an image to a container registry, you first need to follow three steps:
- Use your credential to login to the container registry with
podman login
. - Tag the image according to the name of your container registry and the corresponding repository, using
podman tag
. This step can be skipped if you already provided the appropriate tag when building the image. - Push the image using
podman push
.
# Login to a container registry using username/password interactively podman login <registry_url> # Tag the image accordingly podman tag <image:tag> <registry url>/<image:tag> # Push the image (for docker type registries use the docker:// prefix) podman push docker://<registry url>/<image:tag>
For example, to push an image to the DockerHub container registry, the following steps have to be performed:
# Login to DockerHub (Podman will ask for your credentials) podman login docker.io # Tag the image based on your username podman tag <image:tag> docker.io/<username>/myimage:latest # Push the image to the repository of your choice podman push docker://docker.io/<username>/myimage:latest
Further reading
- Run images with Container Engine
- Containerized use case examples