2. Container

2.1. Introdução

A Open Container Initiative (OCI) é uma estrutura de governança aberta com o propósito expresso de criar padrões abertos da indústria em torno de formatos e runtimes de contêineres. A maioria dos containers são compatíveis com o padrão OCI.

O Docker é o sistema de gerenciamento de containers mais utilizado. Entretanto, algumas mudanças na empresa Docker Inc gerou alguns problemas na comunidade. O Kubernetes descontinuou o Docker e passou a usar o Container Runtime Interface (CRI). As imagens produzidas pelo Docker continuam funcionando sem problemas, pois fazem parte do OCI. Esse também foi um dos motivos que fez com que a RedHat criasse o Podman.

Em relação a ambientes de HPC com multi-nó, o padrão adotado é o singularity, também chamado de apptainer (nome do projeto do singularity na Linux Foundation). O apptainer também é compatível com o padrão do OCI. Existem diversos motivos para o uso do apptainer ao invés do docker em ambientes de HPC, porém, isto não será tratado aqui.

O apptainer permite a importação dos containers diretamente do Docker Hub ou de outros repositórios.

2.2. Baixando imagens

2.2.1. Docker Hub

Usando as imagens oriundas do Docker Hub. Por exemplo, baixando um container Alpine.

[user1@sismom-1 containers]$ apptainer pull docker://alpine:latest
INFO:    Converting OCI blobs to SIF format
INFO:    Starting build...
INFO:    Fetching OCI image...
3.7MiB / 3.7MiB [=================================================================] 100 %0s
INFO:    Extracting OCI image...
INFO:    Inserting Apptainer configuration...
INFO:    Creating SIF file...
[=================================================================================] 100 % 0s
[user1@sismom-1 containers]$ ls
alpine_latest.sif

2.2.2. NVIDIA NGC

Se for utilizar o pytorch, tensorflow recomenda-se utilizar as imagens otimizadas da própria NVIDIA, através do link NGC. Se for outra aplicação também recomenda-se a consulta no NGC para ver se já existe um container dela. Por exemplo, baixando uma versão do pytorch diferente da disponível no cluster, diretório /sw/containers.

[user1@sismom-1 containers]$ apptainer pull docker://nvcr.io/nvidia/pytorch:25.11-py3
INFO:    Converting OCI blobs to SIF format
INFO:    Starting build...
INFO:    Fetching OCI image...
...
INFO:    Creating SIF file...

[user1@sismom-1 containers]$ ls -lh
total 8.3G
-rwxrwxr-x 1 user1 group1 8.2G Oct  8 11:31 pytorch_25.11-py3.sif
-rwxrwxr-x 1 user1 group1 3.7M Oct  8 10:57 alpine_latest.sif

Importante

Os containers mais comuns estão disponiveis no diretório /sw/containers no cluster Sismom.

Atenção

Repare que os containers possuem tamanhos de dezenas a milhares de MB. Se for trabalhar em equipe, recomenda-se o uso compartilhado, a fim de minimizar o consumo de espaço em disco. Por favor, evite de ter várias cópias do mesmo container.

Sugestão: crie um diretório compartilhado e coloque todos os containers nele. Por exemplo, criar um diretório para o projeto1 no diretório /sw/containers/projeto1 onde o grupo tenha permissão de leitura e escrita no diretório em questão.

2.3. Executando o container

2.3.1. Sessão iterativa

Segue uma breve descrição dos comandos abaixo.

  • aloca 1 nó de processamento e 1 GPU

  • identifica a versão do sistema operacional (S.O.) do nó sismom-1

  • executa o container no modo SHELL

  • identifica a versão do S.O. do container que é diferente do S.O. do nó

  • mostra os filesystems que estão montados no container

[user1@sismom-1 containers]$ salloc
salloc: Granted job allocation 5
salloc: Nodes sismom-1 are ready for job

[user1@sismom-1 containers]$ grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Ubuntu 24.04.3 LTS"

[user1@sismom-1 containers]$ apptainer shell alpine_latest.sif
Apptainer> grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Alpine Linux v3.23"
Apptainer> df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  64.0M     16.0K     64.0M   0% /
udev                     62.7G         0     62.7G   0% /dev
tmpfs                    62.8G         0     62.8G   0% /dev/shm
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /etc/localtime
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /etc/hosts
efivarfs                495.9K    185.9K    305.0K  38% /sys/firmware/efi/efivars
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /home/users/user1
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /tmp
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /var/tmp
tmpfs                    64.0M     16.0K     64.0M   0% /etc/resolv.conf
tmpfs                    64.0M     16.0K     64.0M   0% /etc/passwd
tmpfs                    64.0M     16.0K     64.0M   0% /etc/group
Apptainer> exit
exit
[user1@sismom-1 containers]$

Nota

Observe que a área de usuário $HOME é montada, por padrão, dentro do container. Caso necessário, as demais áreas deverão ser montadas através do parâmetro -B <diretório externo>:<diretório interno> ou --bind <diretório externo>:<diretório interno> do comando apptainer.

