Podman: Linux-Container einfach gemacht, Teil 3

Seite 3: Image Tree

Inhaltsverzeichnis

Container-Images bauen oft aufeinander auf, zum Beispiel durch eine "FROM fedora:30"-Anweisung in einem Dockerfile. Das spart Zeit, da man beim Bauen eines Images nicht immer auf einer grünen Wiese beginnt, und es spart Speicherplatz, da man die verschiedenen Layer der Basis-Images teilen kann. So kann man schnell den Überblick über die Beziehungen von Container-Images verlieren. Genau hierfür ist das podman-image-tree-Kommando gedacht, das die Hierarchie der Layer eines Containers-Images als Baumstruktur präsentiert.

[heise]$ podman pull docker.io/library/wordpress

[heise]$ podman pull docker.io/library/php:7.2-apache

[heise]$ podman image tree docker.io/library/wordpress
Image ID: 6e880d17852f
Tags: [docker.io/library/wordpress:latest]
Size: 429.9MB
Image Layers
├── ID: 3c816b4ead84 Size: 58.47MB
├── ID: e39dad2af72e Size: 3.584kB
├── ID: b2d6a702383c Size: 213.6MB
├── ID: 94609408badd Size: 3.584kB
├── ID: f4dddbf86725 Size: 43.04MB
├── ID: 8f695df43a4c Size: 11.78kB
├── ID: c29d67bf8461 Size: 9.728kB
├── ID: 23f4315918f8 Size: 7.68kB
├── ID: d082f93a18b3 Size: 13.51MB
├── ID: 7ea8bedcac69 Size: 4.096kB
├── ID: dc3bbf7b3dc0 Size: 57.53MB
├── ID: fdbbc6404531 Size: 11.78kB
├── ID: 8d24785437c6 Size: 4.608kB
├── ID: 80715f9e8880 Size: 4.608kB Top Layer of: [docker.io/library/php:7.2-apache]
├── ID: c93cbcd6437e Size: 3.573MB
├── ID: dece674f3cd1 Size: 4.608kB
├── ID: 834f4497afda Size: 7.168kB
├── ID: bfe2ce1263f8 Size: 40.06MB
└── ID: 748e99b214cf Size: 11.78kB Top Layer of: [docker.io/library/wordpress:latest]

Im obigen Beispiel ist zu sehen, dass wordpress:latest auf php:7.2-apache aufbaut. Podman analysiert ausgehend vom Image die verwendeten Layer und versucht, sie als Top-Layer anderer Images zu erkennen. Anzumerken ist, dass ein Layer nur dann als Top-Layer eines Images erkannt wird, wenn es auch im lokalen Container-Speicher liegt.

Die Layer-Hierarchie kann jedoch auch in die andere Richtung aufgelöst werden, um herauszufinden, welche Layer ein bestimmtes Image verwenden. Hierzu muss man die --whatrequires[/codee]-Option verwenden.

[heise]$ podman pull docker.io/circleci/ruby:latest

[heise]$ podman pull docker.io/library/ruby:latest

[heise]$ podman image tree ae96a4ad4f3f --whatrequires
Image ID: ae96a4ad4f3f
Tags: [docker.io/library/ruby:latest]
Size: 894.2MB
Image Layers
└── ID: 9c92106221c7 Size: 2.56kB Top Layer of: [docker.io/library/ruby:latest]
├── ID: 1b90f2b80ba0 Size: 3.584kB
│ ├── ID: 42b7d43ae61c Size: 169.5MB
│ ├── ID: 26dc8ba99ec3 Size: 2.048kB
│ ├── ID: b4f822db8d95 Size: 3.957MB
│ ├── ID: 044e9616ef8a Size: 164.7MB
│ ├── ID: bf94b940200d Size: 11.75MB
│ ├── ID: 4938e71bfb3b Size: 8.532MB
│ └── ID: f513034bf553 Size: 1.141MB
├── ID: 1e55901c3ea9 Size: 3.584kB
├── ID: b62835a63f51 Size: 169.5MB
├── ID: 9f4e8857f3fd Size: 2.048kB
├── ID: c3b392020e8f Size: 3.957MB
├── ID: 880163026a0a Size: 164.8MB
├── ID: 8c78b2b14643 Size: 11.75MB
├── ID: 830370cfa182 Size: 8.532MB
└── ID: 567fd7b7bd38 Size: 1.141MB Top Layer of: [docker.io/circleci/ruby:latest]

Historisch bedingt gibt es verschiedene Container-Image-Formate, doch die Zukunft gehört dem Standard der Open-Container Initiative, der in der OCI-Image-Spezifikation zusammengefasst und stetig erweitert wird, um weitere Anwendungsfälle zu standardisieren. Im Groben beschreibt die Spezifikation die Bausteine eines Images und wie die einzelnen Elemente interpretiert werden können oder müssen. Ein wichtiger Teil der Interpretation ist die Konfigurationsdatei, die sowohl Metadaten als auch Kerndaten enthält.

Kerndaten beschreiben die verschiedenen Layer und wie das Image als Container ausgeführt werden soll. Des Weiteren werden die Daten verwendet, um eine Konfigurationsdatei der OCI-Runtime-Spezifikation zu generieren. Sie legt wiederum fest, wie Container-Runtimes wie runc die Container ausführen sollen (z. B. Kommandos, Argumente, Namespaces, SECCOMP-Profile, Mounts, Umgebungsvariablen und vieles mehr).

Zusammengefasst kann man sagen, dass Container-Images in großen Teilen festlegen, wie sie als Container ausgeführt werden. Die OCI-Image-Spezifikation ist jedoch bewusst im Umfang reduziert und beschränkt sich auf das Notwendigste. Für das Ausführen komplexer Anwendungen reicht das oft nicht aus, wenn sie zum Beispiel Anforderungen an den Host oder die Ausführungsumgebung haben (z. B. Namespaces, Cgroups). Podman bietet hierfür das Kommando [code]podman-container-runlabel an. Podman durchsucht dabei die Image-Konfiguration nach einem bestimmten Label, interpretiert dessen Inhalt als Befehl und führt es aus. Das folgende Beispiel veranschaulicht die Möglichkeiten von podman-container-runlabel.

Zunächst ist ein Container-Image mit einem Label zu erstellen:

[heise]$ cat Dockerfile
FROM fedora:30
LABEL hallo podman run IMAGE echo 'Hallo Welt!'

[heise]$ podman build -q --tag heise:latest -f Dockerfile .
--> ae14ee6e9e369922655620e275d6a0f987aaa31368965f4fb4669078aa868300

Das neu gebaute Image hat ein Label namens "hallo", das einen Container desselben Images ausführen soll, um "Hallo Welt!" auszugeben.

[heise]$ podman container runlabel hallo localhost/heise:runlabel
command: podman run localhost/heise:runlabel echo Hallo Welt!
Hallo Welt!

Grundsätzlich führt Podman beliebige Programme auf dem Host-System aus, um Anwendern möglichst viel Flexibilität zu geben. Daher sollten Entwickler beim Verwenden von runlabels das Credo, nur vertrauenswürdige Container-Images herunterzuladen und auszuführen, besonders ernst nehmen.

Das Interessante am Runlabel-Konzept ist, dass Images nicht nur beschreiben können, wie eine Container-Runtime (z. B. runc) den Container auszuführen hat, sondern auch, wie Container-Engines wie Podman oder Docker das tun sollen, oder gar den Zustand des Hosts verändern können.