GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Container-Image-Builds mit Buildah beschleunigen

Vor ein paar Monaten habe ich einen Artikel über die Beschleunigung von Container-Builds innerhalb eines Containers geschrieben. Dieser Artikel konzentrierte sich auf die Geschwindigkeit des Pullens von Container-Images und verschiedene Möglichkeiten, den Image-Speicher vorab zu füllen, indem Volume-Mounts vom Host und das Buildah-Konzept der „zusätzlichen Speicher“ verwendet wurden.

Buildah ist ein Befehlszeilentool zum schnellen und einfachen Erstellen von mit der Open Container Initiative kompatiblen (d. h. auch Docker- und Kubernetes-kompatiblen) Images. Buildah lässt sich einfach in Skripte und Build-Pipelines integrieren und das Beste ist, dass es keinen laufenden Container-Daemon benötigt, um sein Image zu erstellen.

Dieser Artikel behandelt ein zweites Problem mit der Build-Geschwindigkeit bei der Verwendung von dnf /yum Befehle in Containern. Beachten Sie, dass ich in diesem Artikel den Namen dnf verwenden werde (das ist der Upstream-Name) anstelle dessen, was einige Downstreams verwenden (yum ) Diese Kommentare gelten sowohl für dnf und yum .

Download-Geschwindigkeit

Ist Ihnen das manchmal aufgefallen, wenn Sie dnf -y update ausführen oder dnf -y install Zum ersten Mal seit einiger Zeit pausiert der Befehl für eine lange Zeit, bevor er überhaupt anfängt, die Drehzahl zu senken? Was ist los?

Das erste, was dnf lädt riesige Cache-Dateien herunter. Diese Dateien sind in XML geschrieben und enthalten jedes einzelne Paket im Remote-Repository, einschließlich vieler Daten über das Paket. Sie enthalten sogar jeden Pfad innerhalb des Pakets. Diese Daten werden benötigt, damit Sie etwas wie dnf -y install /usr/bin/httpd ausführen können und dann dnf ermittelt das zu installierende Paket. Viele Pakete enthalten Befehle wie (requires: /usr/bin/sendmail ), die diese Funktion nutzen und dnf zulassen ein geeignetes Paket zu ziehen, um den Bedarf zu decken.

Das Abrufen dieser riesigen Dateien – und noch wichtiger, das Verarbeiten dieser Dateien – kann über eine Minute dauern. Diese Daten werden von libsolv verwendet , also muss es in solv konvertiert werden Format, das langsam ist. Geschwindigkeit ist kein großes Problem, wenn Sie dies nur regelmäßig auf Ihrem Host tun, aber wenn es um das Erstellen von Containern geht, ist dies eine viel größere Sache.

Dockerfile-Syntax

Obwohl Sie mit Buildah Container-Images direkt in der Shell erstellen können, verwenden die meisten Benutzer Dockerfiles und Containerfiles, um Container zu erstellen und reproduzierbare Image-Rezepte zu definieren. Buildah sucht standardmäßig nach einer Containerfile und ein Dockerfile jetzt. Alle haben die gleiche Syntax, also werde ich Containerfile verwenden für den Rest dieses Dokuments.

Eine übliche Vorgehensweise in einer Containerfile ist eine Syntax wie:

zu verwenden
FROM ubi8  
RUN dnf -y update; dnf -y install nginx; dnf -y clean all  
…  
RUN dnf -y install jboss; dnf -y clean all  

Untersuchen wir den dnf Linien. Der erste dnf Zeile:

(dnf -y update; dnf -y install nginx; dnf -y clean all ):

  1. Aktualisiert alle Pakete im Container.
  2. Installiert das ausgewählte Paket nginx .
  3. Säubert alles.

Da das ubi8 image wurde wahrscheinlich vor einiger Zeit erstellt und sein /var/cache/dnf -Verzeichnis existiert wahrscheinlich nicht im Container-Image, dnf muss die XML-Cache-Datei herunterziehen und verarbeiten. Dann dnf installiert die eigentlichen Pakete vor dnf -y clean all entfernt alle überschüssigen Daten, die durch frühere Befehle in das Bild eingefügt wurden, z. B. Protokoll- und Cache-Dateien.

