{"id":4032,"date":"2025-01-27T07:00:00","date_gmt":"2025-01-27T06:00:00","guid":{"rendered":"https:\/\/www.my-it-brain.de\/wordpress\/?p=4032"},"modified":"2025-09-08T10:24:52","modified_gmt":"2025-09-08T08:24:52","slug":"einfuehrung-in-den-rhel-image-mode","status":"publish","type":"post","link":"https:\/\/www.my-it-brain.de\/wordpress\/einfuehrung-in-den-rhel-image-mode\/","title":{"rendered":"Einf\u00fchrung in den RHEL image mode"},"content":{"rendered":"\n<p>Dieses Tutorial f\u00fchrt in den <em>RHEL image mode<\/em> ein und zeigt, wie ein solches Image in einer virtuellen Maschine (VM) installiert werden kann. Es wird ebenfalls gezeigt, wie ein installiertes Image aktualisiert und bei Bedarf zur\u00fcckgerollt werden kann.<\/p>\n\n\n\n<p>W\u00e4hrend diese Einf\u00fchrung in Deutsch gehalten ist, liegen die Dokumentation und weitere verwendete Quellen ausschlie\u00dflich in englischer Sprache vor.<\/p>\n\n\n\n<p>Das Tutorial richtet sich in erster Linie an Sysadmins, die bereits Erfahrung mit dem Betrieb von RHEL oder einer verwandten Enterprise Linux Distribution haben. Es bietet keine allgemeine Einf\u00fchrung in die Installation und den Betrieb von Red Hat Enterprise Linux.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Zum Inhalt<\/h2>\n\n\n\n<p>Die folgende Liste bietet einen \u00dcberblick \u00fcber den Inhalt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#what-is-image-mode\">Was ist der RHEL image mode?<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#consolidate\">Konsolidierung von Bereitstellungsprozessen<\/a><\/li>\n\n\n\n<li><a href=\"#immutable\">Immutable RHEL<\/a><\/li>\n\n\n\n<li><a href=\"#declare\">Deklarative Konfiguration des Betriebssystems<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#voraussetzungen\">Voraussetzungen<\/a><\/li>\n\n\n\n<li><a href=\"#lab\">Meine Laborumgebung<\/a><\/li>\n\n\n\n<li><a href=\"#create-bootc-image\">RHEL Bootc Image erstellen<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#containerfile\">Containerfile<\/a><\/li>\n\n\n\n<li><a href=\"#build\">Build<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#registry-login\">Login registry.redhat.io<\/a><\/li>\n\n\n\n<li><a href=\"#create-image\">Image erstellen<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#test\">Test<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#zwischenfazit\">Zwischenfazit<\/a><\/li>\n\n\n\n<li><a href=\"#iso-bootc-image\">ISO-Image mit dem bootc-image-builder erstellen<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#user-password-ssh\">Benutzer, Passwort und SSH-Schl\u00fcssel hinzuf\u00fcgen<\/a><\/li>\n\n\n\n<li><a href=\"#podman-image-scp\">Das Container-Image in den passenden Benutzerkontext kopieren<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#option-1\">M\u00f6glichkeit 1<\/a><\/li>\n\n\n\n<li><a href=\"#option-2\">M\u00f6glichkeit 2<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#bootc-image-builder\">Der bootc-image-builder in Aktion<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#offline-install\">Offline-Installation mit dem RHEL image mode<\/a><\/li>\n\n\n\n<li><a href=\"#fazit\">Fazit nach der Installation von RHEL image mode<\/a><\/li>\n\n\n\n<li><a href=\"#update-rollback\">Systemupdate und Rollback<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#image-update-change\">Bootc Image Installation aktualisieren bzw. Konfiguration \u00e4ndern<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#image-update\">Aktualisierung des RHEL Bootc Image<\/a><\/li>\n\n\n\n<li><a href=\"#bootc-switch\">Das zu verwendende Image aus dem System heraus wechseln<\/a><\/li>\n\n\n\n<li><a href=\"#auto-update\">Automatische Aktualisierungen und wie man sie deaktivieren kann<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#rollback\">Rollback<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#ende\">Ende<\/a><\/li>\n\n\n\n<li><a href=\"#sources\">Quellen und weiterf\u00fchrende Links<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-image-mode\">Was ist der RHEL image mode?<\/h2>\n\n\n\n<p><em>RHEL image mode<\/em> ist eine <a href=\"https:\/\/access.redhat.com\/solutions\/21101\">Technology Preview<\/a> und stellt eine neue Methode dar, um RHEL zu konfigurieren, installieren bzw. deployen und zu verwalten.<\/p>\n\n\n\n<p>Durch Nutzung von Container-Tools wird ein Container-Image erstellt, welches neben dem RHEL-Userland auch den RHEL-Kernel, Boot Loader, Firmware und Treiber umfasst. Dieses RHEL-Container-Image (auch RHEL Bootc Image genannt) kann anschlie\u00dfend genutzt werden, um RHEL im Datacenter oder in der Cloud &#8211; auf Bare-Metal-Servern, virtuellen Maschinen oder Edge-Ger\u00e4ten zu deployen. Das RHEL-Container-Image kann direkt als Container ausgef\u00fchrt werden, um die Funktionalit\u00e4t zu testen. F\u00fcr das Deployment kann das Container-Image in ein Disk-Image f\u00fcr die entsprechende Zielplattform konvertiert werden. Ein installiertes oder als Disk-Image provisioniertes System l\u00e4uft anschlie\u00dfend nativ auf der Hardware bzw. in der virtuellen Maschine und wird dort nicht als Container ausgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"consolidate\">Konsolidierung von Bereitstellungsprozessen<\/h3>\n\n\n\n<p>In vielen Unternehmen kommen heute neben klassischen virtuellen Maschinen auch Linux-Container zum Einsatz. <em>RHEL image mode<\/em> bietet die M\u00f6glichkeit, Bereitstellungsprozesse zu konsolidieren, indem f\u00fcr die Bereitstellung von RHEL-Images die gleichen Werkzeuge genutzt werden, wie f\u00fcr die Bereitstellung von Container-Images f\u00fcr Anwendungen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"immutable\">Immutable RHEL<\/h3>\n\n\n\n<p>Mit Ausnahme von <code>\/etc<\/code> und <code>\/var<\/code> ist das Wurzel-Dateisystem in <em>RHEL image mode<\/em> immutable (read-only).<\/p>\n\n\n\n<p>Anwendungen und Updates werden durch aktualisierte RHEL-Container-Images verteilt. Ein provisioniertes System l\u00e4dt dazu das aktualisierte Image auf die lokale Festplatte und startet dieses nach einem Neustart. Im Fehlerfall kann durch einen weiteren Neustart einfach das vorherige Image gestartet werden. So k\u00f6nnen fehlgeschlagene Updates einfach zur\u00fcckgerollt werden.<\/p>\n\n\n\n<p>Dies bietet dem Admin die Sicherheit, bei Bedarf zum vorherigen Zustand zur\u00fcckkehren zu k\u00f6nnen, ohne daf\u00fcr auf VM-\/Storage-Snapshots oder andere Mechanismen au\u00dferhalb des Betriebssystems zur\u00fcckgreifen zu m\u00fcssen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"declare\">Deklarative Konfiguration des Betriebssystems<\/h3>\n\n\n\n<p><em>RHEL image mode<\/em> macht es einfach, zu konfigurieren und zu verfolgen, welche Pakete in einem Basis-Image enthalten sind und wann welche Pakete hinzugef\u00fcgt wurden.<\/p>\n\n\n\n<p>Red Hat ver\u00f6ffentlicht in der Container-Registry <code>registry.redhat.io<\/code> <a href=\"https:\/\/catalog.redhat.com\/search?searchType=containers&amp;build_categories_list=Scratch%20image&amp;p=1&amp;product_listings_names=Red%20Hat%20Enterprise%20Linux%2010|Red%20Hat%20Enterprise%20Linux%209\">RHEL Bootc Base Images<\/a>, welche die Basis f\u00fcr eigene Images darstellen. Zu jeder Version wird eine Liste der enthaltenen Pakete ver\u00f6ffentlicht. Diese ist \u00fcber den <a href=\"https:\/\/catalog.redhat.com\">Red Hat Ecosystem Catalog<\/a> einsehbar:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"754\" src=\"https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-03-21-38-37-800x754.png\" alt=\"\" class=\"wp-image-4034\" srcset=\"https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-03-21-38-37-800x754.png 800w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-03-21-38-37-300x283.png 300w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-03-21-38-37-768x724.png 768w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-03-21-38-37-624x588.png 624w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-03-21-38-37.png 960w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Ansicht der Paketliste eines RHEL 9 Bootc Base Image<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Hier ist zu beachten, dass obwohl <code>amd64<\/code> als Architektur ausgew\u00e4hlt wurde, die Liste Pakete aller verf\u00fcgbaren Architekturen zeigt. Nat\u00fcrlich sind im Basis-Image nicht 2302 Pakete enthalten. Die Filterm\u00f6glichkeiten und die Ergebnisliste zeigen leider unerwartete Ergebnisse. Ich habe dies bereits intern gemeldet und hoffe, dass sich bald jemand der Sache annimmt.<\/p>\n\n\n\n<p>Das in obiger Abbildung gezeigte Image enth\u00e4lt f\u00fcr die <code>amd64<\/code>-Architektur 441 Pakete. Vergleiche ich dies mit zwei meiner RHEL 9 Installationen, die auf der Minimalinstallation basieren, so umfassen diese 591 bzw. 510 Pakete. Der Vergleich hinkt allerdings, da ich auf den <em>RHEL package mode<\/em> Installationen bereits weitere Software nachinstalliert habe. Ich bin jedoch erfreut, dass das Basis-Image nicht mehr Pakete als eine Minimalinstallation enth\u00e4lt.<\/p>\n\n\n\n<p>Pakete, die zus\u00e4tzlich hinzugef\u00fcgt werden sollen, werden im Containerfile aufgef\u00fchrt, welches \u00fcblicherweise einer Versionskontrolle unterliegt. \u00c4nderungen k\u00f6nnen so jederzeit nachvollzogen werden.<\/p>\n\n\n\n<p>Weitere Informationen bietet das Kapitel 1 in <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html-single\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/index\">Using image mode for RHEL to build, deploy, and manage operating systems<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"voraussetzungen\">Voraussetzungen<\/h2>\n\n\n\n<p>Um die in diesem Tutorial gezeigten Schritte selbst ausf\u00fchren zu k\u00f6nnen, werden folgende Dinge ben\u00f6tigt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ein registriertes RHEL 9 System\n<ul class=\"wp-block-list\">\n<li>mit einer beliebigen <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/potenzielle-mehrwerte-einer-red-hat-enterprise-linux-subscription\/\" data-type=\"post\" data-id=\"3218\">RHEL Subskription<\/a>,<\/li>\n\n\n\n<li>dem installierten Meta-Paket <code>container-tools<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"https:\/\/access.redhat.com\/RegistryAuthentication\">Zugriff auf <code>registry.redhat.io<\/code><\/a><\/li>\n\n\n\n<li>Eine virtuelle Maschine oder einen Rechner, auf dem RHEL image mode installiert werden kann<\/li>\n<\/ul>\n\n\n\n<p>Falls ihr gerade keine geeignete Laborumgebung zur Verf\u00fcgung habt, k\u00f6nnt ihr den Image Mode auch in diesen interaktiven Labs ausprobieren:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.redhat.com\/en\/introduction-to-image-mode-for-red-hat-enterprise-linux-interactive-lab\">Introduction to image mode for Red Hat Enterprise Linux<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/red.ht\/image-mode-2\">Day 2 operations with image mode for Red Hat Enterprise Linux<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"lab\">Meine Laborumgebung<\/h2>\n\n\n\n<p>Meine Laborumgebung besteht aus zwei virtuellen Maschinen, welche auf einem Laptop ausgef\u00fchrt werden. Beide VMs verf\u00fcgen \u00fcber 2 vCPU, 8 GB RAM und 40 GB Speicher.<\/p>\n\n\n\n<p>Auf VM 1 werden folgende T\u00e4tigkeiten ausgef\u00fchrt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Erstellung und Ausf\u00fchrung einer einfachen Container-Registry<\/li>\n\n\n\n<li>Erstellung und Pflege eines oder mehrerer <code>rhel-bootc<\/code>-Container-Images<\/li>\n\n\n\n<li>Erstellung von Disk-Images<\/li>\n<\/ul>\n\n\n\n<p>Anhand von VM 2 werden folgende Dinge demonstriert:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Installation von <em>RHEL image mode<\/em><\/li>\n\n\n\n<li>Aktualisierung der Installation<\/li>\n\n\n\n<li>Wechsel des verwendeten Images<\/li>\n\n\n\n<li>Rollback<\/li>\n<\/ul>\n\n\n\n<p>Die in diesem Tutorial verwendeten Containerfiles, Dateien und Skripte habe ich in einem Git-Repository gesammelt. F\u00fchlt euch frei, die dortigen Dateien auf eigene Gefahr f\u00fcr eigene Versuche zu verwenden. Repository-URL: <a href=\"https:\/\/github.com\/tronde\/image-mode-demo\">https:\/\/github.com\/tronde\/image-mode-demo<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"create-bootc-image\">RHEL Bootc Image erstellen<\/h2>\n\n\n\n<p>Dieser Abschnitt wurde aus Kapitel 2 der Dokumentation <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html-single\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/index\">Using image mode for RHEL to build, deploy, and manage operating systems<\/a> abgeleitet. In ihm wird das RHEL-Container-Image erstellt, welches im n\u00e4chsten Schritt f\u00fcr das Deployment in einer VM vorbereitet wird. Dieser Abschnitt behandelt folgende Schritte:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>Containerfile(5)<\/code> erstellen<\/li>\n\n\n\n<li>Container-Image mit <code>podman-build(1)<\/code> erstellen<\/li>\n\n\n\n<li>Container-Image auf dem Build-System testen<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"containerfile\">Containerfile<\/h3>\n\n\n\n<p>Mit dem folgenden <code>Containerfile(5)<\/code> wird konfiguriert, wie das <em>RHEL Bootc Base Image<\/em> &#8218;<code>rhel-bootc:9.5<\/code>&#8218; angepasst werden soll:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat Containerfile \nFROM registry.redhat.io\/rhel9\/rhel-bootc:9.5\nADD index.html \/var\/www\/html\/index.html\nRUN dnf -y install httpd \\\n    openssh-server \\\n    bind-utils \\\n    net-tools \\\n    chrony \\\n    vim-enhanced \\\n    man-pages \\\n    strace \\\n    lsof \\\n    tcpdump \\\n    bash-completion &amp;&amp; \\\n    dnf clean all\nRUN systemctl enable httpd sshd<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Es wird eine <code>index.html<\/code>-Datei hinzugef\u00fcgt<\/li>\n\n\n\n<li>Die installierten Pakete werden aktualisiert<\/li>\n\n\n\n<li>Weitere Pakete werden installiert<\/li>\n\n\n\n<li>Der DNF-Paket-Cache wird entfernt<\/li>\n\n\n\n<li>Die Dienste <code>httpd<\/code> und <code>sshd<\/code> werden aktiviert, damit sie nach dem Boot-Vorgang automatisch starten<\/li>\n<\/ol>\n\n\n\n<p>Die im Containerfile aufgef\u00fchrten Pakete sind eine pers\u00f6nliche Auswahl, die ich gern auf meinen Systemen habe. Ihr k\u00f6nnt hier nat\u00fcrlich die Pakete eurer Wahl eintragen.<\/p>\n\n\n\n<p>F\u00fcr dieses Tutorial installiere ich den Dienst <code>httpd<\/code>. Das von dem Image provisionierte System wird also einen Webserver hosten. Dass ich die <code>index.html<\/code>-Datei ebenfalls dem Image hinzuf\u00fcge, soll mir lediglich den sp\u00e4teren Test in diesem Tutorial vereinfachen. Je nach Aufbau, Inhalt und \u00c4nderungsrate der auszuliefernden Webseite bzw. Webanwendung ist es nicht sinnvoll, diese in das Image zu integrieren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"build\">Build<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"registry-login\">Login registry.redhat.io<\/h4>\n\n\n\n<p>Bevor das erste Container-Image erstellt werden kann, ist eine Anmeldung an der Container-Registry <code>registry.redhat.io<\/code> notwendig:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman login registry.redhat.io\nUsername: alice\nPassword: \nLogin Succeeded!<\/code><\/pre>\n\n\n\n<p>Weitere Unterst\u00fctzung zur Anmeldung bietet: <a href=\"https:\/\/access.redhat.com\/RegistryAuthentication\">Red Hat Container Registry Authentication<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"create-image\">Image erstellen<\/h4>\n\n\n\n<p>Mit dem folgenden Befehl kann nun ein Image aus obigen Containerfile erstellt werden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ time podman build -t localhost\/rhel9.5-bootc:test .\n\u2026\nSuccessfully tagged localhost\/rhel9.5-bootc:test\nc958185aa4c578af37b5bca796c7c5e50a270f7b7de38126c31fa6ab97046f41\n\nreal    2m52.574s\nuser    2m31.787s\nsys     0m59.680s\n$ podman images\nREPOSITORY                                  TAG               IMAGE ID      CREATED         SIZE\nlocalhost\/rhel9.5-bootc  test              c958185aa4c5  40 seconds ago  1.68 GB\nregistry.redhat.io\/rhel9\/rhel-bootc         9.5               7cf5466a7756  2 days ago      1.56 GB<\/code><\/pre>\n\n\n\n<p>Das Container-Image wird unter dem Namen <code>localhost\/rhel9.5-bootc:test<\/code> im lokalen Dateisystem gespeichert.<\/p>\n\n\n\n<p>Der Build-Vorgang dauerte insgesamt knapp 3 Minuten. Darin ist die Zeit zum Herunterladen des Basis-Image <code>registry.redhat.io\/rhel9\/rhel-bootc:9.5<\/code> enthalten. Ist dieses Image bereits vorhanden, dauert der Build-Vorgang nur knapp \u00fcber 1 Minute.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"test\">Test<\/h3>\n\n\n\n<p>Der nun folgende Code-Block zeigt, wie das soeben erstellte Container-Image mit Podman im interaktiven Modus gestartet werden kann. Es wird gepr\u00fcft, ob die <code>index.html<\/code>-Datei vorhanden ist und wie viele Pakete das Image enth\u00e4lt.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman run -it --rm --name mybootc localhost\/rhel9.5-bootc:test \/bin\/bash\nbash-5.1# ls -l \/var\/www\/html\ntotal 4\n-rw-r--r--. 1 root root 342 Jan 11 11:20 index.html\nbash-5.1# rpm -qa | wc -l\n465\nbash-5.1#<\/code><\/pre>\n\n\n\n<p>Als n\u00e4chste teste ich, ob die <code>index.html<\/code>-Datei auch ausgeliefert wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman run -d --rm -p 127.0.0.1:8888:80 --name mybootc localhost\/rhel9.5-bootc:test \nfa9c1f5110cd58c3f28760fb5a5d69cdc4595a5cba2f29ff67f85eaa076204ab\n$ curl http:\/\/127.0.0.1:8888\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"de\"&gt;\n  &lt;head&gt;\n    &lt;meta charset=\"utf-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;Bootc Demo Page&lt;\/title&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n                &lt;p&gt;Diese Seite wird von einem Webserver ausgeliefert, der mit RHEL Bootc Image Mode bereitgestellt wurde.&lt;\/p&gt;\n  &lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p>Test erfolgreich! Die konfigurierte Webseite wird wie erwartet ausgeliefert. Der Container wird mit <code>podman stop mybootc<\/code> gestoppt und der Test ist beendet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"zwischenfazit\">Zwischenfazit<\/h2>\n\n\n\n<p>Bis hier wurde ein Containerfile erstellt, welches das zu verwendende Basis-Image, die zus\u00e4tzlich zu installierenden Pakete und die auszuf\u00fchrenden Dienste definiert. Mit Hilfe dieses Containerfiles und Podman wurde anschlie\u00dfend das Container-Image <code>localhost\/rhel9.5-bootc:test<\/code> erzeugt. Mit einem einfachen Test konnte auf dem Build-System verifiziert werden, dass die <code>index.html<\/code>-Datei wie gew\u00fcnscht ausgeliefert wird.<\/p>\n\n\n\n<p>Das Image enth\u00e4lt keinerlei Passw\u00f6rter oder SSH-Schl\u00fcssel. Es sind somit bisher keinerlei Geheimnisse enthalten, die mit dem Image verloren gehen k\u00f6nnten.<\/p>\n\n\n\n<p>Verglichen mit einer klassischen RHEL-Minimalinstallation, die als Basis f\u00fcr ein <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/gold-images-fuer-kvm-qemu-erstellen\/\">Golden-Image<\/a> dient, konnte der Vorgang deutlich schneller abgeschlossen werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"iso-bootc-image\">ISO-Image mit dem bootc-image-builder erstellen<\/h2>\n\n\n\n<p>Der <code>bootc-image-builder<\/code> ist eine Container-Variante des <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/composing_a_customized_rhel_system_image\/index\">RHEL Image Builder<\/a>. Mit diesem wird in den folgenden Schritten ein ISO-Image aus dem zuvor erstellten Container-Image erzeugt. Mit dem ISO-Image wird anschlie\u00dfend eine Installation in einer VM durchgef\u00fchrt.<\/p>\n\n\n\n<p>Mit dem <code>bootc-image-builder<\/code> k\u00f6nnen auch Disk-Images wie AMI, GCE, QCOW2, RAW und VMDK erzeugt werden. Ich habe mich f\u00fcr ISO entschieden, da dies am vielseitigsten verwendbar ist. Man kann damit VMs unter KVM\/Qemu und VMware genauso installieren, wie Bare-Metal-Server.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"user-password-ssh\">Benutzer, Passwort und SSH-Schl\u00fcssel hinzuf\u00fcgen<\/h3>\n\n\n\n<p>Um sich nach der Installation interaktiv am System anmelden zu k\u00f6nnen, werden dem ISO-Image ein Benutzer mit Passwort und SSH-Schl\u00fcssel hinzugef\u00fcgt. Daf\u00fcr wird die folgende Datei <code>config.toml<\/code> genutzt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat config.toml \n&#91;&#91;customizations.user]]\nname = \"alice\"\npassword = \"changeme\"\nkey = \"ssh-ed25519 AAAAC3NzaC\u2026cr alice@example.com\"\ngroups = &#91;\"wheel\"]<\/code><\/pre>\n\n\n\n<p>Durch Hinzuf\u00fcgen des Benutzers zur Gruppe <code>wheel<\/code> darf dieser privilegierte Kommandos mittels <code>sudo<\/code> ausf\u00fchren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"podman-image-scp\">Das Container-Image in den passenden Benutzerkontext kopieren<\/h3>\n\n\n\n<p>Das Image <code>localhost\/rhel9.5-bootc:test<\/code> wurde mit einem rootless-Benutzer erstellt. Der Befehl im folgenden Abschnitt muss jedoch mit root-Rechten ausgef\u00fchrt werden. Rootful-Podman kann jedoch nicht auf das Image zugreifen, welches wir mit rootless-Podman erstellt haben. Der Vorgang w\u00fcrde fehlschlagen mit der Meldung: <code>Error: localhost\/rhel9.5-bootc:test: image not known<\/code>.<\/p>\n\n\n\n<p>Um dies zu verhindern, gibt es zwei M\u00f6glichkeiten. M\u00f6glichkeit 1 bietet sich an, wenn man das ISO-Image auf dem gleichen System wie das Container-Image erzeugen m\u00f6chte. Hierbei wird das Container-Image einfach in den passenden Benutzerkontext kopiert. Die zweite M\u00f6glichkeit besteht darin, das Container-Image in eine Container-Registry zu <em>pushen<\/em>, aus der es dann im n\u00e4chsten Schritt wieder <em>gepullt<\/em> werden kann.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"option-1\">M\u00f6glichkeit 1<\/h4>\n\n\n\n<p>Das Container-Image wird mit folgendem Befehl aus dem Kontext des Benutzers &#8218;alice&#8216; in den Kontext des Benutzers &#8218;root&#8216; kopiert.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman image scp alice@localhost::rhel9.5-bootc:test\n\u2026\n$ sudo podman images\nREPOSITORY                                    TAG         IMAGE ID      CREATED         SIZE\nlocalhost\/rhel9.5-bootc                       test        fb6237fff684  21 minutes ago  1.68 GB<\/code><\/pre>\n\n\n\n<p>Wird kein Ziel-Benutzer spezifiziert, wird root als Ziel angenommen. Weitere Informationen zur Verwendung dieses Befehls bietet <code>podman-image-scp(1)<\/code> und der Artikel: <a href=\"https:\/\/www.redhat.com\/en\/blog\/podman-transfer-container-images-without-registry\">How Podman can transfer container images without a registry?<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"option-2\">M\u00f6glichkeit 2<\/h4>\n\n\n\n<p>Selbstverst\u00e4ndlich kann das Container-Image auch in einer Container-Registry gespeichert und im root-Kontext von dort wieder heruntergeladen werden. F\u00fcr die sp\u00e4tere Aktualisierung eines installierten <em>RHEL image mode<\/em> Systems ist die Nutzung einer Container-Registry von Vorteil.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.redhat.com\/en\/blog\/simple-container-registry\">How to implement a simple personal\/private Linux container image registry for internal use<\/a> beschreibt die Einrichtung einer einfachen Registry. Ich habe die auszuf\u00fchrenden Schritte in dem Skript <code>create_simple_container_registry.sh<\/code> zusammengefasst. Die zur Ausf\u00fchrung notwendigen Parameter werden in der Datei <code>registry.vars<\/code> konfiguriert. Diese Datei ist bereits mit Standardwerten gef\u00fcllt, die direkt verwendet werden k\u00f6nnen. Installiert und konfiguriert wird die Registry mit dem Kommando:<br><br><code>$ sudo bash create_simple_container_registry.sh<\/code><\/p>\n\n\n\n<p>Ich trage die IP-Adresse und den Hostnamen meiner VM 1 in die Datei <code>\/etc\/hosts<\/code> ein, damit die Namensaufl\u00f6sung funktioniert. Der folgende Code-Block zeigt, wie das Image <code>localhost\/rhel9.5-bootc<\/code> in die Registry gepusht wird.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman login --tls-verify=false vm1.example.com:5000\nUsername: registryuser\nPassword: \nLogin Succeeded!\n$ podman tag localhost\/rhel9.5-bootc:test vm1.example.com:5000\/rhel9.5-bootc:test\n$ podman push --tls-verify=false jkastnin-tpp1-rhel9-podman-1:5000\/rhel9.5-bootc:test\nGetting image source signatures\n\u2026\nWriting manifest to image destination<\/code><\/pre>\n\n\n\n<p>Die Option <code>--tls-verfiy=false<\/code> ist notwendig, da ein selbstsigniertes TLS-Zertifikat verwendet wird. Mit dem folgenden Befehl kann \u00fcberpr\u00fcft werden, ob sich das Image in der Registry befindet.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ curl -k -u registryuser:registrypass https:\/\/vm1.example.com:5000\/v2\/_catalog\n{\"repositories\":&#91;\"rhel9.5-bootc\"]}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"bootc-image-builder\">Der bootc-image-builder in Aktion<\/h3>\n\n\n\n<p>Der folgende Code-Block zeigt, wie mit dem <code>bootc-image-builder<\/code> eine ISO-Datei erzeugt wird, die sich f\u00fcr eine RHEL-Installation in einer Offline-Umgebung eignet. Der Befehl muss mit <code>sudo<\/code> ausgef\u00fchrt werden, da erweiterte Benutzerrechte erforderlich sind.<\/p>\n\n\n\n<p>Da das Container-Image des <code>bootc-image-builder<\/code> noch nicht lokal vorliegt, muss zuerst ein Login bei <code>registry.redhat.io<\/code> erfolgen. Dies wurde weiter oben bereits f\u00fcr den rootless-Benutzer durchgef\u00fchrt, muss f\u00fcr den rootful-Benutzer jedoch wiederholt werden, da Logins nicht zwischen verschiedenen Benutzerkontexten geteilt werden.<\/p>\n\n\n\n<p><em>Achtung:<\/em> Der folgende Befehl funktioniert nur, wenn das Image <code>localhost\/rhel9.5-bootc:test<\/code> f\u00fcr root verf\u00fcgbar ist. Dies kann durch eine der Methoden, die im vorherigen Abschnitt beschrieben wurden, sichergestellt werden. Ich habe in diesem konkreten Fall <a href=\"#option-1\">M\u00f6glichkeit 1<\/a> verwendet.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo podman login registry.redhat.io\nUsername: alice\nPassword: \nLogin Succeeded!\n$ mkdir output\n$ time sudo podman run \\\n&gt; --rm \\\n&gt; -it \\\n&gt; --privileged \\\n&gt; --pull=newer \\\n&gt; --security-opt label=type:unconfined_t \\\n&gt; -v \/var\/lib\/containers\/storage:\/var\/lib\/containers\/storage \\\n&gt; -v $(pwd)\/config.toml:\/config.toml \\\n&gt; -v $(pwd)\/output:\/output \\\n&gt; registry.redhat.io\/rhel9\/bootc-image-builder:latest \\\n&gt; --type iso \\\n&gt; --config \/config.toml \\\n&gt; --local \\\n&gt; localhost\/rhel9.5-bootc:test\n\u2026\nreal    22m31.407s\nuser    0m1.997s\nsys     0m2.049s\n$ ls -lh output\/bootiso\/\ntotal 2.4G\n-rw-r--r--. 1 root root 2.4G Jan 11 14:26 install.iso\n<\/code><\/pre>\n\n\n\n<p>Nun zur Erkl\u00e4rung des Ganzen:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Der Login erfolgt, um das <code>bootc-image-builder<\/code>-Image herunterladen zu k\u00f6nnen<\/li>\n\n\n\n<li>Im Projektverzeichnis wird das Verzeichnis <code>output<\/code> erstellt, welches die ISO-Datei enthalten wird<\/li>\n\n\n\n<li>Nun folgt ein ziemlich langer Aufruf von <code>podman run<\/code>\n<ul class=\"wp-block-list\">\n<li>Falls in <code>registry.redhat.io<\/code> eine neuere Version des <code>bootc-image-builder<\/code> gefunden wird, wird diese heruntergeladen und genutzt<\/li>\n\n\n\n<li><code>bootc-image-builder<\/code> muss mit erh\u00f6hten Rechten ausgef\u00fchrt werden, weshalb die Ausf\u00fchrung mittels <code>sudo<\/code> und die Option <code>--privileged<\/code> erforderlich sind<\/li>\n\n\n\n<li>Ort der <code>config.toml<\/code> und Verzeichnis f\u00fcr das ISO werden dem Container als Volume zug\u00e4nglich gemacht<\/li>\n\n\n\n<li>Mit <code>--type iso<\/code> wird festgelegt, dass eine ISO-Datei erstellt werden soll<\/li>\n\n\n\n<li>Die Option <code>--local<\/code> gibt an, dass das lokal existierende Image <code>localhost\/rhel9.5-bootc.test<\/code> verwendet und dies nicht aus einer Registry geholt werden soll<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>Dass der Vorgang ganze 22 Minuten dauerte, ist den 2 vCPU-Kernen und den 8 GB RAM meiner VM geschuldet. W\u00e4hrend der Arbeitsspeicher gerade ausreichend war, d\u00fcrften weitere CPU-Kerne den Vorgang deutlich beschleunigen.<\/p>\n\n\n\n<p>Das nun erstellte ISO kann zur Installation in VM 2 verwendet werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"offline-install\">Offline-Installation mit dem RHEL image mode<\/h2>\n\n\n\n<p>Das im vorherigen Abschnitt erstellte Disk-Image <code>install.iso<\/code> wird nun verwendet, um VM 2 zu installieren. Die Installation l\u00e4uft wie eine normale unbeaufsichtigte Anaconda-Installation ab.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"592\" data-id=\"4050\" src=\"https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-55-06-1-800x592.png\" alt=\"\" class=\"wp-image-4050\" srcset=\"https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-55-06-1-800x592.png 800w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-55-06-1-300x222.png 300w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-55-06-1-768x568.png 768w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-55-06-1-624x462.png 624w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-55-06-1.png 885w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"592\" data-id=\"4049\" src=\"https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-56-01-800x592.png\" alt=\"\" class=\"wp-image-4049\" srcset=\"https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-56-01-800x592.png 800w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-56-01-300x222.png 300w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-56-01-768x568.png 768w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-56-01-624x462.png 624w, https:\/\/www.my-it-brain.de\/wordpress\/wp-content\/uploads\/2025\/01\/Screenshot-From-2025-01-13-13-56-01.png 885w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n<\/figure>\n\n\n\n<p>In der Datei <code>config.toml<\/code> wurde ein Benutzer mit einem SSH-Schl\u00fcssel spezifiziert, der nun zum Login in das neue System verwendet werden kann.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ ssh -o StrictHostKeyChecking=no alice@vm2.example.com\nWarning: Permanently added 'vm2.example.com' (ED25519) to the list of known hosts.\n\n$ lsblk\nNAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS\nloop0    7:0    0  7.1M  1 loop \nsr0     11:0    1  2.4G  0 rom  \nzram0  251:0    0  7.8G  0 disk &#91;SWAP]\nvda    252:0    0   30G  0 disk \n\u251c\u2500vda1 252:1    0    1G  0 part \/boot\n\u251c\u2500vda2 252:2    0    1G  0 part &#91;SWAP]\n\u2514\u2500vda3 252:3    0   28G  0 part \/var\n                                \/sysroot\/ostree\/deploy\/default\/var\n                                \/etc\n                                \/sysroot\n\n$ $ mount | grep -E '\"\/\"|var|sysroot|etc'\n\/dev\/vda3 on \/sysroot type ext4 (ro,relatime,seclabel)\ncomposefs on \/ type overlay (ro,relatime,seclabel,lowerdir=\/run\/ostree\/.private\/cfsroot-lower::\/sysroot\/ostree\/repo\/objects,redirect_dir=on,metacopy=on)\n\/dev\/vda3 on \/etc type ext4 (rw,relatime,seclabel)\n\/dev\/vda3 on \/sysroot\/ostree\/deploy\/default\/var type ext4 (rw,relatime,seclabel)\n\/dev\/vda3 on \/var type ext4 (rw,relatime,seclabel)\n\n$ less \/usr\/lib\/systemd\/system\/bootc-fetch-apply-updates.service\n&#91;jkastnin@localhost ~]$ systemctl status httpd\n\u25cf httpd.service - The Apache HTTP Server\n     Loaded: loaded (\/usr\/lib\/systemd\/system\/httpd.service; enabled; preset: disabled)\n     Active: active (running) since Tue 2025-01-14 15:29:07 UTC; 28min ago\n       Docs: man:httpd.service(8)\n   Main PID: 829 (httpd)\n\u2026<\/code><\/pre>\n\n\n\n<p>Da ich im Vorfeld keine genaueren Angaben gemacht habe, wurde der Datentr\u00e4ger automatisch partitioniert. Die Installation l\u00e4sst sich durch <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/automatically_installing_rhel\/kickstart-script-file-format-reference_rhel-installer\">Kickstart<\/a>-Dateien steuern. Dazu wird der Inhalt der Kickstart-Datei in die Datei <code>config.toml<\/code> eingef\u00fcgt. Siehe hierzu Kapitel <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/creating-bootc-compatible-base-disk-images-with-bootc-image-builder_using-image-mode-for-rhel-to-build-deploy-and-manage-operating-systems#using-bootc-image-builder-to-build-iso-images-with-a-kickstart-file_creating-bootc-compatible-base-disk-images-with-bootc-image-builder\">4.9.&nbsp;Using bootc-image-builder to build ISO images with a Kickstart file<\/a> in der RHEL-Dokumentation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fazit\">Fazit nach der Installation von RHEL image mode<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mit rootless <code>podman<\/code> wurde ein <code>rhel9.5-bootc:test<\/code> Image erstellt<\/li>\n\n\n\n<li>Mit dem <code>bootc-image-builder<\/code> wurde ein ISO-Image erstellt, welchem ein Benutzer mit Passwort und \u00f6ffentlichem SSH-Schl\u00fcssel hinzugef\u00fcgt wurde und welches sich f\u00fcr die Installation von Offline-Systemen eignet<\/li>\n\n\n\n<li>Das ISO-Image wurde genutzt, um <em>RHEL image mode<\/em> in einer VM zu installieren<\/li>\n\n\n\n<li>Test von Login und einiger weniger Kommandos<\/li>\n\n\n\n<li>Der konfigurierte Webserver wird ausgef\u00fchrt und liefert die kleine Beispielwebseite aus<\/li>\n<\/ul>\n\n\n\n<p>Auf dem Weg hier her wurde erkl\u00e4rt, wie Container-Images mittels <code>podman-image-scp(1)<\/code> ohne Container-Registry zwischen Benutzerkontexten und Hosts kopiert werden k\u00f6nnen. Es wurde gezeigt, wie eine einfache Container-Registry betrieben und genutzt werden kann.<\/p>\n\n\n\n<p>Weitere M\u00f6glichkeiten zum Deployment von <em>RHEL Bootc Image<\/em>s finden sich in der Dokumentation in <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html-single\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/index#deploying-the-rhel-bootc-images_using-image-mode-for-rhel-to-build-deploy-and-manage-operating-systems\">Chapter&nbsp;6.&nbsp;Deploying the RHEL bootc images<\/a>. Darin findet sich auch ein Abschnitt, wie man das <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html-single\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/index#deploying-a-container-image-by-using-anaconda-and-kickstart_deploying-the-rhel-bootc-images\">RHEL bootc image aus einer Registry mithilfe von Anaconda und Kickstart installiert.<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"update-rollback\">Systemupdate und Rollback<\/h2>\n\n\n\n<p>Zu den Aufgaben des IT-Betriebs geh\u00f6rt es, Betriebssysteme zu aktualisieren, ihre Konfiguration neuen Anforderungen anzupassen und im Fehlerfall die letzten \u00c4nderungen schnell r\u00fcckg\u00e4ngig machen zu k\u00f6nnen. Diesen Aufgaben widmen sich die beiden folgenden Abschnitte.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"image-update-change\">Bootc Image Installation aktualisieren bzw. Konfiguration \u00e4ndern<\/h3>\n\n\n\n<p>W\u00e4hrend <em>RHEL package mode<\/em> Systeme zur Laufzeit mit DNF bzw. YUM aktualisiert werden und mit diesen Werkzeugen Software (de-)installiert wird, ist der Ablauf bei <em>RHEL image mode<\/em> Systemen anders:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Das <em>RHEL Bootc Image<\/em> wird aktualisiert<\/li>\n\n\n\n<li>Das aktualisierte Container-Image wird in einer Registry verf\u00fcgbar gemacht<\/li>\n\n\n\n<li>Das aktualisierte Image wird in den Staging-Bereich des laufenden <em>RHEL image mode<\/em> Systems geladen<\/li>\n\n\n\n<li>Durch einen Neustart wird das aktualisierte Image geladen<\/li>\n\n\n\n<li>Bei Bedarf, z.B. bei auftretenden Problemen, kann das vorherige Image geladen werden<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"image-update\">Aktualisierung des RHEL Bootc Image<\/h4>\n\n\n\n<p>Ich m\u00f6chte die Pakete <code>lsof<\/code>, <code>strace<\/code> und <code>tcpdump<\/code> doch nicht in meiner Standardinstallation haben und sie aus der existierenden Installation entfernen. Deshalb kommentiere die entsprechenden Zeilen aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat Containerfile\nFROM registry.redhat.io\/rhel9\/rhel-bootc:9.5\nADD index.html \/var\/www\/html\/index.html\nRUN dnf -y install httpd \\\n    openssh-server \\\n    bind-utils \\\n    net-tools \\\n    chrony \\\n    vim-enhanced \\\n    man-pages \\\n#    strace \\\n#    lsof \\\n#    tcpdump \\\n    bash-completion &amp;&amp; \\\n    dnf clean all\nRUN systemctl enable httpd sshd<\/code><\/pre>\n\n\n\n<p>Als N\u00e4chstes wird ein neues Image erstellt und in die Registry gepusht. Diesmal verwende ich den Tag <code>0.0.1<\/code>, um f\u00fcr den Verlauf dieses Tutorials leichter den \u00dcberblick zu behalten:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ podman build -t vm1.example.com:5000\/rhel9.5-bootc:0.0.1 .\nSTEP 1\/4: FROM registry.redhat.io\/rhel9\/rhel-bootc:9.5\nSTEP 2\/4: ADD index.html \/var\/www\/html\/index.html\n--&gt; Using cache eb262e01451d150d95636b3771ca8b5985155edd45bcfef838726002f910a411\n\u2026\nSuccessfully tagged vm1.example.com:5000\/rhel9.5-bootc:0.0.1\nce3ec0f5ae5af0d27415c76aed480bfda51d39d5aeffdd78c7c06e29907c3d46\n\n$ podman push --tls-verify=false vm1.example.com:5000\/rhel9.5-bootc:0.0.1<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"bootc-switch\">Das zu verwendende Image aus dem System heraus wechseln<\/h4>\n\n\n\n<p>Der nun folgende Schritt wird in dem laufenden <em>RHEL image mode<\/em> System in VM 2 ausgef\u00fchrt. In der RHEL-Dokumentation ist dieser Schritt in Abschnitt <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/managing-rhel-bootc-images#switching-the-container-image-reference_managing-rhel-bootc-images\">8.1.&nbsp;Switching the container image reference<\/a> beschrieben.<\/p>\n\n\n\n<p>F\u00fcr diesen Schritt ist eine funktionierende Namensaufl\u00f6sung zwischen VM 1 und VM 2 erforderlich. In der Laborumgebung kann dies mithilfe der Datei <code>\/etc\/hosts<\/code> erfolgen. Da in der Registry ein selbstsigniertes Zertifikat verwendet wird und das Kommando <code>bootc<\/code> keine Option <code>--tls-verify<\/code> besitzt, muss eine <em>insecure registry<\/em> in VM 2 konfiguriert werden. Der folgende Codeblock zeigt den Inhalt der Datei, mit der die <em>insecure registry<\/em> konfiguriert wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~]# cat \/etc\/containers\/registries.conf.d\/001-labregistry.conf\n&#91;&#91;registry]]\nlocation=\"vm1.example.com:5000\"\ninsecure=true<\/code><\/pre>\n\n\n\n<p>Da <code>bootc<\/code> auch nicht \u00fcber ein Login-Kommando verf\u00fcgt und keinen Zugriff auf die Login-Informationen von Podman hat, wird in VM 2 ein Pull-Secret f\u00fcr <code>bootc<\/code> konfiguriert. Dazu wird eine Zeichenkette bestehend aus <code>Benutzername:Passwort<\/code> in Base-64 kodiert und zusammen mit der Registry-URL in die Datei <code>\/etc\/ostree\/auth.json<\/code> geschrieben. Der folgende Code-Block zeigt dies mit den Beispielwerten aus diesem Tutorial:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~]# echo -n \"registryuser:registrypass\" | base64 -w 0 ; echo\ncmVnaXN0cnl1c2VyOnJlZ2lzdHJ5cGFzcw==\n\n~]# cat \/etc\/ostree\/auth.json \n{\n\t\"auths\": {\n\t\t\"vm1.example.com:5000\": {\n\t\t\t\"auth\": \"cmVnaXN0cnl1c2VyOnJlZ2lzdHJ5cGFzcw==\"\n\t\t}\n\t}\n}<\/code><\/pre>\n\n\n\n<p>Es gibt verschiedene M\u00f6glichkeiten, das Pull-Secret zu hinterlegen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Manuell, wie gerade gezeigt<\/li>\n\n\n\n<li>Mit einer Automationsl\u00f6sung wie z.B. Ansible zur Laufzeit des Zielsystems<\/li>\n\n\n\n<li>Bei der Erstellung des Disk-Images mit <code>bootc-image-builder<\/code><\/li>\n\n\n\n<li>Bei hinreichend gesicherter Container-Registry direkt im <em>RHEL Bootc Image<\/em><\/li>\n<\/ul>\n\n\n\n<p>Siehe f\u00fcr weitere Hinweise hierzu Abschnitt 11.2 bis 11.4 im Anhang <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/managing-users-groups-ssh-key-and-secrets-in-image-mode-for-rhel\">Managing users, groups, SSH keys, and secrets in image mode for RHEL<\/a>.<\/p>\n\n\n\n<p>Nun k\u00f6nnen wir mit dem folgenden Befehl von Image <code>vm1.example.com:5000\/rhel9.5-bootc:test<\/code> zu Image <code>vm1.example.com:5000\/rhel9.5-bootc:0.0.1<\/code> wechseln:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~]# bootc switch vm1.example.com:5000\/rhel9.5-bootc:0.0.1\nlayers already present: 67; layers needed: 2 (37.5&nbsp;MB)\nFetched layers: 35.74 MiB in 23 seconds (1.58 MiB\/s)                                                                   Deploying: done (5 seconds)                                                                                        Pruned images: 1 (layers: 0, objsize: 0 bytes)\nQueued for next boot: vm1.example.com:5000\/rhel9.5-bootc:0.0.1\n  Version: 9.20250109.0\n  Digest: sha256:c3925bc5d9618e803a3164f8f87a16333e4bf274469e72075d5cb50cf8ac51d9<\/code><\/pre>\n\n\n\n<p>Nach dem Wechsel befindet sich das ab nun zu verwendende Image zun\u00e4chst im Staging-Bereich des lokalen Systems und wird beim n\u00e4chsten Neustart aktiviert. Der Befehl <code>bootc status<\/code> gibt dazu \u00fcbersichtlich Informationen aus, welches Image gestaged ist und welches aktuell verwendet wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~]# bootc status\nCurrent staged image: vm1.example.com:5000\/rhel9.5-bootc:0.0.1\n    Image version: 9.20250109.0 (2025-01-14 19:58:27.484294313 UTC)\n    Image digest: sha256:c3925bc5d9618e803a3164f8f87a16333e4bf274469e72075d5cb50cf8ac51d9\nCurrent booted image: localhost\/rhel9.5-bootc:test\n    Image version: 9.20250109.0 (2025-01-11 12:40:29.172146867 UTC)\n    Image digest: sha256:eee2c8ea204615a9341f3747a6156c5b7bc208bbcf60f0a5bb28f142f6b0aa54\nNo rollback image present<\/code><\/pre>\n\n\n\n<p>Nach einem Neustart wird der Status mit <code>bootc status<\/code> erneut kontrolliert und wir sehen, dass nun das Image aus der Registry verwendet wird und das vorherige Image f\u00fcr ein Rollback vorgehalten wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~]$ sudo bootc status\nNo staged image present\nCurrent booted image: jkastnin-tpp1-rhel9-podman-1:5000\/rhel9.5-bootc:0.0.1\n    Image version: 9.20250109.0 (2025-01-14 19:58:27.484294313 UTC)\n    Image digest: sha256:c3925bc5d9618e803a3164f8f87a16333e4bf274469e72075d5cb50cf8ac51d9\nCurrent rollback image: localhost\/rhel9.5-bootc:test\n    Image version: 9.20250109.0 (2025-01-11 12:40:29.172146867 UTC)\n    Image digest: sha256:eee2c8ea204615a9341f3747a6156c5b7bc208bbcf60f0a5bb28f142f6b0aa54<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"auto-update\">Automatische Aktualisierungen und wie man sie deaktivieren kann<\/h4>\n\n\n\n<p>Auf <em>RHEL image mode<\/em> Systemen existiert ein <code>systemd.timer(5)<\/code>, welcher automatische Updates anst\u00f6\u00dft. Folgender Code-Block zeigt die Timer- und Service-Unit in VM 2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ systemctl status --no-pager bootc-fetch-apply-updates.{timer,service}\n\u25cf bootc-fetch-apply-updates.timer - Apply bootc updates\n     Loaded: loaded (\/usr\/lib\/systemd\/system\/bootc-fetch-apply-updates.timer; disabled; preset: disabled)\n     Active: active (waiting) since Wed 2025-01-15 08:29:37 UTC; 1h 1min ago\n      Until: Wed 2025-01-15 08:29:37 UTC; 1h 1min ago\n    Trigger: Wed 2025-01-15 10:28:13 UTC; 57min left\n   Triggers: \u25cf bootc-fetch-apply-updates.service\n       Docs: man:bootc(8)\n\nJan 15 08:29:37 localhost systemd&#91;1]: Started Apply bootc updates.\n\n\u25cb bootc-fetch-apply-updates.service - Apply bootc updates\n     Loaded: loaded (\/usr\/lib\/systemd\/system\/bootc-fetch-apply-updates.service; static)\n     Active: inactive (dead)\nTriggeredBy: \u25cf bootc-fetch-apply-updates.timer\n       Docs: man:bootc(8)<\/code><\/pre>\n\n\n\n<p>Ein Blick in die Service-Unit verr\u00e4t, was passiert, wenn diese getriggert wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat \/usr\/lib\/systemd\/system\/bootc-fetch-apply-updates.service\n&#91;Unit]\nDescription=Apply bootc updates\nDocumentation=man:bootc(8)\nConditionPathExists=\/run\/ostree-booted\n\n&#91;Service]\nType=oneshot\nExecStart=\/usr\/bin\/bootc update --apply --quiet<\/code><\/pre>\n\n\n\n<p>Das Kommando hinter <code>ExecStart=<\/code>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Pr\u00fcft, ob ein neues Image in der Container-Registry verf\u00fcgbar ist (Pr\u00fcfung efolgt auf Digest nicht auf Tag)<\/li>\n\n\n\n<li>Falls ein neues Image verf\u00fcgbar ist, wird dieses gestaged<\/li>\n\n\n\n<li>Der Host wird automatisch neugestartet, um das neue Image zu laden<\/li>\n<\/ol>\n\n\n\n<p>M\u00f6chte man Aktualisierungen durch andere Verfahren steuern, kann die automatische Aktualisierung wie folgt gestoppt werden:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ systemctl mask bootc-fetch-apply-updates.timer<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"rollback\">Rollback<\/h3>\n\n\n\n<p>Angenommen, das System soll auf das zuvor verwendete Conatiner-Image zur\u00fcckgerollt werden. So kann man sich zuvor mit <code>bootc status<\/code> einen \u00dcberblick verschaffen, welches Image als Rollback-Image eingetragen ist:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo bootc status\nCurrent staged image: jkastnin-tpp1-rhel9-podman-1:5000\/rhel9.5-bootc:0.0.2\n    Image version: 9.20250109.0 (2025-01-15 09:36:38.866194063 UTC)\n    Image digest: sha256:e68453dd17a45ad9243139b5cbb0565bbd97aa2bcd5a230c41e44d295281f9a7\nCurrent booted image: jkastnin-tpp1-rhel9-podman-1:5000\/rhel9.5-bootc:0.0.1\n    Image version: 9.20250109.0 (2025-01-15 09:36:38.866194063 UTC)\n    Image digest: sha256:e68453dd17a45ad9243139b5cbb0565bbd97aa2bcd5a230c41e44d295281f9a7\nCurrent rollback image: jkastnin-tpp1-rhel9-podman-1:5000\/rhel9.5-bootc:0.0.1\n    Image version: 9.20250109.0 (2025-01-14 19:58:27.484294313 UTC)\n    Image digest: sha256:c3925bc5d9618e803a3164f8f87a16333e4bf274469e72075d5cb50cf8ac51d9<\/code><\/pre>\n\n\n\n<p>Euch f\u00e4llt evtl. auf, dass zwei Images den gleichen Tag, aber unterschiedliche SHA-256-Pr\u00fcfsummen haben, und zwei Tags die gleiche Pr\u00fcfsumme und unterschiedliche Tags. Lasst euch davon bitte nicht irritieren; dies ist nur meiner Spielerei geschuldet.<\/p>\n\n\n\n<p>Bei einem Rollback wird das Image hinter dem Eintrag <code>Current rollback image<\/code> als Boot-Image verwendet. Ein Rollback wird mit folgendem Kommando ausgef\u00fchrt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo bootc rollback\nNext boot: rollback deployment<\/code><\/pre>\n\n\n\n<p>Nur den Neustart muss man noch selbst durchf\u00fchren. Nach dem Neustart sieht der Status wie folgt aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo bootc status\n&#91;sudo] password for jkastnin: \nNo staged image present\nCurrent booted image: jkastnin-tpp1-rhel9-podman-1:5000\/rhel9.5-bootc:0.0.1\n    Image version: 9.20250109.0 (2025-01-14 19:58:27.484294313 UTC)\n    Image digest: sha256:c3925bc5d9618e803a3164f8f87a16333e4bf274469e72075d5cb50cf8ac51d9\nCurrent rollback image: jkastnin-tpp1-rhel9-podman-1:5000\/rhel9.5-bootc:0.0.1\n    Image version: 9.20250109.0 (2025-01-15 09:36:38.866194063 UTC)\n    Image digest: sha256:e68453dd17a45ad9243139b5cbb0565bbd97aa2bcd5a230c41e44d295281f9a7<\/code><\/pre>\n\n\n\n<p>Anhand der SHA-256-Pr\u00fcfsumme ist zu erkennen, dass das vorherige <code>rollback image<\/code> nun den Platz mit dem vorherigen <code>booted image<\/code> gewechselt hat. Ein weiterer Aufruf von <code>bootc rollback<\/code> f\u00fchrt zu einem weiteren Image-Wechsel.<\/p>\n\n\n\n<p><em>Hinweis:<\/em> Wenn nach einem Update ein Rollback durchgef\u00fchrt wird und der Systemd-Timer f\u00fcr automatische Updates nicht deaktiviert wurde, f\u00fchrt dieser Timer bei Ablauf zu einem erneuten Update des Systems.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"ende\">Ende<\/h2>\n\n\n\n<p>Hier endet die Einf\u00fchrung in <em>RHEL image mode<\/em>. Wer dem Tutorial aufmerksam gefolgt ist, sollte an dieser Stelle in der Lage sein:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>RHEL Bootc Images<\/em> zu erstellen<\/li>\n\n\n\n<li>Eine einfache Container-Registry mit Podman zu betreiben<\/li>\n\n\n\n<li>Mit <code>bootc-image-builder<\/code> Disk-Images zu erstellen<\/li>\n\n\n\n<li>Ein System im <em>RHEL image mode<\/em> zu installieren<\/li>\n\n\n\n<li>Das installierte System zu aktualisieren<\/li>\n\n\n\n<li>Zu einem anderen Image zu wechseln<\/li>\n\n\n\n<li>Ein Rollback auf das vorherige Image durchzuf\u00fchren<\/li>\n<\/ul>\n\n\n\n<p>Wenn euch diese Einf\u00fchrung gefallen hat, freue ich mich, wenn ihr sie mit euren Netzwerken teilt. Nutzt gern die Kommentarfunktion, um mich wissen zu lassen, wie euch diese Einf\u00fchrung gefallen hat.<\/p>\n\n\n\n<p>Falls ihr euch weitere Artikel rund um den <em>RHEL image mode<\/em> w\u00fcnscht, teilt mir dies gern ebenfalls \u00fcber die Kommentarfunktion mit.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sources\">Quellen und weiterf\u00fchrende Links<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/access.redhat.com\/solutions\/21101\">What does a &#8222;Technology Preview&#8220; feature mean?<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/access.redhat.com\/support\/offerings\/techpreview\">Technology Preview Features &#8211; Scope of Support<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developers.redhat.com\/articles\/2024\/11\/05\/image-mode-rhel-4-key-use-cases-streamlining-your-os\">Image mode for RHEL: 4 key use cases for streamlining your OS<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/access.redhat.com\/solutions\/7054010\">How to get list of the packages included in &#8218;Minimal Install&#8216; ?<\/a> (Login notwendig)<\/li>\n\n\n\n<li><a href=\"https:\/\/www.redhat.com\/en\/blog\/podman-transfer-container-images-without-registry\">How Podman can transfer container images without a registry?<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.redhat.com\/en\/blog\/simple-container-registry\">How to implement a simple personal\/private Linux container image registry for internal use<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html-single\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/index\">Using image mode for RHEL to build, deploy, and manage operating systems<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/access.redhat.com\/RegistryAuthentication\">Red Hat Container Registry Authentication<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/composing_a_customized_rhel_system_image\/index\">Composing a customized RHEL system image<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/deploying-the-rhel-bootc-images_using-image-mode-for-rhel-to-build-deploy-and-manage-operating-systems#deploying-a-container-image-by-using-anaconda-and-kickstart_deploying-the-rhel-bootc-images\">Deploying a container image by using Anaconda and Kickstart<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/using_image_mode_for_rhel_to_build_deploy_and_manage_operating_systems\/managing-rhel-bootc-images#turning-off-automatic-updates_managing-rhel-bootc-images\">8.5.&nbsp;Turning off automatic updates<\/a><\/li>\n<\/ol>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dieses Tutorial f\u00fchrt in den RHEL image mode ein und zeigt, wie ein solches Image in einer virtuellen Maschine (VM) installiert werden kann. Es wird ebenfalls gezeigt, wie ein installiertes Image aktualisiert und bei Bedarf zur\u00fcckgerollt werden kann. W\u00e4hrend diese Einf\u00fchrung in Deutsch gehalten ist, liegen die Dokumentation und weitere verwendete Quellen ausschlie\u00dflich in englischer<span class=\"continue-reading\"> <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/einfuehrung-in-den-rhel-image-mode\/\">[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":[866,867,865,430,305,389,864],"class_list":["post-4032","post","type-post","status-publish","format-standard","hentry","category-tutorials","tag-bootc","tag-bootc-image-builder","tag-image-mode","tag-osbn","tag-planet","tag-rhel","tag-rhel9"],"_links":{"self":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/4032","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=4032"}],"version-history":[{"count":24,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/4032\/revisions"}],"predecessor-version":[{"id":4200,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/4032\/revisions\/4200"}],"wp:attachment":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/media?parent=4032"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/categories?post=4032"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/tags?post=4032"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}