TL;DR — Kurzzusammenfassung

Podman Compose für rootlose Container-Orchestrierung. Installieren, konfigurieren und von Docker Compose migrieren mit systemd, Quadlet und Buildah.

PODMAN COMPOSE — ROOTLOSE ORCHESTRIERUNG podman pod (rootloser Benutzer-Namespace) app (Node.js) Port: 3000 depends_on: db healthcheck: /health db (PostgreSQL) Port: 5432 Volume: pgdata:Z healthcheck: pg_isready redis (Cache) Port: 6379 Volume: redis-data healthcheck: ping systemd Quadlet Auto-Start User-Units Kein Root-Daemon — Container laufen als Ihr Benutzer über Linux-Namespaces

Podman Compose bringt den vertrauten Docker Compose-Workflow zur daemonlosen, rootlosen Podman-Container-Engine. Wenn Sie nach einer Docker-Alternative suchen, die keinen privilegierten Hintergrund-Daemon benötigt, keine Root-Angriffsfläche freilegt und sich nativ in systemd integriert, ist dieser Leitfaden genau das Richtige. Sie lernen, Podman und podman-compose zu installieren, rootlose Benutzer-Namespaces zu konfigurieren, bestehende Docker Compose-Projekte zu migrieren, Pods zu verwalten und den automatischen Start über Quadlet zu aktivieren.

Voraussetzungen

Stellen Sie sicher, dass Sie Folgendes haben:

  • Ein Linux-System: Ubuntu 22.04/24.04, Fedora 39+ oder RHEL/Rocky Linux 9
  • Ein normales Benutzerkonto (Root ist für den täglichen Betrieb nicht erforderlich)
  • Grundkenntnisse der Docker Compose YAML-Syntax
  • sudo-Zugriff nur für die Erstinstallation

Warum Podman Statt Docker?

Dockers Architektur basiert auf einem privilegierten Daemon (dockerd), der als Root läuft. Jeder docker CLI-Aufruf geht über einen Unix-Socket, der Root gehört. Das bedeutet, dass jeder Prozess, der auf den Docker-Socket zugreifen kann, effektiv Root auf dem Host hat.

Podman verfolgt einen grundlegend anderen Ansatz:

AspektDockerPodman
ArchitekturClient-Server-DaemonFork/exec, daemonlos
StandardberechtigungLäuft als RootRootlos standardmäßig
Compose-Unterstützungdocker compose Pluginpodman-compose oder podman compose
Image-FormatOCI (Docker-kompatibel)OCI (Docker-kompatibel)
Socket-Anforderung/var/run/docker.sock (Root)Optionaler Benutzer-Socket
systemd-IntegrationExterne Unit-DateienNativer Quadlet-Support
CLI-KompatibilitätReferenzimplementierungDrop-in (alias docker=podman)

Installation

Ubuntu 22.04 / 24.04

sudo apt update
sudo apt install -y podman
podman --version

Für Podman 5.x auf Ubuntu 22.04, fügen Sie das offizielle Kubic-Repository hinzu:

. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${VERSION_ID}/ /" \
  | sudo tee /etc/apt/sources.list.d/kubic-podman.list
curl -fsSL "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${VERSION_ID}/Release.key" \
  | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubic-podman.gpg
sudo apt update && sudo apt install -y podman

Fedora / RHEL / Rocky Linux

sudo dnf install -y podman          # Fedora
sudo dnf install -y container-tools # RHEL 9 / Rocky Linux 9

Drop-in Alias für Docker

sudo apt install -y podman-docker   # Ubuntu
sudo dnf install -y podman-docker   # Fedora/RHEL

Konfiguration Rootloser Container

Der rootlose Betrieb hängt von Linux-Benutzer-Namespaces und UID/GID-Zuordnungen ab, die in /etc/subuid und /etc/subgid definiert sind.

grep "^$(whoami)" /etc/subuid /etc/subgid

Falls die Einträge fehlen:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $(whoami)
podman system migrate
podman run --rm hello-world

Für Ports unter 1024:

echo 'net.ipv4.ip_unprivileged_port_start=80' | sudo tee /etc/sysctl.d/99-unprivileged-ports.conf
sudo sysctl --system

Installation von podman-compose

# Via pip (alle Distributionen)
pip install --user podman-compose
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Fedora / RHEL
sudo dnf install -y podman-compose

# Ubuntu
sudo apt install -y podman-compose

Podman 4.4+ enthält einen eingebauten podman compose-Unterbefehl, der automatisch an podman-compose oder docker-compose delegiert:

podman compose version

Erstellen einer compose.yaml für Podman

Podman Compose unterstützt die Compose-Spezifikation (v2/v3-Syntax). Ihre bestehenden docker-compose.yml-Dateien funktionieren ohne Änderungen in den meisten Fällen.

Vollständiges Produktions-Stack-Beispiel — Node.js-API mit PostgreSQL und Redis:

# compose.yaml
name: myapp

services:
  api:
    build:
      context: ./api
      dockerfile: Containerfile
    image: myapp-api:latest
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DATABASE_URL: "postgresql://appuser:${DB_PASSWORD}@db:5432/appdb"
      REDIS_URL: "redis://redis:6379"
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 20s
    volumes:
      - ./api/logs:/app/logs:Z
    networks:
      - backend
    restart: unless-stopped

  db:
    image: docker.io/library/postgres:16-alpine
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: "${DB_PASSWORD}"
    volumes:
      - pgdata:/var/lib/postgresql/data:Z
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - backend
    restart: unless-stopped

  redis:
    image: docker.io/library/redis:7-alpine
    command: redis-server --save 60 1 --loglevel warning
    volumes:
      - redis-data:/data:Z
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5
    networks:
      - backend
    restart: unless-stopped

