Podman statt Docker

Dokumentation

Podman arbeitet im Gegensatz zu Docker auch im User-Kontext und ohne root Rechte. Man kann einzelne oder mehrere Container starten - analog zu docker compose. Podman nutzt dafür „pods“, das Konzept ähnelt den Pods in Kubernetes, ist aber weniger komplex. Die Grund-Kommandos sind an den meisten Stellen identisch zu docker, z.B. der Pull Befehl für Images

podman pull docker.io/library/mariadb:11
podman pull docker.io/library/phpmyadmin

Pods

„Pods“ sind Gruppen von funktional miteinander verbundenen Containern. Jeder Pod enthält automatisch einen infra Container. Der infra Container verwaltet die mit dem Pod verbundenen Namespaces und verbindet andere Container mit dem Pod. Das Netzwerk der Container wird zentral über den Pod verwaltet, deshalb muss man die gewünschten Ports beim Anlegen des Ports mit angeben, nicht beim Anlegen des Containers.

Pod erstellen und Container hinzufügen

:information_source: Wenn Container in einem pod laufen, wird der Netzwerk Stack im pod verwaltet. Daher muss man beim Hinzufügen des Containers zum pod nicht nochmal einen port mit -p xxx:yyy angeben. Pod und Container sollten nicht die gleichen Namen haben, das gibt später Ärger beim Einbinden in systemd,

Dieser Pod horcht auf 8082 auf dem Host, der interne Container benutzt 8080

podman pod create --name bentopod -p 8082:8080

Hier wird ein einziger Container hinzugefügt

podman run -d --pod bentopdf --name bentopdf ghcr.io/alam00000/bentopdf-simple:latest

Mehrere Container im Pod

Wenn man Container in einem Pod kombiniert, werden alle Ports, die nach außen sichtbar sind, beim Erstellen des Pods angegeben

podman pod create --name mariapod -p 8080:80 -p 3306:3306 -p 8081:8081

Hier wird ein mariadb Pod und ein Container angelegt, mit root PW, Zusatz-Datenbank und Volume, auf dem die persistenten Daten der Datenbank liegen. Die Konfigurations-Parameter werden über Umgebungsvariablen mit „-e“ mit gegeben.

podman run -d --pod mariapod --name mariadb -e MYSQL_ROOT_PASSWORD=xxxxxx -e MYSQL_DATABASE=digikam -e MYSQL_USER=digikam -e MYSQL_PASSWORD=digikam -v mariadb-data:/var/lib/mysql:Z mariadb

Note: If a container runs within a pod, it is not necessary to publish the port for the containers in the pod. The port must only be published by the pod itself. Pod network stacks act like the network stack on the host - meaning a variety of containers in the pod and programs in the container all share a single interface, IP address, and associated ports. If one container binds to a port, no other container can use that port within the pod while it is in use. Containers in the pod can also communicate over localhost by having one container bind to localhost in the pod, and another connect to that port.

pods auflisten

root@thommienas:~# podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
476fef331c3d filebrowser Running 2 hours ago 1f56dd2075f4 2
95448d0dd264 photoprism Running 2 hours ago 667e2e08056e 3
88f7cfbd1101 mariadb Exited 5 weeks ago 3d564fc35f6e 3

phpmysql Pod Container und Pod

Pod erstellen. Der Apache im Container horcht auf Port 8081. Dieser Port wurde bei podman pod create mit -p 8081:8081 mit gegeben.

podman pod create --name phpmysgl -p 8080:80 -p 3306:3306 -p 8081:8081

podman run -d --pod phpmysgl --name phpmyadmin -e PMA_HOST=127.0.0.1 -e PMA_PORT=3306 -e APACHE_PORT=8081 phpmyadmin:latest

Volumes

Volumes für Daten eines Containers, die zwischen Neustarts des Containers ausserhalb des overlay Speichers persistent gehalten werden,. erzeugt man analog zu dockert

podman volume create mariadb-data

Container betreten

