{"id":3001,"date":"2021-11-15T07:00:00","date_gmt":"2021-11-15T05:00:00","guid":{"rendered":"https:\/\/www.my-it-brain.de\/wordpress\/?p=3001"},"modified":"2022-02-10T10:38:54","modified_gmt":"2022-02-10T09:38:54","slug":"rootless-podman-mit-debian-bullseye","status":"publish","type":"post","link":"https:\/\/www.my-it-brain.de\/wordpress\/rootless-podman-mit-debian-bullseye\/","title":{"rendered":"Rootless-Podman mit Debian Bullseye"},"content":{"rendered":"\n<p>Dieses Tutorial f\u00fchrt ein in:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"#podman-bullseye\">Die Einrichtung von rootless-Podman unter Debian Bullseye<\/a><\/li><li><a href=\"#registry-config\">Die Konfiguration von Container-Registries<\/a><\/li><li><a href=\"#image-suche\">Die Suche nach Container-Repos mit Podman<\/a><\/li><li><a href=\"#skopeo\">Die Inspektion von Remote-Repos mit Skopeo<\/a><\/li><li><a href=\"#podman-login\">Anmeldung an einer Container-Registry<\/a><\/li><li><a href=\"#podman-pull\">Den Download (Pull) von Container-Images mit Podman<\/a><\/li><li><a href=\"#start-stop\">Container Starten, Stoppen und Entfernen mit Podman<\/a><\/li><li><a href=\"#verwaltung\">Die Verwaltung von Container-Prozessen und -Images<\/a><\/li><li><a href=\"#podman-volume\">Die persistente Speicherung von Daten in Podman-Volumes<\/a><\/li><\/ul>\n\n\n\n<p>Viel Spa\u00df beim Lesen und Freude beim Nachmachen. Falls euch das Tutorial gef\u00e4llt, freue ich mich \u00fcber einen Kommentar. Falls ich etwas ausgelassen oder falsch dargestellt habe, freue ich mich ebenfalls \u00fcber einen Hinweis in den Kommentaren oder per E-Mail.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"vorwort\">Vorwort<\/h2>\n\n\n\n<p>Um sich im Container-Dschungel zurechtzufinden, ist eine fundierte Kenntnis der Terminologie unerl\u00e4sslich. Die Einf\u00fchrung in die Terminologie ist jedoch nicht Bestandteil dieses Tutorials, da es den Umfang sprengen w\u00fcrde.<\/p>\n\n\n\n<p>Unter folgenden Links kann man sich mit der Terminologie vertraut machen:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2021\/11\/2021-06-16_Vortrag_Handout_Linux-Container-Terminologie.pdf\">Linux-Container-Terminologie (PDF)<\/a>; J\u00f6rg Kastning; 2021-06-16<\/li><li><a href=\"https:\/\/developers.redhat.com\/blog\/2018\/02\/22\/container-terminology-practical-introduction\/\">A Practical Introduction to Container Terminology<\/a>; <a href=\"https:\/\/www.redhat.com\/en\/authors\/scott-mccarty-fatherlinux\">Scott McCarty (fatherlinux)<\/a>; February 22, 2018<\/li><\/ul>\n\n\n\n<p>Leider wird die Terminologie selbst von jenen nicht stringent verwendet, die sie eigentlich kennen m\u00fcssten. Dies sorgt gerade beim Einstieg in dieses komplexe Thema h\u00e4ufig f\u00fcr Verwirrung. Ich versuche in diesem Artikel so stringent wie m\u00f6glich zu sein.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"umgebung\">Umgebung<\/h2>\n\n\n\n<p>F\u00fcr dieses Tutorial habe ich eine Installation mit Debian 11.1 (Bullseye) verwendet. Auf dem Host existieren die beiden User Alice und Bob, welche f\u00fcr die Nutzung von rootless-Podman vorbereitet werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"podman-bullseye\">Die Einrichtung von rootless-Podman unter Debian Bullseye<\/h2>\n\n\n\n<p>Rootless-Container haben die Eigenschaft, dass sie in <em>User Namespaces<\/em> (siehe user_namespaces(7) und namespaces(7)) ausgef\u00fchrt werden. UIDs und GIDs, welche innerhalb des Containers existieren, werden dabei auf UIDs\/GIDs des Hosts abgebildet. So besitzt ein Prozess, welcher innerhalb eines Containers mit der UID 0 (root) l\u00e4uft, au\u00dferhalb des Containers bspw. die UID 165537 und damit die Rechte eines normalen Benutzers.<\/p>\n\n\n\n<p>Damit dies funktioniert, wird jedem Benutzer, welcher in der Lage sein soll rootless-Podman-Container auszuf\u00fchren, ein disjunktes Intervall sogenannter SUBUIDs und SUBGIDs zugewiesen. Dazu werden zuerst das Paket <code>uidmap<\/code> installiert und anschlie\u00dfend die Dateien <em>\/etc\/subuid<\/em> und <em>\/etc\/subgid<\/em> erzeugt, wie in folgendem Codeblock dargestellt.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install uidmap\n&#91;...]\n$ cat \/etc\/subuid\nalice:100000:65536\nbob:165536:65536\n\n$ cat \/etc\/subgid\nalice:100000:65536\nbob:165536:65536<\/code><\/pre>\n\n\n\n<p>Ich habe mich hier an der <a href=\"#1\">RHEL 8 Dokumentation<\/a> orientiert, welche am Ende des Artikels verlinkt ist. Dar\u00fcber hinaus ist das Vorgehen in der Manpage podman(1) im Abschnitt &#8222;Rootless mode&#8220; dokumentiert.<\/p>\n\n\n\n<p>Nun werden <code>podman<\/code> und <code>skopeo<\/code> installiert, welche im weiteren Verlauf dieses Tutorials zum Einsatz kommen werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install podman skopeo<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"registry-config\">Die Konfiguration von Container-Registries<\/h2>\n\n\n\n<p>In der Datei <em>\/etc\/containers\/registries.conf<\/em> befindet sich die systemweite Konfiguration f\u00fcr Container-Registries. Jeder Benutzer kann abweichend von dieser eine eigene Konfiguration unter <em>$HOME\/.config\/containers\/registries.conf<\/em> pflegen.<\/p>\n\n\n\n<p>Bevor nun die ersten Container-Registries konfiguriert werden, m\u00f6chte ich kurz auf voll-qualifizierte Image-Namen und Pr\u00e4fixe eingehen.<\/p>\n\n\n\n<p>Im Internet findet man h\u00e4ufig Beispiele f\u00fcr Befehle wie <code>podman pull ubuntu<\/code>. Dabei ist <code>podman<\/code> das Kommando, <code>pull<\/code> ein Subkommando und <code>ubuntu<\/code> der Kurzname des herunterzuladenden Images.<\/p>\n\n\n\n<p>Obige Kurznamen haben das Problem, dass durch ihre Verwendung nicht spezifiziert wird, aus welcher Container-Registry das Image heruntergeladen werden soll. Existiert ein Image mit gleichem Namen in diversen Container-Registries, wird es aus der ersten heruntergeladen, in der es gefunden wurde. Dies stellt ein potenzielles Sicherheitsrisiko dar!<\/p>\n\n\n\n<p>Nehmen wir an, auf einem System sind die Container-Registries <em>registry-1.de<\/em> und <em>registry-2.de<\/em> konfiguriert. Das <code>ubuntu<\/code>-Image befindet sich unter <code>registry-2.de\/canonical\/ubuntu<\/code>. Stellt nun jemand ein Image gleichen Namens unter <code>registry-1.de\/boeserbube\/ubuntu<\/code> ein, wird bei Ausf\u00fchrung des oben genannten Kommandos mit Image-Kurznamen das falsche Container-Image heruntergeladen. Dies birgt die Gefahr, dass auf diesem Wege mit Schadcode angereicherte Container-Images ihren Weg ins System finden.<\/p>\n\n\n\n<p>Es wird daher dringend empfohlen, stets den voll-qualifizierten Image-Namen zu verwenden, um vorstehend beschriebenes Sicherheitsrisiko auszuschlie\u00dfen. Der voll-qualifizierte Name hat dabei folgende Form:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>host&#91;:port]\/namespace&#91;_namespace_...]\/repo(:_tag|@digest)<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>host<\/strong> spezifiziert den FQDN unter dem eine Container-Registry erreichbar ist, z.&nbsp;B. registry.fedoraproject.org. <\/li><li><strong>port<\/strong> ist optional und wird verwendet, wenn die Registry nicht den Port 443\/tcp nutzt.<\/li><li><strong>namespace<\/strong> spezifiziert den Namensraum, in dem Container-Repos bereitgestellt werden.<\/li><li><strong>repo<\/strong> bezeichnet ein Repository, aus dem konkrete Container-Images heruntergeladen werden k\u00f6nnen.<\/li><li><strong>_tag|@digest<\/strong> optional k\u00f6nnen spezifische Tags oder Digests mit angegeben werden, um eine spezifische Version eines Container-Images herunterzuladen. Standardm\u00e4\u00dfig wird immer die <s>letzte<\/s> Version mit dem Tag latest heruntergeladen. Nur wenn man explizit einen Tag angibt, kann man sicher sein, welche Version man bekommt (Vielen Dank an Dirk f\u00fcr diesen <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/rootless-podman-mit-debian-bullseye\/#comment-30425\">Hinweis<\/a>).<\/li><\/ul>\n\n\n\n<p>Statt einem <code>podman pull ubuntu<\/code> wird also ein <code>podman pull registry-2.de\/canonical\/ubuntu<\/code> empfohlen. Dabei stellt <code>registry-2.de<\/code> den Host, <code>canonical<\/code> den Namespace und <code>ubuntu<\/code> das Repository dar. Bei Verwendung der Docker-Registry f\u00fchrt man so nicht <code>podman pull ubuntu<\/code> aus, sondern stattdessen <code>podman pull docker.io\/library\/ubuntu<\/code>.<\/p>\n\n\n\n<p>F\u00fcr dieses Tutorial werden mehrere Registries durch folgenden Eintrag in der Datei <strong>\/etc\/containers\/registries.conf<\/strong> konfiguriert:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unqualified-search-registries = &#91;'registry.fedoraproject.org', 'registry.access.redhat.com', 'registry.centos.org', 'quay.io', 'registry.opensuse.org', 'registry.suse.com', 'docker.io']<\/code><\/pre>\n\n\n\n<p>Diese habe ich dem englischsprachigen Artikel unter <a href=\"#2\">2<\/a> entnommen und um die Registries aus <strong>\/etc\/containers\/registries.conf.d\/shortnames.conf<\/strong> erg\u00e4nzt. Letztere Datei stammt aus dem Paket <code>golang-github-containers-common<\/code> und stellt Aliase\/Shortnames bereit, mit denen man sich einige Tipparbeit ersparen kann, da sie die Shortnames mit den entsprechenden Registries verkn\u00fcpft. So sorgt z.&nbsp;B. der folgende Eintrag daf\u00fcr, dass der Befehl <code>podman pull rhel7<\/code> das Image ausschlie\u00dflich aus der Registry &#8222;registry.access.redhat.com\/rhel7&#8220; herunterl\u00e4dt und aus keiner anderen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;aliases]\n \"rhel7\" = \"registry.access.redhat.com\/rhel7\"<\/code><\/pre>\n\n\n\n<p>Auf diese Weise k\u00f6nnen Shortnames gefahrlos verwendet werden.<\/p>\n\n\n\n<p>Bitte beachtet, dass f\u00fcr die Nutzung folgender Registries eine Authentifizierung notwendig ist, f\u00fcr die ein Account bei der jeweiligen Registry erforderlich ist:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>registry.suse.com<\/li><li>registry.access.redhat.com<\/li><li>quay.io<\/li><\/ul>\n\n\n\n<p>Wie man sich an einer Registry authentisiert, wird im Abschnitt <a href=\"#podman-login\">Anmeldung an einer Container-Registry<\/a> erl\u00e4utert.<\/p>\n\n\n\n<p>Jetzt, da einige Registries konfiguriert sind, k\u00f6nnen wir zum n\u00e4chsten Abschnitt \u00fcbergehen und mit Podman nach Images suchen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"image-suche\">Die Suche von Container-Images mit Podman<\/h2>\n\n\n\n<p>Mit folgendem Kommando durchsucht man die konfigurierten Registries nach einem Image f\u00fcr &#8218;debian&#8216;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman search debian\nINDEX      NAME                                                        DESCRIPTI\nON                                      STARS   OFFICIAL  AUTOMATED\ndocker.io  docker.io\/library\/debian                                    Debian is\n a Linux distribution that's compos...  4036    &#91;OK]      \ndocker.io  docker.io\/smartentry\/debian                                 debian wi\nth smartentry                           6                 &#91;OK]\ndocker.io  docker.io\/library\/ubuntu                                    Ubuntu is\n a Debian-based Linux operating sys...  12971   &#91;OK]\n&#91;Ausgabe gek\u00fcrzt]<\/code><\/pre>\n\n\n\n<p>Auf meinem System lieferte die Suche nach &#8218;debian&#8216; 271 Treffer zur\u00fcck. Die Ausgabe wurde zur besseren \u00dcbersicht gek\u00fcrzt. In der Spalte &#8218;INDEX&#8216; findet sich der Name der Registry, aus der ein Suchergebnis stammt, gefolgt von der Spalte &#8218;NAME&#8216;, welche den Namen des gefundenen Repositorys enth\u00e4lt. Nutzer k\u00f6nnen f\u00fcr einzelne Repos Sterne vergeben, wenn sie diese besonders toll finden. Dies wird in der Spalte &#8218;STARS&#8216; ausgedr\u00fcckt.<\/p>\n\n\n\n<p>Laut Manpage podman-search(1) dr\u00fcckt ein &#8222;[OK]&#8220; in Spalte &#8218;OFFICIAL&#8216; aus, dass es sich hierbei um ein offizielles Image handelt. Mir ist Stand heute noch unklar, wer diesen Status in den einzelnen Registries vergibt. Er ist in meinen Augen mit etwas Vorsicht zu genie\u00dfen.<\/p>\n\n\n\n<p>Die Spalte &#8218;AUTOMATED&#8216; gibt an, ob das Image automatisiert erstellt wurde und &#8218;DESCRIPTION&#8216; sollte selbsterkl\u00e4rend sein.<\/p>\n\n\n\n<p>Die Suche bietet einige Filterm\u00f6glichkeiten. So kann man mit folgender Suche nach offiziellen Images filtern:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman search --filter is-official debian\nINDEX      NAME                      DESCRIPTION                                      STARS   OFFICIAL  AUTOMATED\ndocker.io  docker.io\/library\/debian  Debian is a Linux distribution that's compos...  4036    &#91;OK]      \ndocker.io  docker.io\/library\/ubuntu  Ubuntu is a Debian-based Linux operating sys...  12971   &#91;OK]<\/code><\/pre>\n\n\n\n<p>Damit ist die Ausgabe schon \u00fcbersichtlicher, viele Informationen bietet sie allerdings nicht. Der folgende Abschnitt zeigt eine M\u00f6glichkeit auf, sich etwas mehr Informationen zu verschaffen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"skopeo\">Die Inspektion von Remote-Repos mit Skopeo<\/h2>\n\n\n\n<p>Mit <code>skopeo<\/code> k\u00f6nnen aus dem Terminal heraus weitere Informationen \u00fcber ein Remote-Repo abgerufen werden, z.B. f\u00fcr den ersten Suchtreffer von oben:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>skopeo inspect docker:\/\/docker.io\/library\/debian<\/code><\/pre>\n\n\n\n<p>Die Ausgabe obigen Kommandos wird hier stark gek\u00fcrzt dargestellt. Neben dem Namen befinden sich darin u.a. Informationen zu vorhandenen Tags, das Erstellungsdatum, Layer und Angaben zum Environment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"Name\": \"docker.io\/library\/debian\",\n    \"Digest\": \"sha256:4d6ab716de467aad58e91b1b720f0badd7478847ec7a18f66027d0f8a3\n29a43c\",\n    \"RepoTags\": &#91;\n        \"10.11\",\n&#91;...]\n       \"bookworm-20211011\",\n        \"bookworm-20211011-slim\",\n        \"bookworm-backports\",\n        \"bookworm-slim\",\n        \"bullseye\",\n        \"bullseye-20190708\",\n        \"bullseye-20190708-slim\",\n        \"bullseye-20190812\",\n        \"bullseye-20190812-slim\",\n        \"bullseye-20190910\",\n&#91;...]\n        \"bullseye-20211011\",\n        \"bullseye-20211011-slim\",\n        \"bullseye-backports\",\n        \"bullseye-slim\",\n        \"buster\",\n&#91;...]        \n    ],\n    \"Created\": \"2021-10-12T01:20:30.89167925Z\",\n    \"DockerVersion\": \"20.10.7\",\n    \"Labels\": null,\n    \"Architecture\": \"amd64\",\n    \"Os\": \"linux\",\n    \"Layers\": &#91;\n        \"sha256:bb7d5a84853b217ac05783963f12b034243070c1c9c8d2e60ada47444f3cce04\n\"\n    ],\n    \"Env\": &#91;\n        \"PATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin\"\n    ]\n}<\/code><\/pre>\n\n\n\n<p>Probiert dieses Kommando ruhig einmal selbst aus und bl\u00e4ttert durch die sehr umfangreiche Tag-Liste. Hier wird deutlich, dass es sich um ein Repository und nicht um ein einzelnes Image handelt. Neben Bullseye lassen sich hier noch Images f\u00fcr Buster, Stretch, Jessie und weitere herunterladen.<\/p>\n\n\n\n<p>Ich selbst verwende <code>skopeo<\/code> prim\u00e4r, um mir einen \u00dcberblick \u00fcber die verf\u00fcgbaren Tags zu verschaffen, um dar\u00fcber das f\u00fcr mich am besten geeignete Image ausw\u00e4hlen zu k\u00f6nnen.<\/p>\n\n\n\n<p>An dieser Stelle sei darauf hingewiesen, dass zu den meisten Repos eine Webseite existiert, auf der sich weitere Informationen zu einem Repo bzw. Image finden lassen. Hier finden sich oft auch Hinweise, wie ein Image bei der Instanziierung zu parametrisieren ist.<\/p>\n\n\n\n<p>Es braucht dann leider doch mehr als ein Werkzeug, um einen guten \u00dcberblick zu bekommen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"podman-login\">Anmeldung an einer Container-Registry<\/h2>\n\n\n\n<p>Bisher wurde in diesem Tutorial nur die frei zug\u00e4ngliche Registry &#8222;docker.io&#8220; verwendet. Neben dieser existieren noch viele weitere Registries. Auf einige davon darf man erst nach erfolgreicher Authentifizierung zugreifen bzw. sind einige Inhalte erst nach erfolgreicher Authentifizierung zug\u00e4nglich.<\/p>\n\n\n\n<p>Meist muss man sich zuerst \u00fcber die Webseite einer Registry registrieren, um Zugangsdaten zu erhalten, welche man dann im Terminal verwenden kann.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman login quay.io\nUsername: alice\nPassword:\nLogin Succeeded!<\/code><\/pre>\n\n\n\n<p>Vorstehender Code-Block zeigt ein einfaches Beispiel f\u00fcr einen Login-Vorgang. Die Manpage podman-login(1) verr\u00e4t, dass Benutzername und Passwort base64-codiert in der Datei <code>${XDG_RUNTIME_DIR}\/containers\/auth.json<\/code> gespeichert werden. Dabei l\u00f6st <code>${XDG_RUNTIME_DIR}<\/code> zu <em>\/run\/user\/<\/em> auf, welches von der entsprechenden UID und Prozessen mit root-Rechten zugreifbar ist.<\/p>\n\n\n\n<p><em>Hinweis:<\/em> Bei Base64-Codierung handelt es sich um keine Sicherheitsfunktion, zum Schutz der Zugangsdaten. Diese werden quasi als Klartext gespeichert.<\/p>\n\n\n\n<p>Die Zugangsdaten werden in der Datei <code>auth.json<\/code> gespeichert, bis man sich wieder abmeldet (z.B. mit <code>podman logout<\/code>) oder der Host neu gestartet wird. Weitere Informationen dazu bieten die Manpages podman-login(1) und containers-auth.json(5).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"podman-pull\">Den Download (Pull) von Container-Images mit Podman<\/h2>\n\n\n\n<p>Der folgende Befehl zeigt, wie das Container-Image f\u00fcr Debian Bullseye aus dem Repo &#8218;debian&#8216; der Registry &#8218;docker.io&#8216; heruntergeladen wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman pull docker.io\/library\/debian:bullseye\nTrying to pull docker.io\/library\/debian:bullseye...\nGetting image source signatures\nCopying blob bb7d5a84853b done  \nCopying config f776cfb21b done  \nWriting manifest to image destination\nStoring signatures\nf776cfb21b5e06bb5b4883eb15c09ab928a411476b8275293c7f96d09b90f7f9<\/code><\/pre>\n\n\n\n<p>Das Image wird im lokalen Image-Speicher abgelegt. Dieser befindet sich bei Rootless-Podman unterhalb von <em>.local\/share\/containers\/storage\/overlay-images\/<\/em>. Die lokal gespeicherten Images kann man sich mit dem folgenden Kommando auflisten lassen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman images\nREPOSITORY                TAG       IMAGE ID      CREATED      SIZE\nregistry.access.redhat.com\/ubi8  latest    b1e63aaae5cf  7 days ago   233 MB\ndocker.io\/library\/debian         bullseye  f776cfb21b5e  3 weeks ago  129 MB<\/code><\/pre>\n\n\n\n<p>Auf meinem Beispielsystem existiert aktuell nur das soeben heruntergeladene Debian-Image sowie ein UBI8-Image.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"start-stop\">Container starten, stoppen und entfernen mit Podman<\/h2>\n\n\n\n<p>An dieser Stelle m\u00f6chte ich in Erinnerung bringen, dass es sich bei Linux-Containern um zustandslose Prozesse handelt, welche in Kernel-Namespaces ausgef\u00fchrt werden. F\u00fcr wen dies eine v\u00f6llig neue Erkenntnis ist, der sei auf die Artikel unter <a href=\"#3\">3<\/a>, <a href=\"#4\">4<\/a> und <a href=\"#5\">5<\/a> verwiesen.<\/p>\n\n\n\n<p>In den folgenden Unterpunkten f\u00fchre ich noch einige wenige Beispiele exemplarisch auf. F\u00fcr weitere Optionen sie auf die Manpage podman(1) verwiesen, welche einen \u00dcberblick \u00fcber allgemeine Optionen und Verweise zu verf\u00fcgbaren Podman-Kommandos bietet.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"befehl-in-einem-container-ausfuhren\">Befehl in einem Container ausf\u00fchren<\/h3>\n\n\n\n<p>Dieses Beispiel zeigt, wie ein Container von einem lokal gespeicherten Image instanziiert wird, einen einzigen Befehl ausf\u00fchrt, dessen Ausgabe nach STDOUT schreibt und danach beendet und entfernt wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman run --rm ubi8 cat \/etc\/os-release\nNAME=\"Red Hat Enterprise Linux\"\nVERSION=\"8.4 (Ootpa)\"\nID=\"rhel\"\nID_LIKE=\"fedora\"\nVERSION_ID=\"8.4\"\nPLATFORM_ID=\"platform:el8\"\nPRETTY_NAME=\"Red Hat Enterprise Linux 8.4 (Ootpa)\"\nANSI_COLOR=\"0;31\"\nCPE_NAME=\"cpe:\/o:redhat:enterprise_linux:8.4:GA\"\nHOME_URL=\"https:\/\/www.redhat.com\/\"\nDOCUMENTATION_URL=\"https:\/\/access.redhat.com\/documentation\/red_hat_enterprise_linux\/8\/\"\nBUG_REPORT_URL=\"https:\/\/bugzilla.redhat.com\/\"\n\nREDHAT_BUGZILLA_PRODUCT=\"Red Hat Enterprise Linux 8\"\nREDHAT_BUGZILLA_PRODUCT_VERSION=8.4\nREDHAT_SUPPORT_PRODUCT=\"Red Hat Enterprise Linux\"\nREDHAT_SUPPORT_PRODUCT_VERSION=\"8.4\"<\/code><\/pre>\n\n\n\n<p>Der Container existierte nur f\u00fcr die Zeit, die zur Ausf\u00fchrung des Befehls <code>cat \/etc\/os-release<\/code> erforderlich war. Die Ausgabe l\u00e4sst erkennen, dass das Image ubi8 ein Userland aus RHEL 8.4 bereitstellt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"einen-dienst-in-einem-container-starten\">Einen Dienst in einem Container starten<\/h3>\n\n\n\n<p>M\u00f6chte man einen Dienst in einem Container laufen lassen, so gibt es daf\u00fcr die Option &#8218;-d&#8216;, mit welcher man den Container im Hintergrund startet. Ich demonstriere dies an einem kleinen Webserver:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman run -d -p 8080:80 httpd\n\u2714 docker.io\/library\/httpd:latest\nTrying to pull docker.io\/library\/httpd:latest...\nGetting image source signatures\nCopying blob 462e88bc3074 done  \nCopying blob 21d69ac90caf done  \nCopying blob ca52f3eeea66 done  \nCopying blob 7d63c13d9b9b done  \nCopying blob 448256567156 done  \nCopying config 1132a4fc88 done  \nWriting manifest to image destination\nStoring signatures\n3893630d276a7bfb4a3d8c74c5be8ad353b82c1f45081dec0d31b599a5856944<\/code><\/pre>\n\n\n\n<p>Da noch kein Image f\u00fcr &#8218;httpd&#8216; im lokalen Image-Speicher existiert, wird dieses automatisch heruntergeladen. Mit der Option <code>-p 8080:80<\/code> wird der TCP-Port 8080 des Host-Betriebssystems mit dem Port 80 des Containers verkn\u00fcpft.<\/p>\n\n\n\n<p>Folgender Code-Block zeigt, dass nun ein einfacher Webserver l\u00e4uft, welcher die Standard-HTML-Seite &#8222;It works!&#8220; ausliefert:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ curl http:\/\/localhost:8080\n&lt;html&gt;&lt;body&gt;&lt;h1&gt;It works!&lt;\/h1&gt;&lt;\/body&gt;&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p>Der Container l\u00e4uft, bis er durch einen Neustart des Betriebssystems oder manuell durch den Benutzer beendet wird.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"container-stoppen\">Container stoppen<\/h3>\n\n\n\n<p>Um einen im Hintergrund laufenden Container zu stoppen, wird zun\u00e4chst dessen ID ben\u00f6tigt. Diese ist in der ersten Spalte der Ausgabe des Kommandos <code>podman ps<\/code> enthalten:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman ps\nCONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS            PORTS                 NAMES\n3893630d276a  docker.io\/library\/httpd:latest  httpd-foreground  16 minutes ago  Up 2 minutes ago  0.0.0.0:8080-&gt;80\/tcp  optimistic_visvesvaraya<\/code><\/pre>\n\n\n\n<p>Gestoppt wird der Container mit folgendem Befehl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman container stop 3893630d276a\n3893630d276a7bfb4a3d8c74c5be8ad353b82c1f45081dec0d31b599a5856944<\/code><\/pre>\n\n\n\n<p>Es wird die vollst\u00e4ndige ID des Containers ausgegeben. Diese kann genutzt werden, um den Container zu entfernen (<code>podman rm ID<\/code>) oder um ihn wieder zu starten (<code>podman start ID<\/code>).<\/p>\n\n\n\n<p>Wird ein Container nur gestoppt, bleibt seine Konfiguration erhalten, sodass er mit den gleichen Optionen wieder gestartet werden kann. Eine \u00dcbersicht \u00fcber gestoppte oder anderweitig beendete Container bietet das folgende Kommando:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman ps --all\nCONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS                     PORTS                 NAMES\n3893630d276a  docker.io\/library\/httpd:latest  httpd-foreground  13 minutes ago  Exited (0) 16 seconds ago  0.0.0.0:8080-&gt;80\/tcp  optimistic_visvesvaraya<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"verwaltung\">Die Verwaltung von Container-Prozessen und -Images<\/h2>\n\n\n\n<p>Eine \u00dcbersicht \u00fcber laufende Container bietet das folgende Kommando:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman ps\nCONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS            PORTS                 NAMES\n3893630d276a  docker.io\/library\/httpd:latest  httpd-foreground  16 minutes ago  Up 2 minutes ago  0.0.0.0:8080-&gt;80\/tcp  optimistic_visvesvaraya<\/code><\/pre>\n\n\n\n<p>M\u00f6chte man einen Container entfernen, so geschieht dies mit dem Kommando <code>podman rm ID<\/code>. Dabei wird nur die Konfiguration des Containers entfernt, nicht das lokal gespeicherte Image. Folgender Code-Block verdeutlicht dies:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman rm 4476cb9d7eec939281abfe0b12bdb8f2083154dbfbc138492b811e0389ad5bfa\n4476cb9d7eec939281abfe0b12bdb8f2083154dbfbc138492b811e0389ad5bfa\n\n$ podman ps --all\nCONTAINER ID  IMAGE   COMMAND  CREATED  STATUS  PORTS   NAMES\n\n$ podman images\nREPOSITORY                       TAG       IMAGE ID      CREATED      SIZE\nregistry.access.redhat.com\/ubi8  latest    b1e63aaae5cf  7 days ago   233 MB\ndocker.io\/library\/httpd          latest    1132a4fc88fa  11 days ago  148 MB\ndocker.io\/library\/debian         bullseye  f776cfb21b5e  3 weeks ago  129 MB<\/code><\/pre>\n\n\n\n<p>M\u00f6chte man auch das Image entfernen, so geschieht dies mit folgendem Befehl:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ podman rmi b1e63aaae5cf<br>Untagged: registry.access.redhat.com\/ubi8:latest<br>Deleted: b1e63aaae5cffb78e4af9f3a110dbad67e8013ca3de6d09f1ef496d00641e751<\/pre>\n\n\n\n<p>Bei &#8218;b1e63aaae5cf&#8216; handelt es sich um die Image-ID, welche in der Ausgabe von <code>podman images<\/code> zu sehen ist.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"podman-volume\">Die persistente Speicherung von Daten in Podman-Volumes<\/h2>\n\n\n\n<p>Container sind, wie bereits erw\u00e4hnt, zustandslose Objekte. M\u00f6chte man Daten persistent speichern, k\u00f6nnen daf\u00fcr sogenannte Podman-Volumes verwendet werden.<\/p>\n\n\n\n<p>So ist es bspw. m\u00f6glich, ein Verzeichnis vom Host in einen Container hinein zu mounten. Schreibt der Container-Prozess nun Daten in diesem Mountpoint, bleiben diese erhalten, nachdem der Container gel\u00f6scht wurde. Sie k\u00f6nnen sp\u00e4ter in eine neue Container-Instanz hinein gemountet werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"beispiel-verzeichnis-vom-host-in-container-einhangen\">Beispiel: Verzeichnis vom Host in Container einh\u00e4ngen<\/h3>\n\n\n\n<p>Im folgenden Code-Block wird ein Verzeichnis im HOME-Verzeichnis eines normalen Nutzers erstellt und anschlie\u00dfend in einen Container eingeh\u00e4ngt. Der Einh\u00e4ngepunkt im Container muss dabei bereits im Container-Image existieren. Der Container erstellt eine Datei namens TEST in diesem Volume. Anschlie\u00dfend wird der Container beendet und entfernt. Die erstellte Datei befindet sich weiterhin in dem Verzeichnis auf dem Host.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ mkdir testdir\n$ podman run --rm -v ~\/testdir:\/tmp:Z debian touch \/tmp\/TEST\n$ ls -l testdir\/\ntotal 0\n-rw-r--r--. 1 alice alice 0  7. Nov 14:01 TEST<\/code><\/pre>\n\n\n\n<p>Die Option &#8218;Z&#8216; sorgt daf\u00fcr, dass der SELinux-Datei-Kontext f\u00fcr das Verzeichnis korrekt gesetzt wird, sodass der Container auf dieses Volumen zugreifen kann. F\u00fcr weitere Details siehe Option &#8218;-v&#8216; in podman-run(1).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"podman-volume-erstellen-und-einhangen\">Podman-Volume erstellen und einh\u00e4ngen<\/h3>\n\n\n\n<p>Mit podman-volume(1) stellt Podman ein einfaches Verwaltungswerkzeug f\u00fcr Podman-Volumes zur Verf\u00fcgung. Folgendes Code-Beispiel zeigt, wie mit podman-volume-create(1) ein Volume mit einem eindeutigen Beizeichner (testdir2) erstellt wird. Anschlie\u00dfend wird dieses, wie im vorangehenden Beispiel, in einen Container eingeh\u00e4ngt und die Datei TESTDATEI hineingeschrieben.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman volume create testdir2\ntestdir2\n$ podman run --rm -v testdir2:\/tmp:Z debian touch \/tmp\/TESTDATEI<\/code><\/pre>\n\n\n\n<p>Doch wo findet man nun die TESTDATEI au\u00dferhalb des Containers wieder? Wo befindet sich der Speicherort des zuvor erstellten Volumes &#8218;testdir2&#8216;? Auskunft dar\u00fcber gibt das Kommando <code>podman volume inspect VOLUMENAME<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman volume inspect testdir2\n&#91;\n    {\n        \"Name\": \"testdir2\",\n        \"Driver\": \"local\",\n        \"Mountpoint\": \"\/home\/alice\/.local\/share\/containers\/storage\/volumes\/testdir2\/_data\",\n        \"CreatedAt\": \"2021-11-07T14:39:56.557400855+01:00\",\n        \"Labels\": {},\n        \"Scope\": \"local\",\n        \"Options\": {}\n    }\n]<\/code><\/pre>\n\n\n\n<p>Der Schl\u00fcssel Mountpoint gibt den Volume-Pfad an. Und tats\u00e4chlich findet sich dort die TESTDATEI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ ls -l \/home\/alice\/.local\/share\/containers\/storage\/volumes\/testdir2\/_data\ntotal 0\n-rw-r--r--. 1 alice alice 0  7. Nov 14:40 TESTDATEI<\/code><\/pre>\n\n\n\n<p>Die TESTDATEI geh\u00f6rt Alice, welche den Container-Prozess gestartet hat. M\u00f6chte man den Inhalt eines Volumes sichern, kann man die enthaltenen Verzeichnisse und Dateien mit bekannten Mitteln kopieren oder mittels podman-volume-export(1) in ein TAR-Archiv verpacken:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman volume export testdir2 -o testdir2.tar<\/code><\/pre>\n\n\n\n<p>Ben\u00f6tigt man das Volume nicht mehr, kann man es inkl. seines Inhalts mit dem folgenden Befehl l\u00f6schen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman volume rm testdir2\ntestdir2<\/code><\/pre>\n\n\n\n<p>M\u00f6chte man sich die existierenden Volumes anzeigen lassen, gelingt dies mit dem folgenden Befehl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman volume ls\nDRIVER      VOLUME NAME\nlocal       vol1\nlocal       vol2\nlocal       vol3<\/code><\/pre>\n\n\n\n<p>Der Spalte DRIVER ist zu entnehmen, dass alle diese Volumes im lokalen Dateisystem gespeichert sind. \u00dcber weitere Storage-Backends kann ich an dieser Stelle leider noch keine Aussage treffen, da mir hierzu noch das notwendige Wissen fehlt.<\/p>\n\n\n\n<p>Zum Abschluss dieses Abschnitts noch der Befehl, mit dem sich alle ungenutzten Volumes entfernen lassen:<\/p>\n\n\n\n<p><strong>Achtung:<\/strong> Bei folgendem Kommando ist Vorsicht geboten. Ein genauer Blick darauf, welche Volumes entfernt werden sollen, lohnt sich. Andernfalls droht Datenverlust.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman volume prune\nWARNING! This will remove all volumes not used by at least one container. The following volumes will be removed:\nvol1\nvol2\nvol3\nAre you sure you want to continue? &#91;y\/N] y\nvol1\nvol2\nvol3<\/code><\/pre>\n\n\n\n<p>An dieser Stelle m\u00f6chte ich den kurzen \u00dcberblick \u00fcber die Podman-Volume-Befehle beenden. Wer sich weitergehend damit auseinandersetzen m\u00f6chte, findet \u00fcber die Manpage podman-volume(1) einen guten Einstieg.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fazit\">Fazit<\/h2>\n\n\n\n<p>Am Ende dieses Tutorials sollte man in der Lage sein, Rootless-Podman auf Debian Bullseye einzurichten. Mit ein wenig Abstraktionsverm\u00f6gen sollte dies auch auf weiteren Distributionen gelingen.<\/p>\n\n\n\n<p>Die grundlegenden Befehle zur Bedienung und Nutzung wurden kurz vorgestellt, sodass man nun \u00fcber das n\u00f6tige Wissen verf\u00fcgt, die ersten eigenen Schritte mit dieser noch recht jungen Technologie zu unternehmen.<\/p>\n\n\n\n<p>F\u00fcr eure ersten Versuche mit Podman w\u00fcnsche ich euch viel Spa\u00df und Erfolg.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"quellen-und-weiterfuhrende-links\">Quellen und weiterf\u00fchrende Links<\/h2>\n\n\n\n<ol class=\"wp-block-list\"><li id=\"1\">RHEL 8 Building, running, and managing containers. Chapter 1.5. Upgrading to rootless containers URL: <a href=\"https:\/\/access.redhat.com\/documentation\/en-us\/red_hat_enterprise_linux\/8\/html\/building_running_and_managing_containers\/assembly_starting-with-containers_building-running-and-managing-containers#proc_upgrading-to-rootless-containers_assembly_starting-with-containers\">https:\/\/access.redhat.com\/documentation\/en-us\/red_hat_enterprise_linux\/8\/html\/building_running_and_managing_containers\/assembly_starting-with-containers_building-running-and-managing-containers#proc_upgrading-to-rootless-containers_assembly_starting-with-containers<\/a><\/li><li id=\"2\"><a href=\"https:\/\/www.redhat.com\/sysadmin\/manage-container-registries\">How to manage Linux container registries<\/a>. <a href=\"https:\/\/www.redhat.com\/sysadmin\/users\/valentin-rothberg\">Valentin Rothberg<\/a> (Red Hat). Enable Sysadmin. 2021-02-16.<\/li><li id=\"3\"><a href=\"https:\/\/www.redhat.com\/en\/blog\/architecting-containers-part-1-why-understanding-user-space-vs-kernel-space-matters\">Architecting Containers Part 1: Why Understanding User Space vs. Kernel Space Matters<\/a>; [Scott McCarty (fatherlinux)}(https:\/\/www.redhat.com\/en\/authors\/scott-mccarty-fatherlinux); July 29, 2015<\/li><li id=\"4\"><a href=\"https:\/\/www.redhat.com\/en\/blog\/architecting-containers-part-2-why-user-space-matters\">Architecting Containers Part 2: Why the User Space Matters<\/a>; <a href=\"https:\/\/www.redhat.com\/en\/authors\/scott-mccarty-fatherlinux\">Scott McCarty (fatherlinux)<\/a>; September 17, 2015<\/li><li id=\"5\"><a href=\"https:\/\/www.redhat.com\/en\/blog\/architecting-containers-part-3-how-user-space-affects-your-application\">Architecting Containers Part 3: How the User Space Affects Your Application<\/a>; <a href=\"https:\/\/www.redhat.com\/en\/authors\/scott-mccarty-fatherlinux\">Scott McCarty (fatherlinux)<\/a>; November 10, 2015<\/li><li id=\"6\"><a href=\"https:\/\/www.my-it-brain.de\/wordpress\/kanboard-im-container\/\">Beginn der Artikelserie &#8222;Kanboard im Container\u2026&#8220;<\/a>; My-IT-Brain; J\u00f6rg Kastning; 2021-01-04<\/li><\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Dieses Tutorial f\u00fchrt ein in: Die Einrichtung von rootless-Podman unter Debian Bullseye Die Konfiguration von Container-Registries Die Suche nach Container-Repos mit Podman Die Inspektion von Remote-Repos mit Skopeo Anmeldung an einer Container-Registry Den Download (Pull) von Container-Images mit Podman Container Starten, Stoppen und Entfernen mit Podman Die Verwaltung von Container-Prozessen und -Images Die persistente Speicherung<span class=\"continue-reading\"> <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/rootless-podman-mit-debian-bullseye\/\">[Weiterlesen&#8230;]<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_metis_text_type":"","_metis_text_length":0,"_post_count":0,"footnotes":""},"categories":[3],"tags":[654,430,305,606,657,658,656,655],"class_list":["post-3001","post","type-post","status-publish","format-standard","hentry","category-tutorials","tag-bullseye","tag-osbn","tag-planet","tag-podman","tag-podman-login","tag-podman-run","tag-podman-volume","tag-rootless-podman"],"_links":{"self":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/3001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/comments?post=3001"}],"version-history":[{"count":9,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/3001\/revisions"}],"predecessor-version":[{"id":3131,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/3001\/revisions\/3131"}],"wp:attachment":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/media?parent=3001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/categories?post=3001"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/tags?post=3001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}