Benutzern wird empfohlen, clean all auszuführen um das Bild so klein wie möglich zu halten. Jeder RUN Befehl erstellt eine neue Ebene, und selbst wenn Sie den Inhalt in einem späteren RUN entfernen Befehl, enthält die erste Ebene den gesamten Inhalt. Dies bedeutet, dass jeder, der jemals Ihr Image abruft, am Ende die Protokolle und Cache-Dateien abruft. Wenn nun Ihre Containerfile enthält einen oder mehrere dnf Befehle zahlen Sie immer wieder den Preis. Nicht nur das, sondern jedes Mal, wenn Sie dieses Image neu erstellen, zahlen Sie diesen Preis erneut. Wenn Sie sich auf einem Build-Server befinden, lädt jedes Container-Image, das Sie erstellen, diese XML-Dateien immer wieder herunter, wodurch Unmengen an Ressourcen und Zeit verschwendet werden.

Buildah mit Overlay-Halterungen

Wir haben das oben beschriebene Problem gesehen und dachten, wir könnten es besser lösen. Könnten wir die XML-Daten nicht einfach auf den Host ziehen, auf dem Host verarbeiten und per Volume in die Container einhängen? Vielleicht könnten wir einen Cron-Job oder ein systemd einrichten Timer, der einen dnf makecache durchführt einmal für jede Betriebssystemversion, für die Sie Container-Images erstellen werden? Sie könnten diesen Job einmal oder mehrmals am Tag auf dem Host ausführen und dann alle Container-Builder veranlassen, die entsprechenden Caches in die Buildah-Container einzubinden.

Nun, Buildah unterstützt Volume-Mounting-Verzeichnisse vom Host in Container. Das sollte das Problem lösen, und das tut es auch. ABER, die Container wollen oft in dieses Verzeichnis schreiben, wenn sie den Cache aktualisieren müssen, also muss der Cache in den Containern mit Lese-/Schreibzugriff gemountet werden. Dadurch entsteht eine riesige Sicherheitslücke. Stellen Sie sich eine Situation vor, in der ein feindlicher Container-Build Inhalte in diesen Cache geschrieben hat, die ein späterer Container-Builder gelesen hat. Es könnte möglicherweise den zweiten Container dazu verleiten, gehackte Software zu installieren. Wir brauchen eine Lösung, bei der der Inhalt in den Container gemountet wird, nicht vom Container geschrieben werden kann, aber dennoch aus der Perspektive des Containers beschrieben werden kann. Dies ist im Grunde das, was ein Overlay-Mount-Punkt ist.

Das Overlay-Dateisystem hängt einen lower ein Verzeichnis und hängt dann einen upper an Verzeichnis zum merged Einhängepunkt. Wenn ein Prozess in eine neue Datei schreibt, wird merged Verzeichnis, die neue Datei wird in den upper geschrieben Verzeichnis. Wenn ein Prozess eine bestehende Datei im lower ändert Verzeichnis kopiert der Kernel die Datei aus dem lower Verzeichnis zum upper Verzeichnis und erlaubt dem Prozess, die Datei im upper zu ändern Verzeichnis.

Wir haben das Konzept des Overlay-Mounts in Buildah eingeführt. Jetzt können Sie Builds mit

ausführen
buildah bud -v /var/cache/dnf:/var/cache/dnf:O -f /tmp/Containerfile /tmp  

Dnf innerhalb des Containers wird weiterhin prüfen, ob neuere Inhalte in den Repos vorhanden sind, und den Inhalt herunterziehen, falls vorhanden. Wenn der Inhalt auf dem Host jedoch aktuell ist, wird er schnell den Cache des Hosts verwenden. Ich würde empfehlen, dass Sie den Host-Cache mindestens einmal täglich aktualisieren.

Eine zusätzliche Funktion, die wir für das Buildah-Overlay-Reittier hinzugefügt haben, ist das Zerstören des upper Verzeichnis bei jedem RUN Richtlinie. Erinnern Sie sich, dass wir in unserem Beispiel mehrere RUN verwendet haben Befehle, die jeweils ein dnf -y clean all ausgeführt haben . Der dnf -y clean all Befehl bewirkt das upper Verzeichnis, um den gesamten Inhalt des unteren als gelöscht anzuzeigen. Wenn der nächste dnf Wenn der Befehl den vorherigen oberen Wert geteilt hat, würde er den Cache als leer sehen und den XML-Datenspeicher herunterziehen und verarbeiten müssen. Entfernen des upper Verzeichnis bedeutet, dass jeder dnf Befehl sieht wieder den lower Verzeichnis vom Host und teilen Sie weiterhin den Host-Cache.

