Nächste: , Nach oben: Container   [Inhalt][Index]


4.1 Guix-Container

Der einfachste Einstieg ist, guix shell mit der Befehlszeilenoption --container aufzurufen. Siehe Aufruf von guix shell in Referenzhandbuch zu GNU Guix für eine Referenz der möglichen Optionen.

Folgende Befehle legen einen minimalen Shell-Prozess an, bei dem die meisten Namensräume vom übrigen System getrennt sind. Das aktuelle Arbeitsverzeichnis bleibt für den Prozess sichtbar, aber das restliche Dateisystem ist unzugänglich. Diese äußerste Isolation kann sehr hilfreich sein, wenn Sie jeglichen Einfluss durch Umgebungsvariable, global installierte Bibliotheken oder Konfigurationsdateien ausschließen möchten.

guix shell --container

Diese Umgebung ist kahl und leer. Sie haben in der brachen Umgebung nicht einmal die GNU coreutils und müssen zu ihrer Erkundung mit den in die Shell eingebauten Werkzeugen vorliebnehmen. Selbst das Verzeichnis /gnu/store hat seine für gewöhnlich gigantischen Ausmaße verloren und ist nur mehr ein Schatten seiner selbst.

$ echo /gnu/store/*
/gnu/store/…-gcc-10.3.0-lib
/gnu/store/…-glibc-2.33
/gnu/store/…-bash-static-5.1.8
/gnu/store/…-ncurses-6.2.20210619
/gnu/store/…-bash-5.1.8
/gnu/store/…-profile
/gnu/store/…-readline-8.1.1

In einer solchen Umgebung gibt es nichts für Sie zu tun außer die Umgebung wieder zu verlassen. Das geht, indem Sie ^D drücken oder exit aufrufen, womit die eingeschränkte Shell-Umgebung ihr Ende findet.

Sie können zusätzliche Verzeichnisse in der Container-Umgebung zugänglich machen. Verwenden Sie dazu --expose=VERZEICHNIS für eine Verzeichniseinbindung nur mit Lesezugriff innerhalb des Containers oder verwenden Sie --share=VERZEICHNIS für Schreibzugriff. Mit einem zusätzlichen Argument nach dem Verzeichnisnamen können Sie den Namen festlegen, der dem Verzeichnis innerhalb des Containers zugeordnet wird. Folgendes Beispiel zeigt, wie Sie das Verzeichnis /etc aus dem Wirtssystem auf /das/wirtssystem/etc innerhalb eines Containers abbilden, in dem die GNU coreutils installiert sind.

$ guix shell --container --share=/etc=/das/wirtssystem/etc coreutils
$ ls /das/wirtssystem/etc

Gleichermaßen können Sie verhindern, dass das aktuelle Arbeitsverzeichnis eine Zuordnung in den Container bekommt, indem Sie die Befehlszeilenoption --no-cwd angeben. Es ist eine gute Idee, ein Verzeichnis anzulegen, das innerhalb des Containers das Persönliche Verzeichnis (auch „Home-Verzeichnis“) ist. Aus diesem heraus lassen Sie die Shell für den Container starten.

Auf einem fremden System ist es möglich, in einer Container-Umgebung Software zu kompilieren, die mit den Bibliotheken des Systems oder mit dessen Compiler-Toolchain inkompatibel ist. In der Forschung kommt es häufiger vor, dass man in einer R-Sitzung Pakete installieren möchte. Ohne Container ist es gut möglich, dass die Compiler-Toolchain des Fremdsystems und dessen inkompatible Bibliotheken Vorrang haben und die Binärdateien nicht zusammenpassen und in R nicht benutzt werden können. In einer Container-Shell gibt es das Problem nicht, denn die Bibliotheken und Programme des äußeren Systems sind schlicht gar nicht da, weil der mount-Namensraum getrennt ist.

Schauen wir uns ein umfassendes Manifest für eine komfortable R-Entwicklungsumgebung an:

(specifications->manifest
  (list "r-minimal"

        ;; grundlegende Pakete
        "bash-minimal"
        "glibc-locales"
        "nss-certs"

        ;; Befehlszeilenwerkzeuge, die man oft braucht, sonst
        ;; wäre der Container so gut wie leer.
        "coreutils"
        "grep"
        "which"
        "wget"
        "sed"

        ;; R-Programme für Markdown
        "pandoc"

        ;; Toolchain und häufige Bibliotheken für "install.packages"
        "gcc-toolchain@10"
        "gfortran-toolchain"
        "gawk"
        "tar"
        "gzip"
        "unzip"
        "make"
        "cmake"
        "pkg-config"
        "cairo"
        "libxt"
        "openssl"
        "curl"
        "zlib"))

Nehmen wir dieses Manifest und richten uns eine Container-Umgebung ein, in der wir R ausführen. Der Einfachheit halber wollen wir den net-Namensraum teilen und bekommen Zugriff auf die Netzwerkschnittstellen des Wirtssystems. Damit können wir R-Pakete auf traditionelle Weise aus ihrem Quellcode erstellen, ohne uns um inkompatible ABIs oder sonstige Inkompatibilitäten sorgen zu müssen.

$ guix shell --container --network --manifest=manifest.scm -- R

R version 4.2.1 (2022-06-23) -- "Funny-Looking Kid"
Copyright (C) 2022 The R Foundation for Statistical Computing
…
> e <- Sys.getenv("GUIX_ENVIRONMENT")
> Sys.setenv(GIT_SSL_CAINFO=paste0(e, "/etc/ssl/certs/ca-certificates.crt"))
> Sys.setenv(SSL_CERT_FILE=paste0(e, "/etc/ssl/certs/ca-certificates.crt"))
> Sys.setenv(SSL_CERT_DIR=paste0(e, "/etc/ssl/certs"))
> install.packages("Cairo", lib=paste0(getwd()))
…
* installing *source* package 'Cairo' ...
…
* DONE (Cairo)

The downloaded source packages are in
	'/tmp/RtmpCuwdwM/downloaded_packages'
> library("Cairo", lib=getwd())
> # success!

Containerisierte Shells einzusetzen ist lustig, aber wenn man mehr will als einen einzelnen interaktiven Prozess, werden sie ein bisschen umständlich. Manche Aufgaben sind einfach leichter zu lösen, wenn Sie sie auf einem ordentlichen Guix-System als festem Fundament aufbauen. Dann bekämen Sie Zugriff auf das reichhaltige Angebot von Systemdiensten. Im nächsten Abschnitt wird Ihnen gezeigt, wie Sie eine vollständige Instanz von Guix System in einem Container starten können.


Nächste: Container mit Guix System, Nach oben: Container   [Inhalt][Index]