So führen Sie Podman-Container unter Systemd mit Quadlet aus
Quadlet ist ein kostenloses und in C geschriebenes Open-Source-Tool, mit dem wir Podman-Container unter Systemd erstellen und ausführen können. Mit dem Tool können wir Container, Volumes, Netzwerke und ihre Beziehungen mithilfe dedizierter Systemd-Einheiten deklarieren.
In diesem Tutorial erfahren Sie, wie Sie mit Quadlet Podman-Container, Netzwerke und Volumes erstellen und wie Sie Multi-Container-Stacks erstellen.
In diesem Tutorial lernen Sie:
- So erstellen Sie Container, Volumes und Netzwerke mit den entsprechenden Systemd-Einheiten
- So erstellen Sie mit Quadlet einen Stapel mit mehreren Containern
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 einer Systemd-Einheit. Das Besondere an diesem Einheitentyp 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 Basisbild 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 „.container“-Einheit als ~/.config/containers/systemd/mariadb-service.container
. Damit systemd einen Dienst basierend auf der Containereinheit generieren kann, führen wir den folgenden Befehl aus:
$ systemctl --user daemon-reload
Nachdem wir den Befehl ausgeführt haben, können wir uns den generierten Dienst ansehen, indem wir Folgendes ausführen:
$ systemctl --user cat mariadb-service
Um den Container zu starten, können wir wie jeden anderen Dienst Folgendes ausführen:
$ systemctl --user start mariadb-service
Beim ersten Start kann es eine Weile dauern, bis der Dienst startet, wenn das Container-Basisimage nicht auf unserem System vorhanden ist. Wir können die Podman-Befehlszeile verwenden, um den Status des Containers zu überprüfen:
$ podman ps
Der 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-service
Wie Sie vielleicht bemerkt haben, wird der Container standardmäßig nach der Unit-Datei „.container“ plus dem Präfix „systemd-“ (in diesem Fall „systemd-mariadb-service“) 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 bestehen bleiben, wenn wir den systemd-mariadb-service-Container 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. Volumespezifische Optionen können unter der Zeilengruppe [Volume]
angegeben werden:
[Unit]
Description=MariaDB Volume
[Volume]
Wir speichern die Einheit 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 Einheit „.container“ und ordnen das Volume dem zu Verzeichnis /var/lib/mysql
im Container:
[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.target
Wenn wir ein benanntes Volume verwenden, weist Systemd ihm in der Serviceeinheit, die es für unseren Container generiert, automatisch eine Abhängigkeit zu. Damit systemd die erforderlichen Dienste noch einmal neu generieren kann, verwenden wir den Befehl daemon-reload
. Sobald wir den MariaDB-Container (neu) starten, wird das Volume automatisch erstellt, wie wir mithilfe des Befehlszeilenprogramms podman überprüfen können:
$ podman volume ls
Wie erwartet erscheint unser Volume in der durch den Befehl generierten Liste:
DRIVER VOLUME NAME
local systemd-mariadb-volume
Wir können auch überprüfen, ob das Volume auf /var/lib/mysql im Container gemountet ist, indem wir den Befehl podman inspect
verwenden, den Namen des Containers als Argument übergeben und einen Blick auf die „Mounts“ werfen. Abschnitt:
$ podman inspect systemd-mariadb-service
Hier 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"
}
],
Verwendung von Bind-Mounts
Was ist, wenn wir Bind-Mounts anstelle benannter Volumes verwenden möchten? Bind-Mounts sind während der Entwicklung nützlich, da wir damit Hostdateien innerhalb des Containers mounten können. Der Nachteil der Verwendung von Bind-Mounts besteht darin, dass Container vom Host-Dateisystem abhängig werden. Um einen Bind-Mount innerhalb einer „.container“-Einheit zu verwenden, geben wir einfach den relativen oder absoluten Pfad der Hostdatei an, die wir mounten möchten. Angenommen, wir möchten beispielsweise das Verzeichnis /var/lib/mysql
innerhalb des Containers an das Verzeichnis ~/mysql
auf dem Host binden. Folgendes könnten wir in die Einheit „.container“ schreiben:
[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.target
Im obigen Beispiel sehen Sie, 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.
Netzwerke schaffen
Um einen Stapel aus mehreren Containern zu erstellen, müssen wir, ähnlich wie bei Docker-Compose, Container in dasselbe Netzwerk stellen, damit sie miteinander kommunizieren können. Um mit Quadlet ein Netzwerk 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, plus dem Präfix „systemd-“. Wir können im Abschnitt [Netzwerk]
der Datei explizit einen Namen oder eine andere netzwerkspezifische Option angeben. Im folgenden Beispiel geben wir das Subnetz und die Gateway-Adresse für das Netzwerk an (dies entspricht der Ausführung von podman mit --subnet 192.168.30.0/24
und --gateway 192.168.30.1).
Optionen):
[Unit]
Description=MariaDB Network
[Network]
Subnet=192.168.30.0/24
Gateway=192.168.30.1
Wir 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 Containereinheit. Der zuvor definierte MariaDB-Container wird 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
Network=mariadb.network
Erstellen eines Stapels mit mehreren Containern
Wir haben einen Container, auf dem unser MariaDB-Server läuft. Um eine einfache Möglichkeit zur Verwaltung unserer Datenbank über eine Weboberfläche hinzuzufügen, können wir einen Container basierend auf phpMyAdmin erstellen. Damit die beiden Container miteinander kommunizieren können, müssen wir sie in dasselbe Netzwerk einbinden.
Da der phpMyAdmin-Container, um ordnungsgemäß zu funktionieren, erfordert, dass der MariaDB-Server aktiv ist und läuft, können wir diese Abhängigkeit wie für jeden anderen Systemd-Dienst mit Requires
und deklarieren Nach
-Optionen im Abschnitt „[Einheit]“. Ersteres stellt eine feste Abhängigkeit von dem als Wert übergebenen Dienst her; Letzteres stellt sicher, dass unser Service danach beginnt. Wenn Sie mit Systemd nicht vertraut sind, können Sie sich übrigens unser Tutorial zum Erstellen eines Systemd-Dienstes ansehen. So sieht die Containereinheit 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 dem podman -p
(--publish
) entspricht: Sie wird verwendet um einen Host-Port einem Container-Port 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
bereitgestellt: Dieser wird verwendet, um die Adresse des Datenbankservers anzugeben (in diesem Fall haben wir den MariaDB-Containernamen verwendet, der in aufgelöst wird). tatsächliche Adresse). Beachten Sie, dass wir den Namen des MariaDB-Containers als Wert der Umgebungsvariablen verwendet haben, nicht den Namen der „.container“-Einheit. Um unser neues Setup noch einmal zu starten, führen wir Folgendes aus:
$ systemd --user daemon-reload
Anschließend können wir den generierten Dienst „phpmyadmin-service“ starten, der wiederum den phpMyAdmin-Container ausführt. Da eine starke Abhängigkeit von MariaDB besteht, wird letztere automatisch ebenfalls gestartet. Wir sollten phpMyadmin unter der Adresse „localhost:8080“ erreichen können. Zum Anmelden können wir die in der MariaDB-Containereinheit angegebenen Anmeldeinformationen verwenden:
Abschließende Gedanken
In diesem Tutorial haben wir gelernt, wie man mit Quadlet Podman-Container, Volumes und Netzwerke unter Systemd erstellt und ausführt. Anstatt Multi-Container-Stacks in einer einzigen Datei zu definieren, wie wir es bei der Verwendung von Docker-Compose tun, definieren wir mit Quadlet Container, Volumes und Netzwerke mithilfe dedizierter Systemd-Einheiten.