Geschwindigkeitsunterschied

Ich werde eine einfache Containerfile erstellen enthält zwei dnf Befehle ausführen.

FROM fedora:31  
RUN dnf -y install net-utils; dnf -y clean all  
RUN dnf -y install iputils; dnf -y clean all  

Führen Sie dies lokal auf meiner Fedora 31-Box aus

# time -f "Elapsed Time: %E" buildah bud -f Containerfile .  
STEP 1: FROM fedora:31  
STEP 2: RUN dnf -y install procps-ng; dnf -y clean all  
Fedora Modular 31 - x86_64 2.0 MB/s | 5.2 MB 00:02  
Fedora Modular 31 - x86_64 - Updates 1.6 MB/s | 4.0 MB 00:02  
Fedora 31 - x86_64 - Updates 4.2 MB/s | 19 MB 00:04  
Fedora 31 - x86_64 1.8 MB/s | 71 MB 00:39  
Last metadata expiration check: 0:00:01 ago on Wed Feb 5 13:55:54 2020.  
Dependencies resolved.  
================================================================================  
Package Architecture Version Repository Size  
================================================================================  
Installing:  
procps-ng x86_64 3.3.15-6.fc31 fedora 326 k

Transaction Summary  
================================================================================  
Install 1 Package

Total download size: 326 k  
Installed size: 966 k  
Downloading Packages:  
procps-ng-3.3.15-6.fc31.x86_64.rpm 375 kB/s | 326 kB 00:00  
--------------------------------------------------------------------------------  
Total 218 kB/s | 326 kB 00:01  
Running transaction check  
Transaction check succeeded.  
Running transaction test  
Transaction test succeeded.  
Running transaction  
Preparing : 1/1  
Installing : procps-ng-3.3.15-6.fc31.x86_64 1/1  
Running scriptlet: procps-ng-3.3.15-6.fc31.x86_64 1/1  
Verifying : procps-ng-3.3.15-6.fc31.x86_64 1/1

Installed:  
procps-ng-3.3.15-6.fc31.x86_64

Complete!  
33 files removed  
STEP 3: RUN dnf -y install iputils; dnf -y clean all  
Fedora Modular 31 - x86_64 741 kB/s | 5.2 MB 00:07  
Fedora Modular 31 - x86_64 - Updates 928 kB/s | 4.0 MB 00:04  
Fedora 31 - x86_64 - Updates 3.8 MB/s | 19 MB 00:05  
Fedora 31 - x86_64 7.9 MB/s | 71 MB 00:08  
Last metadata expiration check: 0:00:01 ago on Wed Feb 5 13:57:13 2020.  
Dependencies resolved.  
================================================================================  
Package Architecture Version Repository Size  
================================================================================  
Installing:  
iputils x86_64 20190515-3.fc31 fedora 141 k

Transaction Summary  
================================================================================  
Install 1 Package

Total download size: 141 k  
Installed size: 387 k  
Downloading Packages:  
iputils-20190515-3.fc31.x86_64.rpm 252 kB/s | 141 kB 00:00  
--------------------------------------------------------------------------------  
Total 141 kB/s | 141 kB 00:01  
Running transaction check  
Transaction check succeeded.  
Running transaction test  
Transaction test succeeded.  
Running transaction  
Preparing : 1/1  
Installing : iputils-20190515-3.fc31.x86_64 1/1  
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1  
Verifying : iputils-20190515-3.fc31.x86_64 1/1

Installed:  
iputils-20190515-3.fc31.x86_64

Complete!  
33 files removed  
STEP 4: COMMIT  
Getting image source signatures  
Copying blob ac0b803c5612 skipped: already exists  
Copying blob 922380d685bc done  
Copying config 566e2afbb4 done  
Writing manifest to image destination  
Storing signatures  
566e2afbb417f0119109578a87950250b566a3b4908868627975a4c7428accfb  
566e2afbb417f0119109578a87950250b566a3b4908868627975a4c7428accfb

Elapsed Time: 2:15.00  

Dieser Durchlauf dauerte 2 Minuten und 15 Sekunden, um ein neues Container-Image mit den zwei neuen Paketen zu erstellen.

