Einführung
In diesem Lab lernen Sie, wie Sie eine mehrschichtige Webanwendung mit Podman auf Red Hat Enterprise Linux (RHEL) bereitstellen. Sie erstellen eine Komplettlösung, indem Sie einen MariaDB-Datenbankcontainer als Backend und einen Apache-Webserver-Container als Frontend bereitstellen. Diese praktische Erfahrung führt Sie durch die wesentlichen Schritte der containerisierten Anwendungsbereitstellung, von der ersten Konfiguration bis zur öffentlichen Zugänglichkeit des Dienstes.
Sie beginnen mit dem Ausführen eines MariaDB-Containers und dessen Konfiguration beim Start mit Umgebungsvariablen. Als Nächstes konfigurieren Sie persistenten Speicher, um die Datenbeständigkeit für die Datenbank sicherzustellen, und erstellen ein benutzerdefiniertes Netzwerk für die Containerkommunikation. Anschließend stellen Sie den Apache-Webserver bereit, legen dessen Port offen, um die Konnektivität zu testen, und lernen schließlich, wie Sie den Container als systemd-Dienst für einen robusten, automatisierten Betrieb verwalten.
Ausführen eines MariaDB-Datenbank-Containers mit Umgebungsvariablen
In diesem Schritt lernen Sie, wie Sie eine containerisierte Anwendung ausführen und beim Start mithilfe von Umgebungsvariablen konfigurieren. Dies ist eine grundlegende Fähigkeit im Containermanagement, die flexible und sichere Bereitstellungen ermöglicht. Wir verwenden das offizielle MariaDB-Image als Beispiel, da es mehrere Konfigurationsparameter zur Initialisierung einer Datenbank benötigt.
Stellen Sie zunächst sicher, dass Sie sich im richtigen Arbeitsverzeichnis befinden. Alle Arbeiten für dieses Lab werden im Verzeichnis ~/project durchgeführt.
cd ~/project
Bevor Sie einen Container ausführen, ist es gute Praxis, das Image explizit aus der Registry zu ziehen. Dies stellt sicher, dass Sie die richtige Version lokal haben. Wir verwenden für dieses Lab das Image mariadb:10.6, um die Konsistenz zu gewährleisten.
podman pull mariadb:10.6
Wählen Sie das Image mariadb:10.6 aus der Docker-Registry.
Sie sollten eine Ausgabe sehen, die anzeigt, dass das Image heruntergeladen und extrahiert wird.
10.6: Pulling from library/mariadb
...
Status: Downloaded newer image for mariadb:10.6
docker.io/library/mariadb:10.6
Jetzt können Sie den MariaDB-Container ausführen. Der Befehl podman run erstellt und startet einen neuen Container. Wir verwenden mehrere Flags:
-d: Führt den Container im Detached-Modus (im Hintergrund) aus.--name mariadb_server: Weist unserem Container einen einprägsamen Namen zu.-e VARIABLE=value: Setzt eine Umgebungsvariable innerhalb des Containers. Das MariaDB-Image verwendet diese, um die Datenbank beim ersten Start zu konfigurieren.
Führen Sie den folgenden Befehl aus, um Ihren MariaDB-Container zu starten. Wir setzen das Root-Passwort und erstellen außerdem eine neue Datenbank namens webappdb mit dem dedizierten Benutzer webappuser.
podman run -d \
--name mariadb_server \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
mariadb:10.6
Der Befehl gibt eine lange Container-ID aus, die bestätigt, dass der Container erstellt wurde.
a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
Um zu überprüfen, ob der Container läuft, verwenden Sie den Befehl podman ps.
podman ps
Sie sollten mariadb_server in der Liste der laufenden Container sehen.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" 15 seconds ago Up 14 seconds 3306/tcp mariadb_server
Schließlich überprüfen wir die Container-Logs, um sicherzustellen, dass die Datenbank mithilfe der von uns bereitgestellten Umgebungsvariablen korrekt initialisiert wurde.
podman logs mariadb_server
Scrollen Sie durch die Logs. Sie suchen nach einer Zeile, die anzeigt, dass der Server bereit für Verbindungen ist, was einen erfolgreichen Start bestätigt. Die Ausgabe ist lang, aber eine wichtige Erfolgsmeldung am Ende sieht so aus:
...
2024-05-20 10:30:00+00:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/
...
2024-05-20 10:30:15+00:00 [Note] mariadbd: ready for connections.
Version: '10.6.x-MariaDB-1:10.6.x+maria~ubu2004' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
Sie haben erfolgreich einen MariaDB-Container mit Umgebungsvariablen gestartet und konfiguriert.
Konfigurieren von persistentem Speicher für den MariaDB-Container
In diesem Schritt lernen Sie, wie Sie persistenten Speicher für einen Container konfigurieren. Standardmäßig werden alle Daten, die innerhalb eines Containers erstellt werden, in einer beschreibbaren Schicht gespeichert, die an den Lebenszyklus des Containers gebunden ist. Wenn Sie den Container entfernen, gehen alle diese Daten verloren. Für zustandsbehaftete Anwendungen wie Datenbanken ist dies nicht ideal. Um dies zu lösen, verwenden wir Podman-Volumes oder Bind-Mounts, um die Daten auf dem Host-Dateisystem zu speichern, unabhängig vom Container.
Zuerst müssen wir den Container entfernen, den wir im vorherigen Schritt erstellt haben, da wir ihn mit einer neuen Speicherkonfiguration neu starten werden.
Stoppen Sie den laufenden mariadb_server-Container:
podman stop mariadb_server
Sie sehen den Namen des Containers als Ausgabe, was bestätigt, dass der Befehl empfangen wurde.
mariadb_server
Entfernen Sie nun den gestoppten Container:
podman rm mariadb_server
Auch hier wird der Name des Containers zurückgegeben.
mariadb_server
Als Nächstes erstellen Sie ein Verzeichnis auf Ihrem Host-Rechner innerhalb des Verzeichnisses ~/project. Dieses Verzeichnis enthält die MariaDB-Datenbankdateien.
mkdir ~/project/mariadb_data
Bei der Verwendung von Podman im Rootless-Modus müssen wir die korrekten Berechtigungen für das gemountete Verzeichnis festlegen. Der MariaDB-Container wird als bestimmter Benutzer (UID 999) ausgeführt, daher müssen wir sicherstellen, dass das Verzeichnis zugänglich ist. Wir verwenden das Flag --userns=keep-id und legen die entsprechenden Berechtigungen fest:
chmod 755 ~/project/mariadb_data
Führen Sie nun den MariaDB-Container erneut aus. Dieser Befehl ähnelt dem aus dem vorherigen Schritt, jedoch mit dem Zusatz des Flags -v und --userns=keep-id, um die Benutzer-Namespace-Zuordnung ordnungsgemäß zu handhaben. Das Flag -v mountet das Verzeichnis ~/project/mariadb_data von Ihrem Host in das Verzeichnis /var/lib/mysql innerhalb des Containers, wo MariaDB seine Daten speichert. Wir verwenden $(pwd)/mariadb_data, um den erforderlichen absoluten Pfad für den podman-Befehl bereitzustellen.
podman run -d \
--name mariadb_server \
--userns=keep-id \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
-v $(pwd)/mariadb_data:/var/lib/mysql:Z \
mariadb:10.6
Das Suffix :Z beim Volume-Mount weist Podman an, den Inhalt mit einem privaten, unshared Label neu zu kennzeichnen, was für die SELinux-Kompatibilität wichtig ist.
Nachdem der Container gestartet wurde, können Sie überprüfen, ob die Daten auf Ihrem Host-Rechner gespeichert werden. Listen Sie den Inhalt des Verzeichnisses ~/project/mariadb_data auf.
ls -l ~/project/mariadb_data
Da die Datenbank-Engine des Containers initialisiert wurde, sehen Sie mehrere Dateien und Verzeichnisse, die innerhalb von ~/project/mariadb_data erstellt wurden. Dies bestätigt, dass Ihre Daten jetzt persistent sind. Selbst wenn Sie den Container entfernen, bleiben diese Daten erhalten.
total 110632
-rw-rw---- 1 labex labex 16384 May 20 10:45 aria_log.00000001
-rw-rw---- 1 labex labex 52 May 20 10:45 aria_log_control
-rw-rw---- 1 labex labex 983 May 20 10:45 ib_buffer_pool
-rw-rw---- 1 labex labex 12582912 May 20 10:45 ibdata1
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile0
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile1
drwx------ 2 labex labex 4096 May 20 10:45 mysql
drwx------ 2 labex labex 4096 May 20 10:45 performance_schema
drwx------ 2 labex labex 4096 May 20 10:45 sys
drwx------ 2 labex labex 4096 May 20 10:45 webappdb
Sie haben Ihren MariaDB-Container erfolgreich so konfiguriert, dass er persistenten Speicher verwendet, wodurch sichergestellt wird, dass Ihre Datenbankdaten Container-Neustarts und -Entfernungen überleben.
Erstellen eines benutzerdefinierten Netzwerks und Bereitstellen eines Apache Webservers
In diesem Schritt erstellen Sie ein benutzerdefiniertes Netzwerk für Ihre Container und stellen einen Apache-Webserver bereit. Während Podman ein Standardnetzwerk bereitstellt, ist die Verwendung benutzerdefinierter Netzwerke eine Best Practice. Sie bieten eine bessere Isolation und, was am wichtigsten ist, ermöglichen die automatische DNS-Auflösung zwischen Containern. Dadurch können Container über ihre Namen miteinander kommunizieren, was zuverlässiger ist als die Verwendung von IP-Adressen, die sich ändern können.
Zuerst erstellen wir ein benutzerdefiniertes Bridge-Netzwerk für unsere Anwendung. Wir nennen es webapp-network.
podman network create webapp-network
Der Befehl gibt den Namen des neu erstellten Netzwerks aus.
webapp-network
Sie können alle Podman-Netzwerke auflisten, um zu bestätigen, dass Ihres erfolgreich erstellt wurde.
podman network ls
Sie sollten webapp-network in der Liste zusammen mit den Standardnetzwerken sehen.
NETWORK ID NAME DRIVER SCOPE
...
f1e2d3c4b5a6 webapp-network bridge local
...
Als Nächstes müssen wir unseren mariadb_server-Container in diesem neuen Netzwerk neu erstellen. Aufgrund der Netzwerk-Backend-Konfiguration in dieser Umgebung können wir einen bestehenden Container nicht mit einem neuen Netzwerk verbinden. Stattdessen stoppen und erstellen wir den Container mit der neuen Netzwerkkonfiguration neu.
Stoppen Sie den laufenden mariadb_server-Container:
podman stop mariadb_server
Entfernen Sie den gestoppten Container:
podman rm mariadb_server
Erstellen Sie nun den MariaDB-Container mit dem neuen Netzwerk neu. Dieser Befehl ähnelt dem aus dem vorherigen Schritt, jedoch mit dem Zusatz des Flags --network webapp-network:
podman run -d \
--name mariadb_server \
--network webapp-network \
--userns=keep-id \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
-v $(pwd)/mariadb_data:/var/lib/mysql:Z \
mariadb:10.6
Lassen Sie uns nun unseren Webserver bereitstellen. Wir verwenden das offizielle Apache httpd-Image. Erstellen Sie zuerst ein Verzeichnis auf dem Host, um die Dateien Ihrer Website zu speichern.
mkdir ~/project/webapp_content
Erstellen Sie eine einfache index.html-Datei in diesem neuen Verzeichnis. Dies ist die Homepage unserer Webanwendung.
echo "<h1>Welcome to My Web App</h1>" > ~/project/webapp_content/index.html
Legen Sie die korrekten Berechtigungen für das Webapp-Inhaltsverzeichnis fest, um sicherzustellen, dass der Apache-Container auf die Dateien zugreifen kann:
chmod 755 ~/project/webapp_content
Führen Sie nun den Apache httpd-Container aus. Wir verbinden ihn mit unserem webapp-network und mounten das Verzeichnis webapp_content als Volume. Dies stellt sicher, dass der Webserver die von uns gerade erstellte Datei index.html bereitstellen kann.
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
httpd:2.4
Lassen Sie uns die Optionen aufschlüsseln:
--network webapp-network: Verbindet den neuen Container mit unserem benutzerdefinierten Netzwerk.-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z: Dies mountet unser lokales Verzeichniswebapp_contentin den Container unter/usr/local/apache2/htdocs/, dem Standardverzeichnis, aus dem Apache Dateien bereitstellt. Das Suffix:Zweist Podman an, den Inhalt mit einem privaten, unshared Label für die SELinux-Kompatibilität neu zu kennzeichnen.
Überprüfen Sie, ob beide Container ausgeführt werden.
podman ps
Sie sollten jetzt sowohl mariadb_server als auch web_server in der Liste der laufenden Container sehen.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a3f46c0ab3a docker.io/library/mariadb:10.6 mariadbd 29 seconds ago Up 29 seconds 3306/tcp mariadb_server
da5d52ce9c41 docker.io/library/httpd:2.4 httpd-foreground 7 seconds ago Up 7 seconds 80/tcp web_server
Beide Container befinden sich jetzt im selben benutzerdefinierten Netzwerk und können über den Namen miteinander kommunizieren.
Webserver-Port freigeben und Konnektivität testen
In diesem Schritt lernen Sie, wie Sie den Port eines Containers für den Host-Rechner freigeben, wodurch der Dienst von außerhalb des isolierten Netzwerks des Containers zugänglich wird. Unser Apache-Webserver läuft, aber wir können noch nicht von unserem Host-Browser oder der Befehlszeile darauf zugreifen. Wir werden dies beheben, indem wir den Port des Containers veröffentlichen.
Port-Mappings werden definiert, wenn ein Container erstellt wird. Daher müssen wir zuerst den web_server-Container, den wir im vorherigen Schritt erstellt haben, stoppen und entfernen. Machen Sie sich keine Sorgen um den Website-Inhalt; er ist sicher im Verzeichnis ~/project/webapp_content auf unserem Host, da wir ein Bind-Mount verwendet haben.
Zuerst stoppen Sie den Container:
podman stop web_server
web_server
Entfernen Sie als Nächstes den gestoppten Container:
podman rm web_server
web_server
Nun werden wir den web_server-Container erneut ausführen, aber dieses Mal fügen wir das Flag -p (oder --publish) hinzu, um einen Port vom Host auf einen Port im Container abzubilden. Wir werden Port 8080 auf dem Host auf Port 80 (dem Standard-HTTP-Port) innerhalb des Containers abbilden.
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
-p 8080:80 \
httpd:2.4
Das neue Flag -p 8080:80 weist Podman an, den gesamten Datenverkehr von Port 8080 auf dem Host an Port 80 innerhalb des web_server-Containers weiterzuleiten.
Lassen Sie uns mit podman ps überprüfen, ob der Container läuft und der Port korrekt abgebildet ist.
podman ps
Beachten Sie die Spalte PORTS für den web_server-Container. Sie zeigt jetzt die Abbildung von 0.0.0.0:8080 auf 80/tcp an, was darauf hindeutet, dass der Port erfolgreich freigegeben wurde.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5d4e3f2a1b6 httpd:2.4 "httpd-foreground" 10 seconds ago Up 9 seconds 0.0.0.0:8080->80/tcp web_server
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" 25 minutes ago Up 25 minutes 3306/tcp mariadb_server
Schließlich testen wir die Konnektivität von unserem Host-Rechner aus mit dem Befehl curl. Dieser sendet eine HTTP-Anfrage an localhost auf Port 8080.
curl http://localhost:8080
Sie sollten den HTML-Inhalt aus Ihrer index.html-Datei als Ausgabe sehen, was bestätigt, dass Ihr Webserver jetzt vom Host aus zugänglich ist.
<h1>Welcome to My Web App</h1>
Sie haben Ihren containerisierten Webserver erfolgreich für den Host-Rechner freigegeben, ein entscheidender Schritt, um Anwendungen für Benutzer verfügbar zu machen.
Den Webserver-Container als systemd-Dienst verwalten
In diesem letzten Schritt lernen Sie, wie Sie einen Container so konfigurieren, dass er automatisch startet, um sicherzustellen, dass Ihr Dienst gegen Abstürze oder Systemneustarts widerstandsfähig ist. Auf einem Standard-Red Hat Enterprise Linux-System ist systemd das primäre Werkzeug zur Verwaltung von Diensten. Die Podman-Umgebung in diesem Lab verwendet jedoch systemd nicht, um Container direkt zu verwalten.
Stattdessen werden wir das gleiche Ergebnis – automatische Neustarts des Dienstes – mit den integrierten Restart-Richtlinien von Podman erreichen. Dies ist die Standardmethode, die für Container geeignet ist, um sicherzustellen, dass ein Container automatisch vom Podman-Daemon gestartet wird. Wir werden unseren web_server so konfigurieren, dass er immer neu gestartet wird, wenn er aus irgendeinem Grund anhält.
Zuerst müssen wir den bestehenden Container entfernen, da Neustartrichtlinien nur angewendet werden können, wenn ein Container erstellt wird.
Stoppen Sie den web_server-Container:
podman stop web_server
web_server
Und jetzt entfernen Sie ihn:
podman rm web_server
web_server
Als Nächstes erstellen Sie den web_server-Container mit der gleichen Konfiguration wie zuvor neu, aber fügen Sie das Flag --restart always hinzu. Dieses Flag weist den Podman-Daemon an, den Container zu überwachen und ihn neu zu starten, wenn er jemals beendet wird.
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
-p 8080:80 \
--restart always \
httpd:2.4
Der Container startet wie gewohnt. Um zu bestätigen, dass die Neustartrichtlinie aktiv ist, können Sie die Konfiguration des Containers untersuchen.
podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'
Der Befehl sollte always zurückgeben, was bestätigt, dass die Richtlinie festgelegt ist.
always
Lassen Sie uns nun demonstrieren, wie die Neustartrichtlinie funktioniert, indem wir den Container manuell neu starten, um zu simulieren, was nach einem Systemneustart oder einem Containerfehler passieren würde.
Überprüfen wir zuerst die aktuelle Konfiguration der Neustartrichtlinie:
podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'
Dies sollte always anzeigen, was bestätigt, dass unsere Neustartrichtlinie konfiguriert ist.
always
Testen wir nun den manuellen Neustart, um die Wiederherstellung nach einem Fehler zu simulieren:
podman start web_server
web_server
Überprüfen Sie, ob der Container läuft:
podman ps
Sie sollten beide Container mit der Neustartrichtlinie sehen:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e7f6g5h4i3j2 httpd:2.4 "httpd-foreground" About a minute ago Up 5 seconds 0.0.0.0:8080->80/tcp web_server
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" About an hour ago Up About an hour 3306/tcp mariadb_server
Bestätigen Sie abschließend, dass der Dienst zugänglich ist:
curl http://localhost:8080
<h1>Welcome to My Web App</h1>
Verständnis der Neustartrichtlinien:
Die von Ihnen konfigurierte Richtlinie --restart always stellt sicher, dass:
- Der Container automatisch neu gestartet wird, wenn er unerwartet beendet wird
- Der Container automatisch gestartet wird, wenn der Podman-Dienst startet (z. B. nach einem Systemneustart)
- Dies bietet Ausfallsicherheit für Produktionsbereitstellungen
Hinweis: In einigen Lab-Umgebungen kann das automatische Neustartverhalten je nach Podman-Konfiguration und ob der Podman-Systemdienst ausgeführt wird, variieren. Das wichtigste Lernziel ist das Verständnis, wie Neustartrichtlinien für Produktionsbereitstellungen konfiguriert werden.
Sie haben Ihren Container erfolgreich so konfiguriert, dass er wie ein Dienst verwaltet wird, wodurch sichergestellt wird, dass er automatisch verfügbar bleibt. Dies schließt das grundlegende Lifecycle-Management einer containerisierten Anwendung ab.
Zusammenfassung
In diesem Lab haben Sie den grundlegenden Prozess der Bereitstellung einer Webanwendung mit mehreren Containern auf RHEL mit Podman gelernt. Sie begannen mit der Ausführung eines MariaDB-Datenbank-Containers und konfigurierten seinen Anfangszustand – einschließlich des Root-Passworts, einer neuen Datenbank und eines dedizierten Benutzers – durch Übergabe von Umgebungsvariablen zur Laufzeit. Anschließend konfigurierten Sie persistenten Speicher für den Datenbank-Container, um sicherzustellen, dass kritische Daten über Container-Neustarts hinweg erhalten bleiben.
Um den Anwendungs-Stack zu vervollständigen, erstellten Sie ein benutzerdefiniertes Netzwerk, um eine sichere, isolierte Kommunikation zwischen den Containern zu ermöglichen. Sie stellten einen Apache-Webserver-Container in diesem Netzwerk bereit und gaben seinen Port frei, um externen Benutzerzugriff zu ermöglichen. Schließlich integrierten Sie den Webserver-Container in systemd und verwalteten ihn als Systemdienst, um sicherzustellen, dass er automatisch beim Booten startet und zuverlässig läuft, was ein produktionsreifes Bereitstellungsmuster demonstriert.



