Apptainer-kontit
Tässä osiossa annetaan ohjeet konttien rakentamiseen ja ajamiseen Apptainerilla CSC:n supertietokoneilla. Vaikka keskitymme CSC-kohtaiseen käyttöön ja parhaisiin käytäntöihin, virallinen Apptainer-dokumentaatio toimii kattavana yleiskäytön viitteenä. Käytännönläheisiä ohjeita varten katso osio Esimerkit, joka sisältää CSC-järjestelmiin räätälöityjä konkreettisia esimerkkejä.
Huomaa, että Apptainer tunnettiin aiemmin nimellä Singularity, ja vanha nimi voi edelleen tulla vastaan ohjelmiston sisäisissä osissa ja vanhassa dokumentaatiossa. Projektin nimi muutettiin, kun se siirtyi Sylabsilta Linux Foundationille, mutta ydintoiminnallisuus pysyi samana. Sylabs ylläpitää projektista haarautettua versiota nimeltä SingularityCE.
Taustaa
Apptainer-konttikuva on yksi pakattu tiedosto, joka sisältää kaiken sovelluksen ajamiseen tarvittavan.
Tämä muuttumaton tiedosto sisältää täydellisen juuritiedostojärjestelmän, mukaan lukien kaikki sovellukset, kirjastot ja riippuvuudet, sekä metadataa, kuten ympäristömuuttujia ja ajonaikaisia asetuksia.
Apptainer käyttää kuvilleen Singularity Image Format (SIF) -muotoa, jonka tunnistaa .sif-tiedostopäätteestä.
Apptainer-konttien avulla voit valita peruskuvaksi minkä tahansa Linux-jakelun, kuten Ubuntun, Rocky Linuxin tai OpenSUSEn, ja hyödyntää sen omaa paketinhallintaa ohjelmistojen asentamiseen kyseiseen ympäristöön. Konttien rakentamiseen CSC:n supertietokoneilla liittyy kuitenkin tiettyjä rajoituksia, erityisesti silloin, kun valittu peruskuva poikkeaa isäntäjärjestelmän Linux-jakelusta. Näitä ongelmia ja niiden ratkaisuja käsitellään tarkemmin myöhemmin.
Ohjelmiston ajaminen Apptainer-kontista voi merkittävästi parantaa käynnistysaikoja ja vähentää I/O-pullonkauloja Lustre rinnakkaistiedostojärjestelmässä. Tämä on erityisen hyödyllistä sovelluksille, jotka sisältävät paljon tiedostoja tai lataavat käynnistyksen aikana suuren määrän jaettuja kirjastoja. Esimerkiksi Python-ympäristöt ovat tunnettuja tästä ongelmasta laajojen moduuliriippuvuuksiensa ja dynaamisen latauskäyttäytymisensä vuoksi.
Apptainer-kontit varmistavat toistettavan ajon, koska niiden kuvat ovat muuttumattomia. Kun konttikuva on kerran rakennettu, se pysyy muuttumattomana, mikä takaa yhdenmukaisen toiminnan eri järjestelmissä ja ajan kuluessa. Lisäksi Apptainerin build-määrittelyt dokumentoivat tarkasti vaiheet, paketit ja asetukset, joilla kontti on luotu, mikä tekee koko rakennusprosessista läpinäkyvän ja toistettavan.
Konttikuvilla on yksi tärkeä rajoitus: ne eivät ole yhdisteltäviä. Toisin kuin perinteisissä paketinhallintajärjestelmissä, joissa ohjelmistoja voidaan lisätä järjestelmään vaiheittain, olemassa olevia kontteja ei voi yksinkertaisesti yhdistää uuden luomiseksi. Esimerkiksi se, että sinulla on yksi kontti Pythonille ja toinen R:lle, ei anna pääsyä molempiin ympäristöihin samanaikaisesti. Jos haluat käyttää molempia työkaluja yhdessä, sinun on luotava uusi konttikuva, joka sisältää sekä Python- että R-asennukset alusta alkaen.
Konttien ajaminen
Apptainerin käyttäminen suoraan
Oletetaan, että meillä on konttikuva nimeltä container.sif.
Voimme suorittaa mielivaltaisen komennon (korvaa mycommand) kontin sisällä komennolla apptainer exec seuraavasti:
Voimme tuoda isäntäjärjestelmän hakemistoja kontin sisälle bind mounttien avulla. Roihussa voimme liittää eri levyalueet konttiin käsin seuraavasti:
apptainer exec --bind="/users,/projappl,/scratch,/dataset,$TMPDIR,$LOCAL_SCRATCH" container.sif mycommand
Käytön helpottamiseksi voimme käyttää komentoa csc-common-bind, joka tulostaa yleisten levyalueiden listan, jolloin niitä ei tarvitse kirjoittaa itse:
Roihu-GPU:ssa voimme lisätä Nvidia GPU -tuen --nv-valitsimella seuraavasti:
Voimme käyttää samoja valitsimia myös komentojen apptainer run ja apptainer shell kanssa.
Konttikuvien rakentaminen
Tässä osiossa selitetään, miten Apptainerilla muunnetaan olemassa olevia Docker- ja OCI-kuvia SIF-kuviksi, miten uusia SIF-kuvia rakennetaan määrittelytiedostoista ja miten kontteja voidaan kehittää interaktiivisesti muokattavana sandboxina eli (ch)root-hakemistona. Lisäksi käsittelemme, miten rakennusympäristö määritetään Roihussa: missä rakennetaan ja mitä väliaikais-, välimuisti- ja bind mount -hakemistoja käytetään.
Linux-jakelun valitseminen peruskuvaksi
Kun valitset kontillesi peruskuvaa, voit valita useista Linux-jakeluista, joilla kullakin on oma paketinhallintansa. Red Hat Enterprise Linux (RHEL) -pohjaisissa jakeluissa, jotka käyttävät DNF-paketinhallintaa, suosittuja vaihtoehtoja ovat RedHat Universal Base Images (UBI), joita on saatavilla kuvina redhat/ubi8 ja redhat/ubi9, sekä yhteisövetoiset vaihtoehdot kuten rockylinux ja almalinux. Jos suosit SUSE-pohjaisia järjestelmiä, joissa käytetään Zypper-paketinhallintaa, opensuse/leap tarjoaa vakaan perustan. Debian-pohjaisissa jakeluissa, joissa käytetään APT-paketinhallintaa, sekä debian että ubuntu tarjoavat hyvin ylläpidettyjä peruskuvia laajoilla pakettivarastoilla.
Vaikka Apptainer sallii konttien rakentamisen käyttäen mitä tahansa Linux-jakelua peruskuvana, rakentamiseen CSC:n supertietokoneilla liittyy joitakin rajoituksia, koska käytössä on Apptainerin fakeroot-tila ilman unprivileged user namespaceja.
Tässä ympäristössä tietyt etuoikeutetut komennot, joita suoritetaan tavallisesti pakettien asennuksen aikana, epäonnistuvat.
Esimerkiksi paketinhallinnat suorittavat usein etuoikeutettuja komentoja, kuten useradd ja groupadd, osana asennusskriptejään, ja nämä epäonnistuvat fakeroot-ympäristössä.
Käyttämällä peruskuvaa samasta perheestä kuin isäntäjärjestelmä vähennämme fakeroot-tilan käytöstä konttien rakentamisessa aiheutuvien ongelmien määrää. Jos käytät peruskuvaa, joka ei ole samasta perheestä kuin isäntäjärjestelmä, on odotettavissa, että useampia paketteja ei voida asentaa onnistuneesti. Paras tapa selvittää tämä on yrittää rakentaa kontti.
Voit tunnistaa isäntäjärjestelmäsi Linux-jakelun seuraavasti:
NAME="Red Hat Enterprise Linux"
VERSION="9.8 (Plow)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="9.8"
...
Vaikka peruskuva vastaisi isäntäjärjestelmää, jotkin pakettien asennusskriptit kutsuvat silti yllä mainittuja etuoikeutettuja komentoja. Voimme käyttää tähän väliaikaista ratkaisua korvaamalla ongelmalliset komennot valeversioilla, jotka onnistuvat aina:
Tämä lähestymistapa mahdollistaa pakettien asennuksen onnistumisen ohittamalla käyttöoikeuksiin liittyvät virheet.
Ohjelmistojen asentaminen konttiin
Tyypillinen tapa asentaa ohjelmistoja konttiin on aloittaa käyttämällä järjestelmän paketinhallintaa, kuten DNF:ää, APT:tä tai Zypperiä, "järjestelmätason" ohjelmistojen asentamiseen hakemistoon /usr, ja asentaa sen jälkeen ohjelmistoja käyttäjätilan paketinhallinnalla, kuten Pipillä, Condalla tai Spackilla, tai asentaa ohjelmistoja käsin hakemistoon /usr/local tai yksilölliseen hakemistoon polun /opt alle.
Rakennuspaikka
Roihussa voimme rakentaa kontteja kirjautumissolmuilla ja laskentasolmuilla. Huomaa, että Roihu-CPU:lla ja Roihu-GPU:lla on eri prosessoriarkkitehtuurit, joten rakenna kontti samalla puolella, jolla aiot sitä ajaa. Rakentaaksemme laskentasolmulla voimme varata interaktiivisen Slurm-työn seuraavasti:
Väliaikaishakemisto
Ympäristömuuttujan TMPDIR on osoitettava paikalliselle levylle.
Apptainer käyttää sitä tunnistaakseen hakemiston väliaikaishakemistokseen konttia rakennettaessa.
Roihu asettaa ympäristömuuttujan TMPDIR automaattisesti kirjautumissolmuilla ja kaikissa töissä.
Paikallista levyä ei tarvitse varata erikseen, eikä se kuluta laskutusyksiköitä (BUs).
Saatavilla oleva kapasiteetti riippuu solmusta: 80 GB kirjautumissolmuilla ja töissä 20 GiB:stä useisiin teratavuihin allokaatiotyypistä riippuen.
Katso tarkat määrät kohdasta Roihun levyalueet.
Lustren rinnakkaistiedostojärjestelmää ei voi (eikä pidä) käyttää väliaikaishakemistona.
Välimuistihakemisto
Apptainer tallentaa välimuistihakemistoon kerroksia ja blob-objekteja, kuten peruskuvia.
Oletussijainti on kotihakemistossa ($HOME/.apptainer), jossa Roihussa on 15 GiB:n kiintiö, jonka yksikin peruskuva voi jo ylittää.
Siksi suosittelemme vaihtamaan välimuistin sijainnin scratch-alueelle (korvaa <project> omalla projektillasi):
Scratch-alueella oleva välimuisti säilyy istuntojen välillä, joten toistuvat rakennukset voivat hyödyntää jo ladattuja kerroksia uudelleen.
Vastapainona Lustre on hitaampi kuin paikallinen levy, ja välimuisti lasketaan mukaan scratch-alueen 250 GiB:n kiintiöön.
Jos tarvitset välimuistia vain yhtä rakennusta varten, aseta sen sijaan APPTAINER_CACHEDIR=$TMPDIR, jolloin se katoaa istunnon päättyessä.
Voimme myös tarvittaessa tyhjentää välimuistihakemiston:
Väliaikaishakemiston bind mounttaus
Oletuksena Apptainer bind mounttaa isäntäjärjestelmän /tmp-hakemiston rakennusympäristön /tmp-hakemistoksi.
Roihussa /tmp:n koko on kuitenkin rajallinen, joten bind mounttaamme paikallisen levyn ($TMPDIR) hakemistoon /tmp, jotta levytila ei lopu kesken, seuraavasti: --bind="$TMPDIR:/tmp".
SIF-kuvan rakentaminen olemassa olevasta Docker- tai OCI-kuvasta
Voimme hakea olemassa olevia konttikuvia konttirekisteristä pullaamalla ne. Apptainer muuntaa ne Docker- tai OCI-muodosta Singularity Image Format (SIF) -muotoon.
SIF-kuvan rakentaminen määrittelytiedostosta
Apptainerin määrittelytiedostot käyttävät tiedostopäätettä .def.
Tässä on yksinkertainen esimerkki kontin määrittelystä:
Bootstrap: docker
From: docker.io/rockylinux/rockylinux:9.8
%post
# Replace the failing commands with always succeeding dummies.
cp /usr/bin/true /usr/sbin/useradd
cp /usr/bin/true /usr/sbin/groupadd
# Continue to install software into the container normally.
dnf -y update # would fail without the dummies
Voimme kutsua Apptaineria rakentamaan kontin (container.sif) määrittelytiedostosta (container.def) käyttäen fakerootia seuraavasti:
Katso lisää esimerkkejä Apptainerin määrittelytiedostoista osiosta Esimerkit.
Kehittäminen interaktiivisella sandboxilla
Voimme myös rakentaa Apptainer-sandboxeja fakerootilla.
Sandboxit ovat hyödyllisiä konttien interaktiiviseen kehittämiseen.
Sandbox on luotava paikalliselle levylle ($TMPDIR), ei Lustren rinnakkaistiedostojärjestelmään.
Voimme alustaa sandboxin peruskuvasta seuraavasti:
apptainer build --fakeroot --sandbox "$TMPDIR/rockylinux" docker://docker.io/rockylinux/rockylinux:9.8
Sen jälkeen voimme käynnistää shellin sandboxissa ja asentaa siihen ohjelmistoja:
apptainer shell --fakeroot --writable --contain --cleanenv --bind="$TMPDIR:/tmp" "$TMPDIR/rockylinux"
Voimme käyttää samoja keinoja epäonnistuvien komentojen korvaamiseen sandboxissa:
Nyt voimme asentaa ohjelmistoja normaalisti:
Roihun peruskuvat
CSC tarjoaa erilliset peruskuvat sekä Roihu-CPU:lle että Roihu-GPU:lle. Nämä peruskuvat on rakennettu Rocky Linux 9 -kuvien päälle. Jokainen kuva sisältää yhden Spackilla rakennetun ohjelmistopinon sekä sen riippuvuudet ja modulefile-tiedostot ympäristön aktivointia varten. Ohjelmistoversiot vastaavat järjestelmäohjelmiston versioita.
Peruskuvien avulla voit rakentaa kontteja, joiden ohjelmistopino on identtinen alustan kanssa, kuten optimoituja MPI-kontteja. Tuloksena syntyvät konttikuvat ovat omavaraisia eivätkä vaadi binäärien bind mounttausta ajon aikana. Nämä kontit eivät kuitenkaan ole siirrettäviä muihin koneisiin. Konttikuvat ovat saatavilla OCI-muodossa Satamassa, joka on CSC:n konttikuvarekisteri.
Roihu-CPU-solmut käyttävät x86_64-suorittimia, kun taas Roihu-GPU-solmut käyttävät Arm-pohjaisia (aarch64) Nvidia Grace -suorittimia.
CPU-peruskuvat on siksi rakennettu x86_64:lle ja GPU-peruskuvat aarch64:lle, eikä toiselle puolelle rakennettu kontti toimi toisella.
Rakenna konttisi sillä kirjautumissolmulla, joka vastaa niitä solmuja, joilla aiot ajaa, eli roihu-cpu.csc.fi tai roihu-gpu.csc.fi.
Samasta syystä konttirekisteristä haettu peruskuva toimii vain, jos siitä on tarjolla rakennus käyttämällesi arkkitehtuurille.
Roihu-CPU:n peruskuvat ovat seuraavat:
satama.csc.fi/r_installation_spack/core-cpu-gcc-15.2.0:v2026_03(4.54 GB)
Roihu-GPU:n peruskuvat ovat seuraavat:
satama.csc.fi/r_installation_spack/core-gpu-gcc-15.2.0-cuda-13.1.1:v2026_03(13.7 GB)satama.csc.fi/r_installation_spack/core-gpu-gcc-14.3.0-cuda-12.9.1:v2026_03(15.9 GB)satama.csc.fi/r_installation_spack/core-gpu-gcc-13.4.0-cuda-12.6.3:v2026_03(13.5 GB)
Käytännön käyttöä varten katso esimerkit Roihu-CPU-peruskontin rakentamisesta ja ajamisesta OSU-mikrotesteillä sekä Roihu-GPU-peruskontin rakentamisesta ja ajamisesta NCCL-testeillä.
Koneoppimiseen tarkoitetut peruskuvat Roihu-GPU:lle
Yllä kuvattujen yleisten peruskuvien lisäksi, joiden tavoitteena on toistaa Roihun ympäristö mahdollisimman tarkasti, on olemassa myös vaihtoehtoinen joukko peruskuvia, jotka perustuvat Rocky Linux 9:ään ja joihin Python 3, MPI ja CUDA on asennettu tavallisilla Rocky Linuxin RPM-paketeilla Spackin sijaan. Tämä lähestymistapa tuottaa kontin, joka ei ole identtinen Roihun isäntäjärjestelmän kanssa, mutta jota voi joissakin tapauksissa olla helpompi laajentaa kuin yleisiä kontteja. Huomaa, että nämä kuvat ovat vain Roihu-GPU:lle.
Kuvat on luotu erityisesti yleisesti käytettyjen koneoppimiskehysten tarpeet huomioiden. Erityisesti CSC:n asennukset PyTorchista, TensorFlow’sta, JAXista ja vLLM:stä on tehty näitä kuvia käyttäen.
Ensin on joukko ml-base-kuvia, joita käytetään perustana
kaikille muille kuville. Ne sisältävät Python 3:n, MPI:n ja CUDAn
Roihu-GPU:n kanssa yhteensopivassa kokoonpanossa.
Esimerkiksi:
satama.csc.fi/r_installation_aida/ml-base:rocky9.7_gcc12_py3.12_cuda12.9- käyttää CUDA 12.9:ääsatama.csc.fi/r_installation_aida/ml-base:rocky9.7_gcc12_py3.12_cuda13- käyttää CUDA 13.0:aa
PyTorchilla on kahdenlaisia kuvia: pytorch-base ja pytorch.
pytorch-base-kuvassa on perusasennus PyTorchista sekä suuri joukko
olennaisia paketteja asennettuna Python Package Indexin
(PyPI) kautta, mukaan lukien Accelerate, Dask, JupyterLab,
Pandas, Scikit-learn ja Transformers. pytorch-kuva lisää mukaan
monimutkaisempia asennuksia, kuten xFormersin, OpenCV:n, ffcv:n, PyTorch
Geometricin, DeepSpeedin, FAISSin, Flash Attentionin ja Transformer
Enginen. pytorch-kuva on se, jota käytetään CSC:n PyTorch-asennuksessa,
kun taas pytorch-base voi olla hyödyllinen kevyempänä peruskuvana
omia asennuksia varten.
satama.csc.fi/r_installation_aida/pytorch-base:2.13_cuda13_roihusatama.csc.fi/r_installation_aida/pytorch:2.13_cuda13_roihu
Lopuksi myös TensorFlow-, JAX- ja vLLM-asennuksilla on vastaavat kontit Satamassa:
satama.csc.fi/r_installation_aida/tensorflow:2.21_cuda12.9_roihusatama.csc.fi/r_installation_aida/jax:0.10_cuda13_roihusatama.csc.fi/r_installation_aida/vllm:0.29.0_cuda13_roihu
Kaikki kuvat löytyvät Sataman r_installation_aida -repositoriosta. Kuvat
on rakennettu Podmanilla, ja kaikki niiden rakentamiseen käytetyt Podman-reseptit löytyvät
GitHubista.
Voit rakentaa omia kuvia näiden pohjalta samalla tavalla kuin minkä tahansa
muidenkin peruskuvien pohjalta; prosessi on kuvattu aiemmin tällä
sivulla. Esimerkki määrittelytiedostosta,
kun rakennetaan ml-base-kuvan päälle käyttäen CUDA 13.0:aa:
Bootstrap: docker
From: satama.csc.fi/r_installation_aida/ml-base:rocky9.7_gcc12_py3.12_cuda13
%post
# Build your application here with normal Linux commands, for example:
dnf install some_useful_rpm_package
pip install some_useful_python_package
Koneoppimisen oppaassamme on myös ohje ml-base-konttimme laajentamiseen sandboxin avulla.
Aineistojen lukeminen SquashFS-tiedostosta
Voimme myös välttää I/O-pullonkauloja aineistoissa, jotka koostuvat suuresta määrästä pieniä tiedostoja, kokoamalla ne yhdeksi SquashFS-tiedostoksi. SquashFS-tiedosto voidaan bind mountata kontin sisälle ja sitä voidaan käyttää vain luku -tilassa. Seuraava esimerkki purkaa aineiston paikalliselle levylle, luo aineistosta SquashFS-tiedoston ja siirtää sen sitten takaisin scratch-alueelle:
# Extract individual files to local drive
cd $TMPDIR
tar xf /scratch/<project>/mydataset.tar
# Create squashfs file
mksquashfs mydataset mydataset.sqfs -processors 4
# Move the resulting squashfs file back to the shared drive
mv mydataset.sqfs /scratch/<project>/
Nyt voimme bind mountata aineiston seuraavasti:
Data on saatavilla kontin sisällä polussa /data.
Konttikääreet
Tykky-konttikääre on saatavilla kontitettujen Pip- ja Conda-asennusten luomiseen kääreskriptien avulla. Jos Tykky on sinulle ennestään tuttu, voit jatkaa sen käyttöä, mutta suosittelemme konttien rakentamista ja ajamista suoraan, kuten edellisissä osioissa on selitetty.