Versuchen wir es jetzt mit einem Overlay-Mount vom Host.

# dnf -y makecache  
# time -f "Elapsed Time: %E" buildah bud -v /var/cache/dnf:/var/cache/dnf:O -f Containerfile .  
STEP 1: FROM fedora:31  
STEP 2: RUN dnf -y install procps-ng; dnf -y clean all  
Last metadata expiration check: 0:02:34 ago on Wed Feb 5 13:51:54 2020.  
Dependencies resolved.  
================================================================================  
Package Architecture Version Repository Size  
================================================================================  
Installing:  
procps-ng x86_64 3.3.15-6.fc31 fedora 326 k

Transaction Summary  
================================================================================  
Install 1 Package

Total download size: 326 k  
Installed size: 966 k  
Downloading Packages:  
procps-ng-3.3.15-6.fc31.x86_64.rpm 496 kB/s | 326 kB 00:00  
--------------------------------------------------------------------------------  
Total 245 kB/s | 326 kB 00:01  
Running transaction check  
Transaction check succeeded.  
Running transaction test  
Transaction test succeeded.  
Running transaction  
Preparing : 1/1  
Installing : procps-ng-3.3.15-6.fc31.x86_64 1/1  
Running scriptlet: procps-ng-3.3.15-6.fc31.x86_64 1/1  
Verifying : procps-ng-3.3.15-6.fc31.x86_64 1/1

Installed:  
procps-ng-3.3.15-6.fc31.x86_64

Complete!  
285 files removed  
STEP 3: RUN dnf -y install iputils; dnf -y clean all  
Last metadata expiration check: 0:02:41 ago on Wed Feb 5 13:51:54 2020.  
Dependencies resolved.  
================================================================================  
Package Architecture Version Repository Size  
================================================================================  
Installing:  
iputils x86_64 20190515-3.fc31 fedora 141 k

Transaction Summary  
================================================================================  
Install 1 Package

Total download size: 141 k  
Installed size: 387 k  
Downloading Packages:  
iputils-20190515-3.fc31.x86_64.rpm 556 kB/s | 141 kB 00:00  
--------------------------------------------------------------------------------  
Total 222 kB/s | 141 kB 00:00  
Running transaction check  
Transaction check succeeded.  
Running transaction test  
Transaction test succeeded.  
Running transaction  
Preparing : 1/1  
Installing : iputils-20190515-3.fc31.x86_64 1/1  
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1  
Verifying : iputils-20190515-3.fc31.x86_64 1/1

Installed:  
iputils-20190515-3.fc31.x86_64

Complete!  
285 files removed  
STEP 4: COMMIT  
Getting image source signatures  
Copying blob ac0b803c5612 skipped: already exists  
Copying blob 524bb3b83d61 done  
Copying config 0f82aa6064 done  
Writing manifest to image destination  
Storing signatures  
0f82aa6064814ff3dcb603c34c75e516e00817811681b83b8632f3e9b694e518  
0f82aa6064814ff3dcb603c34c75e516e00817811681b83b8632f3e9b694e518  
Elapsed Time: 0.17.44  

Mit dem Overlay-Mount konnten wir mit den beiden Zusatzpaketen in 17 Sekunden statt 2 Minuten und 15 Sekunden ein neues Image aufbauen. Das ist fast 8-mal schneller, um dasselbe Container-Image zu erstellen.

Dies zeigt nun, dass, wenn Sie Images auf einem Host-Betriebssystem erstellen, das über den dnf verfügt Metadaten vorgecacht können Sie die Installationsgeschwindigkeit um einen RIESIGEN Betrag beschleunigen. Aber was ist, wenn Ihr Build-System Images für andere Versionen des Betriebssystems erstellt? Angenommen, Sie möchten Images sowohl für Fedora 30 als auch für Fedora 31 erstellen. Hinweis:Dies würde auch auf einem RHEL8-System funktionieren, auf dem Sie möglicherweise RHEL7- und vielleicht sogar RHEL6-Images erstellen möchten.
Dnf enthält eine coole Funktion, mit der Sie beim Abrufen von Inhalten mithilfe von --releasever verschiedene Releases angeben können Möglichkeit. Dnf erlaubt Ihnen auch, alternative Verzeichnisse zum Platzieren des Cache-Verzeichnisses anzugeben, --setopt=cachedir .