networks:
  backend:
    driver: bridge

volumes:
  pgdata:
  redis-data:

Podman-spezifische Hinweise:

  • docker.io/library/-Präfix: Podman fügt Docker Hub nicht als implizites Registry hinzu. Verwenden Sie immer vollständig qualifizierte Image-Referenzen.
  • :Z-Volume-Label: Auf SELinux-fähigen Systemen (Fedora, RHEL, Rocky) kennzeichnet das Suffix :Z das Volume neu, damit der Container-Prozess darauf zugreifen kann.

Starten Sie den Stack:

podman-compose up -d
podman pod ps
podman ps
podman-compose logs -f api

Pod-Verwaltung

Wenn podman-compose einen Multi-Service-Stack startet, erstellt es einen Podman-Pod, der die Container gruppiert und einen Netzwerk-Namespace teilt:

podman pod ps
podman pod inspect myapp_default
podman pod stats myapp_default
podman-compose down
podman-compose down -v

Images mit Buildah und Containerfiles erstellen

# Containerfile
FROM docker.io/library/node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

FROM docker.io/library/node:22-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
RUN adduser -D -u 1001 appuser
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
podman build -t myapp-api:latest -f Containerfile ./api

systemd-Integration: Quadlet

Quadlet ist die moderne Methode, Podman-Container als systemd-Dienste auszuführen, ohne Unit-Dateien manuell schreiben zu müssen. Es ist ab Podman 4.4+ enthalten.

Erstellen Sie ~/.config/containers/systemd/myapp-db.container:

[Unit]
Description=MyApp Datenbank

[Container]
Image=docker.io/library/postgres:16-alpine
Environment=POSTGRES_DB=appdb
Environment=POSTGRES_USER=appuser
EnvironmentFile=%h/.config/myapp/db.env
Volume=%h/.local/share/myapp/pgdata:/var/lib/postgresql/data:Z
HealthCmd=pg_isready -U appuser -d appdb
HealthInterval=10s

[Service]
Restart=always

[Install]
WantedBy=default.target

Aktivieren:

systemctl --user daemon-reload
systemctl --user enable --now myapp-db
journalctl --user -u myapp-db -f
loginctl enable-linger $(whoami)

Vergleich: Compose-Orchestrierungstools

ToolRootlosDaemonsystemd-IntegrationCompose SpecKubernetes-Export
Docker ComposeNein (rootful)Ja (dockerd)Nur externVollständigNein
podman-composeJaNeinVia Quadletv2/v3Nein
podman composeJaNeinVia Quadletv2/v3Nein
Nerdctl + containerdTeilweiseJa (containerd)BegrenztVollständigNein
Podman QuadletJaNeinNativDeklarativVia podman kube generate
Kubernetes (k3s)TeilweiseJaExternVia KomposeJa (nativ)

Migration von Docker Compose

# Schritt 1 — Alias docker auf podman
alias docker=podman
alias docker-compose=podman-compose

echo "alias docker=podman" >> ~/.bashrc
echo "alias docker-compose=podman-compose" >> ~/.bashrc

Image-Referenzen aktualisieren:

# Vorher (Docker)
image: postgres:16-alpine

# Nachher (Podman Best Practice)
image: docker.io/library/postgres:16-alpine

Fügen Sie SELinux-Volume-Labels auf RHEL/Fedora-Systemen hinzu und entfernen Sie privileged: true wo möglich.

Besonderheiten und Fallstricke

Netzwerkunterschiede: Der rootlose Podman-Modus verwendet pasta/slirp4netns statt Kernel-Bridge-Netzwerke. Macvlan- und ipvlan-Netzwerke erfordern den Root-Modus.

Ports unter 1024: Rootlose Container können standardmäßig keine Host-Ports unter 1024 binden. Konfigurieren Sie net.ipv4.ip_unprivileged_port_start=80 oder verwenden Sie einen Reverse-Proxy.

docker.sock-Kompatibilität: Tools wie Portainer benötigen den Docker-Socket. Podman stellt einen kompatiblen Socket über podman system service bereit. Starten Sie mit systemctl --user start podman.socket.

SELinux-Verweigerungen: Wenn ein Volume-Mount auf RHEL/Fedora fehlschlägt, fügen Sie das :Z-Label hinzu. Deaktivieren Sie SELinux niemals.

Fehlerbehebung

“short-name resolution”-Fehler: Podman erfordert vollständig qualifizierte Image-Namen. Fügen Sie unqualified-search-registries = ["docker.io"] zu /etc/containers/registries.conf hinzu.

“newuidmap/newgidmap not found”: Installieren Sie das uidmap-Paket (sudo apt install uidmap).

Container erreicht das Internet nicht: Installieren Sie slirp4netns (sudo apt install slirp4netns) oder passt auf Ubuntu 24.04 (sudo apt install passt).

Zusammenfassung

  • Podman ist eine daemonlose, standardmäßig rootlose Container-Engine, die OCI-kompatibel und ein Drop-in für die Docker CLI ist
  • podman-compose unterstützt Compose Spec v2/v3 und führt Multi-Service-Stacks ohne Root-Rechte aus
  • Konfigurieren Sie /etc/subuid und /etc/subgid für rootlose UID-Zuordnung vor dem Ausführen von Multi-Container-Workloads
  • Verwenden Sie immer vollständig qualifizierte Image-Referenzen und fügen Sie :Z-Volume-Labels auf SELinux-Systemen hinzu
  • Quadlet bietet native systemd-Integration für automatischen Start und Journal-Protokollierung containerisierter Dienste
  • Für Produktions-Workloads bevorzugen Sie Quadlet gegenüber podman generate systemd für deklarative, wartbare Dienstdefinitionen

Verwandte Artikel