So führen Sie Podman-Container unter Systemd mit Quadlet aus
Quadlet ist ein kostenloses Open-Source-Tool, das in C geschrieben wurde und es uns ermöglicht, Podman-Container unter Systemd zu erstellen und auszuführen. Das Tool ermöglichte es uns, Container, Volumes, Netzwerke und deren Beziehungen mit dedizierten Systemd-Units zu deklarieren.
In diesem Tutorial erfahren Sie, wie Sie Quadlet verwenden, um Podman-Container, Netzwerke und Volumes zu erstellen, und wie Sie Multi-Container-Stacks erstellen.
In diesem Tutorial lernen Sie:
- Wie man Container, Volumes und Netzwerke mit den entsprechenden Systemd-Units erstellt
- So erstellen Sie einen Stack mit mehreren Containern mit Quadlet
Ein einfaches Beispiel: Erstellen eines MariaDB-Containers
In diesem ersten, einfachen Beispiel definieren wir eine Einheit für einen MariaDB-Datenbankserver. So sieht es aus:
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
[Install]
WantedBy=multi-user.target
Mit diesen wenigen Zeilen haben wir einen Container definiert, der auf dem neuesten offiziellen MariaDB-Image basiert, das auf Dockerhub verfügbar ist. Wie Sie sehen können, ist ein ".container" ein dedizierter Typ von Systemd-Unit. Das Besondere an dieser Art von Unit ist der Abschnitt "Container", in dem wir Optionen angeben können, die denen entsprechen, die wir an die Podman-Befehlszeile übergeben können. Die einzige erforderliche Option im Abschnitt "Container" ist Image, um das Basisimage für den Container anzugeben.
Wenn wir möchten, dass der Container als root ausgeführt wird, speichern wir die Datei im Verzeichnis /etc/containers/systemd. Um es als unseren eigenen unprivilegierten Benutzer auszuführen, speichern wir es stattdessen unter ~/.config/containers/systemd. In diesem Beispiel verwenden wir den letzteren Ansatz und speichern unsere Unit ".container" als ~/.config/containers/systemd/mariadb-service.container. Damit systemd einen Dienst basierend auf der Container-Unit generieren kann, führen wir den folgenden Befehl aus:
systemctl --user daemon-reloadNachdem wir den Befehl ausgeführt haben, können wir einen Blick auf den generierten Dienst werfen, indem wir Folgendes ausführen:
systemctl --user cat mariadb-serviceUm den Container zu starten, können wir, wie jeder andere Dienst auch, Folgendes ausführen:
systemctl --user start mariadb-serviceWenn wir den Dienst zum ersten Mal starten, kann es eine Weile dauern, bis er gestartet wird, wenn das Containerbasisimage auf unserem System nicht vorhanden ist. Wir können die podman-Befehlszeile verwenden, um den Status des Containers zu überprüfen:
podman psDer Befehl gibt die folgende Ausgabe zurück, die bestätigt, dass der Container betriebsbereit ist:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
151226b10a1c docker.io/library/mariadb:latest mariadbd 59 seconds ago Up About a minute systemd-mariadb-serviceWie Sie vielleicht bemerkt haben, wird der Container standardmäßig nach der Unit-Datei ".container" plus dem Präfix "systemd-" ("systemd-mariadb-service", in diesem Fall) benannt. Um dem Container explizit einen Namen zuzuweisen, können wir ihn jedoch als Wert der Option ContainerName im Abschnitt "[Container]" übergeben.
Erstellen einer "Volumen"-Einheit
Wir verwenden Volumes, um Containerdaten beizubehalten. In diesem Fall möchten wir, dass unsere Datenbankdaten auch dann erhalten bleiben, wenn wir den Container systemd-mariadb-service löschen. Wir definieren ein benanntes Volume in der entsprechenden Einheit ".volume". Im folgenden Beispiel geben wir nur eine Beschreibung für das Volume an. Volume-spezifische Optionen können in der Zeilengruppe [Volume] angegeben werden:
[Unit]
Description=MariaDB Volume
[Volume]
Wir speichern die Unit als ~/.config/containers/systemd/mariadb-volume.volume. Um den MariaDB-Container anzuweisen, das Volume zu verwenden, verwenden wir die Option Volume im Abschnitt [Container] der Unit ".container" und ordnen das Volume dem Verzeichnis /var/lib/mysql innerhalb des Containers zu:
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
Volume=mariadb-volume.volume:/var/lib/mysql
[Install]
WantedBy=multi-user.targetWenn wir ein benanntes Volume verwenden, weist Systemd automatisch eine Abhängigkeit davon in der Service-Unit zu, die es für unseren Container generiert. Damit systemd die benötigten Dienste neu generieren kann, verwenden wir erneut den Befehl daemon-reload. Sobald wir den MariaDB-Container (neu) starten, wird das Volume automatisch erstellt, wie wir mit dem Befehlszeilenprogramm podman überprüfen können:
podman volume ls
Wie erwartet erscheint unser Volume in der Liste, die mit dem Befehl generiert wird:
DRIVER VOLUME NAME
local systemd-mariadb-volumeWir können auch überprüfen, ob das Volume auf /var/lib/mysql innerhalb des Containers gemountet ist, indem wir den Befehl podman inspect verwenden, den Namen des Containers als Argument übergeben und einen Blick auf den Abschnitt "Mounts" werfen:
podman inspect systemd-mariadb-serviceHier ist der relevante Abschnitt der Ausgabe:
"Mounts": [
{
"Type": "volume",
"Name": "systemd-mariadb-volume",
"Source": "/home/doc/.local/share/containers/storage/volumes/systemd-mariadb-volume/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"Options": [
"nosuid",
"nodev",
"rbind"
],
"RW": true,
"Propagation": "rprivate"
}
],Bind-Mounts verwenden
Was ist, wenn wir bind-mounts anstelle von benannten Volumes verwenden möchten? Bind-Mounts sind während der Entwicklung nützlich, da sie es uns ermöglichen, Hostdateien innerhalb des Containers einzuhängen. Der Nachteil der Verwendung von Bind-Mounts ist, dass Container vom Dateisystem des Hosts abhängig werden. Um einen Bind-Mount innerhalb einer ".container "-Unit zu verwenden, geben wir einfach den relativen oder absoluten Pfad der Hostdatei an, die wir mounten möchten. Nehmen wir zum Beispiel an, wir möchten das Verzeichnis /var/lib/mysql innerhalb des Containers an das Verzeichnis ~/mysql auf dem Host binden. Hier ist, was wir in der Einheit ".container" schreiben könnten:
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
Volume=%h/mysql:/var/lib/mysql
[Install]
WantedBy=multi-user.targetIm obigen Beispiel können Sie feststellen, dass wir den Platzhalter %h verwendet haben, der von Systemd automatisch auf den absoluten Pfad unseres eigenen HOME-Verzeichnisses erweitert wird. Es ist auch möglich, relative Pfade zu verwenden, die relativ zur Position der Unit-Datei aufgelöst werden.
Erstellen von Netzwerken
Um einen Stack zu erstellen, der aus mehreren Containern besteht, müssen wir, ähnlich wie wir es mit docker-compose tun, Container im selben Netzwerk ablegen, damit sie miteinander kommunizieren können. Um ein Netzwerk mit Quadlet zu erstellen, können wir Einheiten mit der Erweiterung ".network " verwenden.
Wie bei Containern und Volumes werden Netzwerke standardmäßig nach der Unit-Datei benannt, in der sie definiert sind, zuzüglich des Präfix "systemd-". Wir können explizit einen Namen oder eine andere netzwerkspezifische Option im Abschnitt [Netzwerk] der Datei angeben. Im folgenden Beispiel geben wir das Subnetz und die Gatewayadresse für das Netzwerk an (dies entspricht dem Ausführen von podman mit den Optionen --subnet 192.168.30.0/24 und --gateway 192.168.30.1):
[Unit]
Description=MariaDB Network
[Network]
Subnet=192.168.30.0/24
Gateway=192.168.30.1Wir speichern die Datei als ~/.config/containers/systemd/mariadb.network. Um einen Container in ein bestimmtes Netzwerk zu "platzieren", verwenden wir die Option Netzwerk im Abschnitt "Container" seiner Container-Unit. Der MariaDB-Container, den wir zuvor definiert haben, wird:
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
Volume=mariadb-volume.volume:/var/lib/mysql
Network=mariadb.networkErstellen eines Stacks mit mehreren Containern
Wir haben einen Container, auf dem unser MariaDB-Server läuft. Um eine einfache Möglichkeit zu bieten, unsere Datenbank über eine Weboberfläche zu verwalten, können wir einen Container erstellen, der auf phpMyAdmin basiert. Damit die beiden Container miteinander kommunizieren können, müssen wir sie in das gleiche Netzwerk legen.
Da der phpMyAdmin-Container, um korrekt zu funktionieren, voraussetzt, dass der MariaDB-Server aktiv ist und läuft, können wir diese Abhängigkeit deklarieren, wie wir es für jeden anderen Systemd-Dienst tun würden, mit den Optionen Requires und After im Abschnitt "[Unit]". Ersteres stellt eine feste Abhängigkeit von dem Dienst her, der als Wert übergeben wird. Letzteres stellt sicher, dass unser Service danach beginnt. Übrigens, wenn Sie sich mit Systemd nicht auskennen, können Sie sich unser Tutorial zum Erstellen eines Systemd-Dienstes ansehen. So sieht die Container-Unit für phpMyAdmin aus:
[Unit]
Description=phpMyAdmin container
Requires=mariadb-service.service
After=mariadb-service.service
[Container]
Image=docker.io/phpmyadmin:latest
Network=mariadb.network
Environment=PMA_HOST=systemd-mariadb-service
PublishPort=8080:80
[Install]
WantedBy=multi-user.target
Im obigen Beispiel haben wir auch die Option PublishPort verwendet, die das Äquivalent zu podman -p (--publish) ist: Sie wird verwendet, um einen Hostport einem Containerport zuzuordnen. In diesem Fall haben wir Port 8080 auf dem Hostsystem dem Port 80 innerhalb des Containers zugeordnet.
Wir haben auch einen Wert für die Umgebungsvariable PMA_HOST über die Option Environment angegeben: Diese wird verwendet, um die Adresse des Datenbankservers anzugeben (in diesem Fall haben wir den Namen des MariaDB-Containers verwendet, der in die tatsächliche Adresse aufgelöst wird). Beachten Sie, dass wir den Namen des MariaDB-Containers als Wert der Umgebungsvariablen verwendet haben, nicht den Namen der Unit ".container". Um unser neues Setup zu starten, führen wir erneut Folgendes aus:
systemd --user daemon-reloadDann können wir den generierten Dienst "phpmyadmin-service" starten, der wiederum den phpMyAdmin-Container ausführt. Da es eine starke Abhängigkeit von der MariaDB-Version hat, wird diese automatisch auch gestartet. Wir sollten in der Lage sein, phpMyadmin unter der Adresse "localhost:8080" zu erreichen. Für die Anmeldung können wir die Anmeldeinformationen verwenden, die in der MariaDB-Container-Unit angegeben sind:
Abschließende Gedanken
In diesem Tutorial haben wir gelernt, wie man Podman-Container, Volumes und Netzwerke unter Systemd mit Quadlet erstellt und ausführt. Anstatt Stacks mit mehreren Containern in einer einzigen Datei zu definieren, wie wir es bei der Verwendung von docker-compose tun, definieren wir mit Quadlet Container, Volumes und Netzwerke mit dedizierten Systemd-Einheiten.