Auch das läuft analog zu docker

root@thommienas:/# podman exec -it 81c9ba1625db mariadb -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 12.3.2-MariaDB-ubu2404 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

Datenbanken im Container zeigen

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.000 sec)

Pod inspizieren

Mit inspect bekomtm man eine Übersicht über die Grundkonfiguration des pods und alle darin enthaltenen Container inklusive des „infra“ Containers

podman pod inspect mariadb

Welche Container sind im Pod

podman pod inspect mariadb --format '{{range .Containers}}{{.Id}}{{"\n"}}{{end}}'

Namen und IDs

podman pod inspect my-pod --format '{{range .Containers}}{{.Name}} ({{.Id}}){{"\n"}}{{end}}'

Podman Netzwerke

podman pod inspect mariadb --format '{{.InfraConfig}}'
{map[3306/tcp:[{0.0.0.0 3306}] 80/tcp:[{0.0.0.0 8080}] 8081/tcp:[{0.0.0.0 8081}]] false <nil> false [] [] [] false false [
] [podman] map[] 0 0 private host private}

Port Bindings

root@thommienas:~# podman pod inspect mariadb0 --format '{{.InfraConfig.PortBindings}}'
map[3306/tcp:[{0.0.0.0 3306}] 80/tcp:[{0.0.0.0 8080}]]

Podman Netzwerke

Liste der Netzwerke

root@omv:/etc/podman# podman network ls

Infos über die Ports im pod gibt der inspect Schalter

root@omv:/etc/podman# podman pod inspect bentopdf

[
{
"Id": "3782c6a31e080136a9f61d4d83acd882424ba5fb8661b40d120dfd51233486e1",
"Name": "bentopdf",
"Created": "2026-09-20T21:14:08.908182528+02:00",
"CreateCommand": [
"podman",
"pod",
"create",
"--name",
"bentopdf",
"-p",
"8082:8080"
],
"ExitPolicy": "continue",
"State": "Running",
"Hostname": "",
"CreateCgroup": true,
"CgroupParent": "machine.slice",
"CgroupPath": "machine.slice/machine-libpod_pod_3782c6a31e080136a9f61d4d83acd882424ba5fb8661b40d120dfd51233486e1.slice",
"CreateInfra": true,
"InfraContainerID": "10ae35edfb776957ac66f434f3d3f15f39b44b499fc5fba4a5cbc23d7abe917a",
"InfraConfig": {
"PortBindings": {
"8080/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "8082"
}
]
},
"HostNetwork": false,
"StaticIP": "",
"StaticMAC": "",
"NoManageResolvConf": false,
"DNSServer": null,
"DNSSearch": null,
"DNSOption": null,
"NoManageHostname": false,
"NoManageHosts": false,
"HostAdd": null,
"HostsFile": "",
"Networks": [
"podman"
],
"NetworkOptions": null,
"pid_ns": "private",
"userns": "host",
"uts_ns": "private"
},
"SharedNamespaces": [
"ipc",
"net",
"uts"
],
"NumContainers": 2,
"Containers": [
{
"Id": "10ae35edfb776957ac66f434f3d3f15f39b44b499fc5fba4a5cbc23d7abe917a",
"Name": "3782c6a31e08-infra",
"State": "running"
},
{
"Id": "9abc6dbccc9d1c0bce92d715377edef6a3e14b841fb5d82e69dec60b8c464970",
"Name": "bentopdf",
"State": "running"
}
],
"LockNumber": 0
}
]

Systemd

Mit podman generate kann man für einen Pod zur Laufzeit ein systemd-fähige .pod Datei erzeugen.
root@omv:/etc/containers/systemd# podman generate systemd bentopod

Allerdings macht man das mitterweile mit quadlets

DEPRECATED command:
It is recommended to use Quadlets for running containers and pods under systemd.
Please refer to podman-systemd.unit(5) for details.

