Proxmox VE 9.1 leitet LXC-Containers aus OCI-Images ab
Die Virtualisierungs- und Containerlösung Proxmox VE kann in ihrer neuen Version OCI-Images als Vorlagen nutzen, speichert den Zustand des vTPM im QCOW2-Format, knipst schnell eine Nested…
Die Virtualisierungs- und Containerlösung Proxmox VE kann in ihrer neuen Version OCI-Images als Vorlagen nutzen, speichert den Zustand des vTPM im QCOW2-Format, knipst schnell eine Nested…
Die Virtualisierungs- und Containerlösung Proxmox VE kann in ihrer neuen Version OCI-Images als Vorlagen nutzen, speichert den Zustand des vTPM im QCOW2-Format, knipst schnell eine Nested…
Ca. seit 2020 kommt nftables (Kommando nft) per Default als Firewall-Backend unter Linux zum Einsatz. Manche Distributionen machten den Schritt noch früher, andere folgten ein, zwei Jahre später. Aber mittlerweile verwenden praktisch alle Linux-Distributionen nftables.
Alte Firewall-Scripts mit iptables funktionieren dank einer Kompatibilitätsschicht zum Glück größtenteils weiterhin. Viele wichtige Firewall-Tools und -Anwendungen (von firewalld über fail2ban bis hin zu den libvirt-Bibliotheken) brauchen diese Komaptibilitätsschicht aber nicht mehr, sondern wurden auf nftables umgestellt.
Welches Programm ist säumig? Docker! Und das wird zunehmend zum Problem.
Update 11.11.2025: In naher Zukunft wird mit Engine Version 29.0 nftables als experimentelles Firewall-Backend ausgeliefert. (Aktuell gibt es den rc3, den ich aber nicht getestet habe. Meine lokalen Installationen verwenden die Engine-Version 28.5.1.) Ich habe den Artikel diesbezüglich erweitert/korrigiert. Sobald die Engine 29 ausgeliefert wird, werde ich das neue Backend ausprobieren und einen neuen Artikel verfassen.
Auf die bisher massivsten Schwierigkeiten bin ich unter Fedora >=42 und openSUSE >= 16 gestoßen: Wird zuerst Docker installiert und ausgeführt, funktioniert in virtuellen Maschinen, die mit libvirt/virt-manager gestartet werden, das NAT-Networking nicht mehr. Und es bedarf wirklich einiger Mühe, den Zusammenhang mit Docker zu erkennen. Die vorgebliche »Lösung« besteht darin, die libvirt-Firewall-Funktionen von nftables zurück auf iptables zu stellen. Eine echte Lösung wäre es, wenn Docker endlich nftables unterstützen würde.
# in der Datei /etc/libvirt/network.conf
firewall_backend = "iptables"
Danach starten Sie den libvirt-Dämon dann neu:
sudo systemctl restart libvirtd
Weitere Infos gibt es hier und hier. Die openSUSE-Release-Notes weisen ebenfalls auf das Problem hin.
Weil Docker iptables verwendet, ist es mit nftables oder firewalld nicht möglich, Container mit offenen Ports nach außen hin zu blockieren. Wenn Sie also docker run -p 8080:80 machen oder in compose.yaml eine entsprechende Ports-Zeile einbauen, ist der Port 8080 nicht nur auf dem lokalen Rechner sichtbar, sondern für die ganze Welt! nftables- oder firewalld-Regeln können dagegen nichts tun!
Deswegen ist es wichtig, dass Docker-Container möglichst in internen Netzwerken miteinander kommunizieren bzw. dass offene Ports unbedingt auf localhost limitiert werden:
# Port 8080 ist nur für localhost zugänglich.
docker run -p localhost:8080:80 ...
Ihre Optionen in compose.yaml sehen so aus:
```bash
# compose.yaml
# Ziel: myservice soll mit anderem Container
# in compose.yaml über Port 8888 kommunizieren
services:
myservice:
image: xxx
ports:
# unsicher!
# - "8888:8888"
# besser (Port ist für localhost sichtbar)
# - "127.0.0.1:8888:8888"
# noch besser (Port ist nur Docker-intern offen)
- "8888"
otherservice:
...
Die sicherste Lösung besteht darin, die Container ausschließlich über ein Docker-internes Netzwerk miteinander zu verbinden (siehe backend_network im folgenden schablonenhaften Beispiel). Die Verbindung nach außen für die Ports 80 und 443 erfolgt über ein zweites Netzwerk (frontend_network). Die Angabe des drivers ist optional und verdeutlicht hier nur den Default-Netzwerktyp.
# compose.yaml
# am besten: die beiden Services myservice und
# nginx kommunizieren über das interne Netzwerk
# miteinander
services:
myservice:
build: .
ports:
- "8888:8888"
networks:
- backend_network
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- /etc/mycerts/fullchain.pem:/etc/nginx/ssl/nginx.crt
- /etc/mycerts/privkey.pem:/etc/nginx/ssl/nginx.key
depends_on:
- myservice
networks:
- frontend_network
- backend_network
networks:
# Verbindung zum Host über eine Bridge
frontend_network:
driver: bridge
# Docker-interne Kommunikation zwischen den Containern
backend_network:
driver: bridge
internal: true
Docker hat es sich zuletzt sehr einfach gemacht. Auf https://docs.docker.com/engine/install/ubuntu/#firewall-limitations steht:
If you use ufw or firewalld to manage firewall settings, be aware that when you expose container ports using Docker, these ports bypass your firewall rules. For more information, refer to Docker and ufw.
Docker is only compatible with iptables-nft and iptables-legacy. Firewall rules created with nft are not supported on a system with Docker installed. Make sure that any firewall rulesets you use are created with iptables or ip6tables, and that you add them to the DOCKER-USER chain, see Packet filtering and firewalls.
Und https://docs.docker.com/engine/security/#docker-daemon-attack-surface gibt diese Zusammenfassung:
Finally, if you run Docker on a server, it is recommended to run exclusively Docker on the server, and move all other services within containers controlled by Docker. Of course, it is fine to keep your favorite admin tools (probably at least an SSH server), as well as existing monitoring/supervision processes, such as NRPE and collectd.
Salopp formuliert: Verwenden Sie für das Docker-Deployment ausschließlich für diesen Zweck dezidierte Server und/oder verwenden Sie bei Bedarf veraltete iptable-Firewalls. Vor fünf Jahren war dieser Standpunkt noch verständlich, aber heute geht das einfach gar nicht mehr. Die Praxis sieht ganz oft so aus, dass auf einem Server diverse »normale« Dienste laufen und zusätzlich ein, zwei Docker-Container Zusatzfunktionen zur Verfügung stellen. Sicherheitstechnisch wird dieser alltägliche Wunsch zum Alptraum.
Bei Docker weiß man natürlich auch, dass iptables keine Zukunft hat. Laut diesem Issue sind 10 von 11 Punkte für die Umstellung von iptables auf nftables erledigt. Aber auch dann ist unklar, wie es weiter gehen soll: Natürlich ist das ein massiver Eingriff in grundlegende Docker-Funktionen. Die sollten vor einem Release ordentlich getestet werden. Einen (offiziellen) Zeitplan für den Umstieg auf nftables habe ich vergeblich gesucht.
Docker ist als Plattform-überschreitende Containerlösung für Software-Entwickler fast konkurrenzlos. Aber sobald man den Sichtwinkel auf Linux reduziert und sich womöglich auf Red-Hat-ähnliche Distributionen fokussiert, sieht die Lage anders aus: Podman ist vielleicht nicht hundertprozentig kompatibel, aber es ist mittlerweile ein sehr ausgereiftes Container-System, das mit Docker in vielerlei Hinsicht mithalten kann. Installationsprobleme entfallen, weil Podman per Default installiert ist. Firewall-Probleme entfallen auch. Und der root-less-Ansatz von Podman ist sicherheitstechnis sowieso ein großer Vorteil (auch wenn er oft zu Netzwerkeinschränkungen und Kompatibilitätsproblemen führt, vor allem bei compose-Setups).
Für mich persönlich war Docker immer die Referenz und Podman die nicht ganz perfekte Alternative. Aber die anhaltenden Firewall-Probleme lassen mich an diesem Standpunkt zweifeln. Die Firewall-Inkompatibilität ist definitiv ein gewichtiger Grund, der gegen den Einsatz der Docker Engine auf Server-Installationen spricht. Docker wäre gut beraten, iptables ENDLICH hinter sich zu lassen!
Update 11.11.2025: Als ich diesen Artikel im Oktober 2025 verfasst und im November veröffentlicht habe, ist mir entgangen, dass die Docker-Engine in der noch nicht ausgelieferten Version 29 tatsächlich bereits ein experimentelles nftables-Backend enthält!
Version 29 liegt aktuell als Release Candidate 3 vor. Ich warte mit meinen Tests, bis die Version tatsächlich ausgeliefert wird. Hier sind die Release Notes, hier die neue Dokumentationsseite. Vermutlich wird es ein, zwei weitere Releases brauchen, bis das nftables-Backend den Sprung von »experimentell« bis »stabil« schafft, aber immerhin ist jetzt ganz konkret ein Ende der Firewall-Misere in Sicht.
Das neue nftables-Backend für Docker
IncusOS ist ein modernes, unveränderliches Betriebssystem auf der Basis von Debian 13 »Trixie«, das ausschließlich für den sicheren und zuverlässigen Betrieb der Container des LXD-Forks Incus entwickelt wurde.
Nach einer längeren Entwicklungsphase meldet sich Flatpak eindrucksvoll zurück. Sebastian Wick von Red Hat hat kürzlich Einblicke in die Arbeit am beliebten Linux-Sandboxing-Framework gegeben. Die Pre-Release-Version 1.17 markiert die erste Aktualisierung seit sechs Monaten und startet eine neue instabile Serie und beerbt Version 1.16.1. Wick räumte ein, dass Flatpak Anfang 2025 eine eher ruhige Phase […]
Der Beitrag Flatpak 1.17 – das steht uns bevor erschien zuerst auf fosstopia.
Mit der Veröffentlichung von Version 4.44.3 schließt der Docker Desktop eine kritische Sicherheitslücke.
Die von Red Hat veröffentlichen Untersuchung „The State of Virtualization“ bietet Einblicke zur Nutzung von Virtualisierung und Containern.
Apple hat einige Neuerungen für Entwickler angekündigt, die unter macOS arbeiten.
Apple hat einige Neuerungen für Entwickler angekündigt, die unter macOS arbeiten.
Die Docker-Alternative Podman ergänzt in seiner neuen Version einige nützliche neue (Sub-)Kommandos und Parameter.
Die Docker-Alternative Podman ergänzt in seiner neuen Version einige nützliche neue (Sub-)Kommandos und Parameter.
Die plattformübergreifende Linux-Paketlösung Flatpak ist in Version 1.16.1 erschienen. Das erste Wartungsupdate der 1.16-Serie bringt viele Detailverbesserungen, die sowohl Nutzern als auch Administratoren zugutekommen. Im Fokus stehen neben besserer Performance und optimiertem Speicherverbrauch vor allem Sicherheitsaspekte. Besonders relevant ist die überarbeitete Kindersicherung. Kinderkonten dürfen ab sofort standardmäßig installierte Flatpak-Anwendungen selbstständig aktualisieren. Dadurch gelangen wichtige Sicherheitsupdates […]
Der Beitrag Flatpak 1.16.1 veröffentlicht: Mehr Kontrolle, mehr Sicherheit, mehr Effizienz erschien zuerst auf fosstopia.
Mit Version 1.33 bringt Kubernetes ein umfangreiches Funktionspaket. Die neue Version trägt den Codenamen „Octarine“ – eine Anspielung auf die unsichtbare Zauberfarbe aus Terry Pratchetts Scheibenwelt. Insgesamt umfasst das Update 64 Änderungen, darunter 18 stabile Features. Besonders hervorzuheben ist die Stabilisierung des Sidecar-Patterns. Damit lassen sich Zusatzcontainer für Logging, Netzwerk oder Monitoring fest in den […]
Der Beitrag Kubernetes 1.33 veröffentlicht: Mehr Stabilität, neue Features und bessere Skalierung erschien zuerst auf fosstopia.
Neben einem flexibleren Logging verspricht die neue Version des Contianer- und VM-Managers Incus auch ein Hotplugging des Hauptspeichers in VMs, Performance-Verbesserungen sowie neue Network…
Neben einem flexibleren Logging verspricht die neue Version des Contianer- und VM-Managers Incus auch ein Hotplugging des Hauptspeichers in VMs, Performance-Verbesserungen sowie neue Network…
Das Incus-Team hat Incus 6.10 veröffentlicht.
Microsoft hat die Bereitstellung von Skype für Linux umgestellt: Künftig gibt es die Anwendung nur noch im Snap-Format. Nutzer, die den Messenger bisher über .deb- oder .rpm-Pakete installiert haben, müssen umsteigen, denn diese Repositories wurden geschlossen und gelten nun als veraltet. Die Entscheidung folgt einer bereits vor über einem Jahr angekündigten Strategie. Während Microsoft einige […]
Der Beitrag Microsoft stellt Skype für Linux nur noch als Snap-Paket bereit erschien zuerst auf fosstopia.
Distrobox zündet mit wenigen Hangriffen komplette Distributionen in Containern. Die aktualisierte Fassung macht zwar nur einen kleinen Versionssprung, enthält aber einige interessante Neuerungen.
Distrobox zündet mit wenigen Hangriffen komplette Distributionen in Containern. Die aktualisierte Fassung macht zwar nur einen kleinen Versionssprung, enthält aber einige interessante Neuerungen.
Das beliebte Linux-Framework Flatpak wurde auf Version 1.16 aktualisiert. Dieses große Update bringt neue Funktionen und Verbesserungen mit. Zweieinhalb Jahre nach Version 1.14 bietet Flatpak 1.16: Neu ist auch die Zulassung des modify_ldt-Systemaufrufs mit –allow=multiarch.Dies wird benötigt, um 16-Bit-Programme mit Wine auszuführen. Ein HTTP-Backend-Variable in flatpak.pc wurde hinzugefügt. Das erleichtert Projekten wie GNOME Software die […]
Der Beitrag Neue Flatpak 1.16 Version erschienen erschien zuerst auf fosstopia.
Die aktuelle Version des Managers für Container und virtuelle Maschinen verbessert die Konvertierung von VMs, erlaubt eine feinere Steuerung von via TLS angemeldeten Clients und bietet über seine…
Die aktuelle Version des Managers für Container und virtuelle Maschinen verbessert die Konvertierung von VMs, erlaubt eine feinere Steuerung von via TLS angemeldeten Clients und bietet über seine…
Mit Distrobox lassen sich komplette Distributionen bequem in Container sperren und so unter anderem gefahrlos testen.
Dieser Artikel gibt meine Motivation für den Bau von Container-Images und die Vorgehensweise wieder und zeigt, wie ich mit Buildah meine OCI-kompatiblen Container-Images erstelle.
Es handelt sich dabei mehr um einen Erfahrungsbericht als ein Tutorial und ich erhebe keinen Anspruch auf Vollständigkeit. Das behandelte Beispiel ist jedoch zum Einstieg und zur Nachahmung für all jene geeignet, die Container ausführen können und diese gerne ohne Verwendung von Containerfiles bauen möchten.
Ich möchte die Ansible-Rollen aus meiner Collection tronde.nextcloud mit Molecule und Podman-Containern testen. Als Zielplattform für das Deployment der Nextcloud unterstütze ich zunächst Debian und RHEL.
Die Tests sollen verifizieren, dass Nextcloud im Container in einer rootless-Podman-Umgebung bereitgestellt werden kann. Da der Test unter Verwendung von Podman-Containern durchgeführt werden soll, müssen diese Container eine solche rootless-Podman-Umgebung bereitstellen.
Für RHEL 8 und RHEL 9 habe ich entsprechende Container-Images gefunden. Für Debian bin ich nicht fündig geworden und habe daher beschlossen, diese Container-Images selbst zu erstellen.
Buildah ist das Werkzeug meiner Wahl, da:
containerfile(5) benötigt undFür mich sind dies ausreichend Gründe, um mich kopfüber in ein neues Container-Projekt zu stürzen. Wer mehr über die Beziehung von Buildah zu Podman erfahren möchte, dem empfehle ich den englischsprachigen Artikel: Buildah and Podman Relationship von Tom Sweeney.
Um rootless Podman in einem Container zum Laufen zu bekommen, habe ich mich an dem englischsprachigen Artikel How to use Podman inside of a container von Dan Walsh orientiert. Das Ergebnis findet ihr in meinem GitHub-Repo tronde/container-image-forge.
Die folgenden Code-Blöcke zeigen Auszüge aus dem Skript buildah_create_debian_bookworm_with_rootless_podman.sh (Commit 7634ed8). Die enthaltenen Befehle werden unter dem jeweiligen Code-Block erläutert. Alle Befehle werden als normaler Benutzer ohne Root-Rechte ausgeführt.
# Name of target container image
tctri=debian_rootless_podman
# Get a base image
ctr=$(buildah from --pull=newer docker://docker.io/library/debian:bookworm)
tctri nimmt den Namen des Container-Images auf, welches ich erzeugen werdectr nimmt den Namen des Containers auf, welcher durch den buildah-from(1)-Befehl erzeugt wird; mit diesem Container wird im Folgenden gearbeitet--pull=newer sorgt dafür, dass das Image nur dann aus der angegebenen Registry heruntergeladen wird, wenn es aktueller als das evtl. lokal gespeicherte Image istbuildah run -- $ctr apt -y update
buildah run -- $ctr apt -y upgrade
buildah run -- $ctr apt -y install podman fuse-overlayfs libvshadow-utils libcap2-bin ca-certificates
buildah-run(1) werden Befehle innerhalb des Arbeits-Containers ausgeführtca-certificates wird benötigt, um später Container-Images aus einer Registry herunterladen zu könnenbuildah run -- $ctr useradd podman
buildah run -- $ctr sh -c "echo podman:1:999 > /etc/subuid"
buildah run -- $ctr sh -c "echo podman:1001:64535 >> /etc/subuid"
buildah run -- $ctr sh -c "echo podman:1:999 > /etc/subgid"
buildah run -- $ctr sh -c "echo podman:1001:64535 >> /etc/subgid"
buildah run -- $ctr setcap cap_setuid+epi /usr/bin/newuidmap
buildah run -- $ctr setcap cap_setgid+epi /usr/bin/newgidmap
podman erstellt/etc/sub[g,u]id habe ich mir aus dem ubi9/podman-Image abgeschautsetcap-Befehle sind notwendig, um rootless Podman ausführen zu können; ich habe sie durch Internetrecherche und Trial-and-Error zusammengestelltbuildah config -v /var/lib/containers $ctr
buildah config -v /home/podman/.local/share/containers $ctr
/var/lib/containers/home/podman/.local/share/containersbuildah run -- $ctr chown -R podman:podman /home/podman
buildah run -- $ctr sh -c "mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock"
buildah config --env _CONTAINERS_USERNS_CONFIGURED="" $ctr
podman bekommt ein HOME-Verzeichnisbuildah run -- $ctr apt -y reinstall uidmap
buildah run -- $ctr apt -y clean
buildah run -- $ctr rm -rf /var/lib/apt/lists/*
uidmap neu installiert werden, um ein UID/GID-Mapping sicherzustellen; dies scheint analog zur Neuinstallation der shadow-utils in Artikel [7] notwendig zu sein# Commit to an image
buildah commit --rm $ctr $tctri
# Alternative: Use this and add GPG fingerprint for image signing
# buildah commit --sign-by <fingerprint> --rm $ctr $tctri
# Tag the image just created
buildah tag $tctri $tctri:bookworm-$(date --iso)
buildah-commit(1) wird der Inhalt des Arbeits-Containers $ctr in ein Container-Image namens $tctri geschrieben--rm wird der Arbeits-Container entferntbuildah-tag(1) fügt dem Image einen Tag mit Datumsstempel hinzu; siehe auch: Recommendations for tagging and versioning container imagesDer Befehl buildah-commit(1) fügt dem neuen Image übrigens nur einen weiteren Layer hinzu, egal wie viele Befehle zuvor im Arbeits-Container ausgeführt wurden. Das erzeugte Image umfasst also die Layer des Basis-Image plus einen weiteren.
An diesem Punkt habe ich ein Basis-Image ausgewählt, mithilfe von buildah zusätzliche Software installiert, einen Benutzer hinzugefügt und ein neues Image erzeugt.
Um den Build-Prozess zu automatisieren, habe ich die notwendigen Befehle in Bash-Skripte geschrieben und unter https://github.com/Tronde/container-image-forge abgelegt.
Die fertigen Images halte ich in der Registry https://quay.io/repository/rhn-support-jkastnin/debian_rootless_podman vor. Fühlt euch frei, diese für eigene Experimente zu benutzen, doch verwendet sie nur mit Vorsicht in Produktion. Ich erzeuge diese Images nur nach Bedarf neu, so dass die veröffentlichen Versionen veraltet und voller Sicherheitslücken sein können.
Jetzt, wo die Images fertig sind, kann ich prüfen, ob sich rootless Podman darin auch wie gewünscht ausführen lässt.
Die Prozesse innerhalb des von meinem Container-Image instanziierten Containers laufen als Benutzer root. Um die Prozesse als Benutzer podman auszuführen, ist dies beim Aufruf von podman run explizit mit anzugeben. Der folgende Code-Block verdeutlicht dies und zeigt zugleich den ersten Fehler beim Versuch rootless Podman auszuführen.
]$ podman run --rm localhost/debian_rootless_podman:bookworm-2024-09-21 id
uid=0(root) gid=0(root) groups=0(root)
]$ podman run --rm --user podman localhost/debian_rootless_podman:bookworm-2024-09-21 id
uid=1000(podman) gid=1000(podman) groups=1000(podman)
]$ podman run --rm --security-opt label=disable --user podman --device /dev/fuse localhost/debian_rootless_podman:bookworm-2024-09-21 podman info
time="2024-09-21T18:43:35Z" level=error msg="running `/usr/bin/newuidmap 15 0 1000 1 1 1 999 1000 1001 64535`: newuidmap: write to uid_map failed: Operation not permitted\n"
Error: cannot set up namespace using "/usr/bin/newuidmap": exit status 1
Der Fehler deutet auf fehlende capabilities(7) hin. Um diese Hypothese zu testen, wiederhole ich den letzten Befehl mit der Option --privileged (siehe dazu podman-run(1)):
]$ podman run --rm --security-opt label=disable --user podman --device /dev/fuse --privileged localhost/debian_rootless_podman:bookworm-2024-09-21 podman info
host:
…
Damit funktioniert es. Leider geben sich viele Menschen an dieser Stelle mit dem Ergebnis zufrieden. Doch ich möchte diese Container nicht einfach mit --privileged ausführen. Also studiere ich die Manpage capabilities(7) und teste mich Stück für Stück heran, bis ich mit dem folgenden Kommando ebenfalls erfolgreich bin:
]$ podman run --rm --user podman --security-opt label=disable --device /dev/fuse --cap-add=setuid,setgid,sys_admin,chown localhost/debian_rootless_podman:bookworm-2024-09-21 podman info
host:
…
Dies ist schon deutlich besser, da dem Container hiermit deutlich weniger Privilegien eingeräumt werden müssen. Das Thema Container-Privilegien und capabilities(7) werde ich noch genauer untersuchen. Eventuell folgt dazu dann auch ein weiterer Artikel. Für den Moment ist das Ergebnis gut genug.
Incus jongliert Container und virtuelle Maschinen. Die neue Version kann einen Sub-Pfad eines Volumes als Disk verwenden und isolierte OVN-Netzwerke erzeugen.