Im folgenden Beispiel werde ich zwei Caches auf dem Host herunterziehen und dann Buildah im Befehlszeilenmodus verwenden.

# dnf -y makecache --releasever=31 --setopt=cachedir=/var/cache/dnf/31  
# dnf -y makecache --releasever=30 --setopt=cachedir=/var/cache/dnf/30  
# ctr31=$(buildah from fedora:31)  
# time -f 'Elapsed Time: %E' buildah run -v /var/cache/dnf/31:/var/cache/dnf:O ${ctr31} dnf -y install iputils  
Last metadata expiration check: 0:00:15 ago on Wed Feb 5 14:17:41 2020.  
Dependencies resolved.  
================================================================================  
Package Architecture Version Repository Size  
================================================================================  
Installing:  
iputils x86_64 20190515-3.fc31 fedora 141 k

Transaction Summary  
================================================================================  
Install 1 Package

Total download size: 141 k  
Installed size: 387 k  
Downloading Packages:  
iputils-20190515-3.fc31.x86_64.rpm 192 kB/s | 141 kB 00:00  
--------------------------------------------------------------------------------  
Total 107 kB/s | 141 kB 00:01  
Running transaction check  
Transaction check succeeded.  
Running transaction test  
Transaction test succeeded.  
Running transaction  
Preparing : 1/1  
Installing : iputils-20190515-3.fc31.x86_64 1/1  
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1  
Verifying : iputils-20190515-3.fc31.x86_64 1/1

Installed:  
iputils-20190515-3.fc31.x86_64

Complete!  
Elapsed Time: 0:06.85

# ctr30=$(buildah from fedora:30)  
# time -f 'Elapsed Time: %E' buildah run -v /var/cache/dnf/30:/var/cache/dnf:O ${ctr30} dnf -y install iputils  
Last metadata expiration check: 0:00:15 ago on Wed Feb 5 14:17:47 2020.  
Dependencies resolved.  
================================================================================  
Package Architecture Version Repository Size  
================================================================================  
Installing:  
iputils x86_64 20180629-4.fc30 fedora 123 k

Transaction Summary  
================================================================================  
Install 1 Package

Total download size: 123 k  
Installed size: 351 k  
Downloading Packages:  
iputils-20180629-4.fc30.x86_64.rpm 370 kB/s | 123 kB 00:00  
--------------------------------------------------------------------------------  
Total 138 kB/s | 123 kB 00:00  
Running transaction check  
Transaction check succeeded.  
Running transaction test  
Transaction test succeeded.  
Running transaction  
Preparing : 1/1  
Installing : iputils-20180629-4.fc30.x86_64 1/1  
Running scriptlet: iputils-20180629-4.fc30.x86_64 1/1  
Verifying : iputils-20180629-4.fc30.x86_64 1/1

Installed:  
iputils-20180629-4.fc30.x86_64

Complete!  
Elapsed Time: 0:08.88  

Wie Sie sehen können, konnten wir Buildah-Container mit dnf ausführen Cache von zwei verschiedenen Versionen von Fedora vom selben Build-Host und die Container für Fedora 31 dauerten 6+ Sekunden und der Fedora 30-Build dauerte 8+ Sekunden.

Hinweis:Ich habe ein Unterverzeichnis von /var/cache/dnf gewählt für die Cache-Dateien, um sicherzustellen, dass die SELinux-Labels korrekt sind. Führen Sie einfach dnf clean all aus bereinigt /var/cache/dnf/31 nicht . Sie müssten dnf clean all --setopt=cachedir=/var/cache/dnf/31 ausführen Repo-Cache-Dateien ordnungsgemäß zu bereinigen, aber einige Artefakte bleiben trotzdem erhalten (gpg-Schlüssel, leere Verzeichnisse).

Jetzt nur um zu sehen, wie lange es dauern würde, den Build auf Fedora 31 ohne das Overlay-Mount auszuführen.