pod-d958d6c311806e75959303a416b0ec55008b540b0186823aebe19baf8c94cff9.service
autogenerated by Podman 5.4.2
Mon Sep 21 16:37:53 CEST 2026

[Unit]
Description=Podman pod-d958d6c311806e75959303a416b0ec55008b540b0186823aebe19baf8c94cff9.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/containers/storage
Wants=container-3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581.service
Before=container-3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman start 1f93dadee117414e7314f61aaa4e5de058ba0a486d4642cd90689dbc7431722c
ExecStop=/usr/bin/podman stop \
-t 10 1f93dadee117414e7314f61aaa4e5de058ba0a486d4642cd90689dbc7431722c
ExecStopPost=/usr/bin/podman stop \
-t 10 1f93dadee117414e7314f61aaa4e5de058ba0a486d4642cd90689dbc7431722c
PIDFile=/run/containers/storage/overlay-containers/1f93dadee117414e7314f61aaa4e5de058ba0a486d4642cd90689dbc7431722c/userda
ta/conmon.pid
Type=forking

[Install]
WantedBy=default.target
# container-3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581.service
# autogenerated by Podman 5.4.2
# Mon Sep 21 16:37:53 CEST 2026

[Unit]
Description=Podman container-3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/containers/storage
BindsTo=pod-d958d6c311806e75959303a416b0ec55008b540b0186823aebe19baf8c94cff9.service
After=pod-d958d6c311806e75959303a416b0ec55008b540b0186823aebe19baf8c94cff9.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman start 3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581
ExecStop=/usr/bin/podman stop \
-t 10 3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581
ExecStopPost=/usr/bin/podman stop \
-t 10 3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581
PIDFile=/run/containers/storage/overlay-containers/3511c9f5e7485a90c73bff85da9f2069b686bfb5714cd3165bbc516668fdc581/userda
ta/conmon.pid
Type=forking

[Install]
WantedBy=default.target

Quadlets

Der Autostart von pods (oder Containern) erfolgt über /usr/libexec/podman/quadlet mit systemd. Dazu wird eine .pod Datei ins Verzeichnis /etc/containers/systemd/ gelegt, die von quadlet eingelesen wird. Die nötigen systemd service files werden von podman über einen systemd generator (quadlet) erzeugt, wenn systemctl daemon-reload ausgelöst wird.

Doku:

[1] Make systemd better for Podman with Quadlet

[2] Moving from docker-compose to Podman pods

[3] podman-quadlet-install — Podman documentation

[4]https://www.techtutorials.tv/sections/podman/podman-and-quadlets/

[5]podman pod automatisieren: als service starten & updaten

Test

Über /usr/libexec/podman/quadlet -dryrun

kann man die Erstellung der service Files testen:

quadlet-generator[40023]: Loading source unit file /etc/containers/systemd/bentopdf.pod
---bentopdf-pod.service---
[X-Pod]
PodName=bentopdf
PublishPort=8082:8080

[Service]
Restart=on-failure
SyslogIdentifier=%N
ExecStart=/usr/bin/podman pod start --pod-id-file=%t/%N.pod-id
ExecStop=/usr/bin/podman pod stop --pod-id-file=%t/%N.pod-id --ignore --time=10
ExecStopPost=/usr/bin/podman pod rm --pod-id-file=%t/%N.pod-id --ignore --force
ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile=%t/%N.pid --pod-id-file=%t/%N.pod-id --exit-policy=
stop --replace --publish 8082:8080 --infra-name bentopdf-infra --name bentopdf
Environment=PODMAN_SYSTEMD_UNIT=%n
Type=forking
PIDFile=%t/%N.pid

[Install]
WantedBy=default.target

[Unit]
Wants=network-online.target
After=network-online.target
SourcePath=/etc/containers/systemd/bentopdf.pod
RequiresMountsFor=%t/containers


  1. Fußnoten ↩︎

  2. Fußnoten ↩︎

  3. Fußnoten ↩︎

  4. Fußnoten ↩︎

  5. Fußnoten ↩︎