[user1@sismom-1 containers]$ apptainer shell -B /data1:/mnt alpine_latest.sif
Apptainer> df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  64.0M     16.0K     64.0M   0% /
udev                     62.7G         0     62.7G   0% /dev
tmpfs                    62.8G         0     62.8G   0% /dev/shm
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /etc/localtime
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /etc/hosts
efivarfs                495.9K    185.9K    305.0K  38% /sys/firmware/efi/efivars
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /home/users/users1
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /tmp
/dev/mapper/ubuntu--vg-ubuntu--lv
                        97.9G     90.0G      2.9G  97% /var/tmp
tmpfs                    64.0M     16.0K     64.0M   0% /etc/resolv.conf
tmpfs                    64.0M     16.0K     64.0M   0% /etc/passwd
tmpfs                    64.0M     16.0K     64.0M   0% /etc/group
/dev/mapper/mpatha-part3
                         90.7T      1.7T     89.0T   2% /mnt
Apptainer> exit
exit
[user1@sismom-1 containers]$

2.3.2. Sessão iterativa com GPU

Nestes comandos é chamado o Pytorch dentro do container e verifica a quantidade de GPUs que o container identificou.

[user1@sismom-1 containers]$ salloc -N1 --gpus=1
salloc: Granted job allocation 4475
salloc: Nodes gpu01 are ready for job

[user1@gpu01 containers]$ apptainer shell --nv pytorch_25.11-py3.sif
Apptainer> python
Python 3.12.3 (main, Aug 14 2025, 17:47:21) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> torch.cuda.device_count()
1
>>>

2.3.3. Executando o container

Para executar um container deve usar o comando apptainer run ou apptainer exec.

[user1@sismom-1 containers]$ apptainer run pytorch_25.11-py3.sif
=============
== PyTorch ==
=============

NVIDIA Release 25.11 (build 231036167)
PyTorch Version 2.10.0a0+b558c98
Container image Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Copyright (c) 2014-2024 Facebook Inc.
All rights reserved.

Failed to detect NVIDIA driver version.

Apptainer>

Importante

Repare na mensagem de erro Failed to detect NVIDIA driver version na execução do container. Isso se deve porque o suporte a qualquer GPU é desabilitado por padrão. Para habilitar basta acrescentar o parâmetro --nv, para GPUs da NVIDIA, como mostrado abaixo.

[user1@sismom-1 containers]$ apptainer run --nv pytorch_25.11-py3.sif
=============
== PyTorch ==
=============

NVIDIA Release 25.11 (build 231036167)
PyTorch Version 2.10.0a0+b558c98
Container image Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
All rights reserved.

Apptainer> python
Python 3.12.3 (main, Aug 14 2025, 17:47:21) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> torch.cuda.is_available()
True
>>> torch.cuda.device_count()
8
>>> exit()
Apptainer>

2.4. Criando uma nova imagem

A fim de ilustrar a criação de uma nova imagem, será usada como base a imagem docker://python:alpine. Essa imagem não tem instalada o pacote numpy. Pode-se observar que dá erro ao tentar executar o script python que utiliza o numpy.

[user1@sismom-1 containers]$ apptainer run python_alpine3.19.sif python numpy-test.py
Traceback (most recent call last):
File "/home/users/user1/userguide/numpy-test.py", line 3, in <module>
    import numpy as np
ModuleNotFoundError: No module named 'numpy'

Semelhante ao Dockerfile do gerenciador Docker, o apptainer usa um arquivo definition com as informações dos comandos necessários para instalar todas as dependências necessárias. Por exemplo, foi criado um arquivo numpy.def com o seguinte conteúdo.

# image
Bootstrap: docker
From: python:alpine

%post
# upgrading pip
pip install --upgrade --no-cache-dir pip setuptools

# installing new packages
pip install --no-cache-dir numpy

O cabeçalho define o formato Docker e a imagem From: python:alpine e depois o trecho %post define os comandos que serão executados para instalação dos pacotes, bibliotecas, etc.

Nota

Os comandos do arquivo definition irão variar com base no sistema operacional da imagem utilizada, por exemplo: Ubuntu, Rocky Linux, Red Hat Universal Base Image (ubi), etc.

  • Criando uma nova imagem chamada numpy.sif

[user1@sismom-1 containers]$ apptainer build numpy.sif numpy.def
INFO:    Starting build...
...
Writing manifest to image destination
...
INFO:    Running post scriptlet
+ pip install --upgrade --no-cache-dir pip setuptools
...
+ pip install --no-cache-dir numpy
...
INFO:    Creating SIF file...
INFO:    Build complete: numpy.sif

Executando o script python, que possui a dependência do numpy, sem nenhum erro.

[user1@sismom-1 containers]$ apptainer run numpy.sif python numpy-test.py
Maximo:  0.7051411895679115

Nota

No caso do container utilizar GPUs, recomenda-se o uso das imagem da NVIDIA NGC que já inclui todas as dependências, além de já estarem otimizadas.