# ctr31=$(buildah from fedora:31)  
# time -f 'Elapsed Time: %E' buildah run ${ctr31} dnf -y install iputils  
Fedora Modular 31 - x86_64 1.2 MB/s | 5.2 MB 00:04  
Fedora Modular 31 - x86_64 - Updates 875 kB/s | 4.0 MB 00:04  
Fedora 31 - x86_64 - Updates 2.4 MB/s | 19 MB 00:07  
Fedora 31 - x86_64 1.7 MB/s | 71 MB 00:41  
Dependencies resolved.  
================================================================================  
Package Architecture Version Repository Size  
================================================================================  
Installing:  
iputils x86_64 20190515-3.fc31 fedora 141 k

Transaction Summary  
================================================================================  
Install 1 Package

Total download size: 141 k  
Installed size: 387 k  
Downloading Packages:  
iputils-20190515-3.fc31.x86_64.rpm 279 kB/s | 141 kB 00:00  
--------------------------------------------------------------------------------  
Total 129 kB/s | 141 kB 00:01  
Running transaction check  
Transaction check succeeded.  
Running transaction test  
Transaction test succeeded.  
Running transaction  
Preparing : 1/1  
Installing : iputils-20190515-3.fc31.x86_64 1/1  
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1  
Verifying : iputils-20190515-3.fc31.x86_64 1/1

Installed:  
iputils-20190515-3.fc31.x86_64

Complete!  
Elapsed Time: 1:29.85  

In diesem Fall dauerte es fast 1,5 Minuten, um denselben Container auszuführen. Buildah mit Overlay-Reittieren lief 14-mal schneller.

Rootlose Container

Alle meine bisherigen Beispiele haben die Builds mit Containerfiles ausgeführt als Wurzel. Aber Sie können dies auch mit Rootless-Containern tun. In den nächsten Beispielen lasse ich Buildah Container mit buildah run ausführen Syntax, um die Verwendung des Caches zu demonstrieren.

Ausführen

$ buildah run -v /var/cache/dnf/30:/var/cache/dnf:O ${ctr30} dnf -y install iputils  

funktioniert gut. Solange der Benutzer den /var/cache/dnf/30 lesen kann Verzeichnis, das lower Verzeichnis gelesen werden. Aber Sie müssen sich auf etwas auf dem Host verlassen, um den Cache regelmäßig zu aktualisieren.

Wenn Benutzer möchten, können sie sogar dnf verwenden um den Cache in ihrem Home-Verzeichnis zu erstellen.

$ dnf -y makecache --releasever=30 --setopt=cachedir=$HOME/dnfcache  
$ chcon --reference /var/cache/dnf -R $HOME/dnfcache  
$ ctr30=$(buildah from fedora:30)  
$ buildah run -v $HOME/dnfcache:/var/cache/dnf:O ${ctr30} dnf -y install iputils  

Beachten Sie, dass ich das SELinux-Label von $HOME/dnfcache ändern musste Verzeichnis, damit SELinux den Containern erlauben würde, den lower zu lesen Verzeichnis für das Overlay-Mount.

Fazit

Um den Bau von Containern zu beschleunigen, müssen Sie verstehen, was passiert, wenn Sie Pakete installieren. dnf vorab zwischenspeichern Daten auf dem Host und die Verwendung von Overlay-Mounts zum Mounten des Caches in den Container mit Buildah kann die Geschwindigkeit von Builds erheblich erhöhen und die Anzahl der Ressourcen reduzieren, die zur Unterstützung einer Build-Farm erforderlich sind.

Buildah steht für Einfachheit, hat aber auch einige großartige Funktionen wie Overlay mounts und additional stores was Ihnen helfen kann, Ihre Container-Image-Builds zu beschleunigen.

[ Neu bei Containern? Laden Sie den Containers Primer herunter und lernen Sie die Grundlagen von Linux-Containern kennen. ]


Linux
  1. Erstellen Sie Ihren eigenen Container unter Linux

  2. Verwenden Sie Aufgabenzustände mit Server-Imaging

  3. Bildoptimierung mit webp

  4. Alle Grafikdateien mit find auflisten?

  5. Kernel-Tuning mit Privileged Docker Container

Wie man mit dnf-Paketgruppen arbeitet

So klonen Sie ein verschlüsseltes Disk-Image mit Clonezilla

So installieren Sie Software mit Yum/Dnf unter Verwendung des RHEL-ISO-Images

Die ultimative Anleitung zur Bildbearbeitung mit ImageMagick

So erstellen Sie ein Docker-Windows-Image mit Docker-Build-Tag

Erste Schritte mit Buildah zum Verwalten von Linux-Containern