TL;DR — Résumé Rapide

Guide complet de Podman Compose pour l'orchestration rootless. Installez, configurez et migrez depuis Docker Compose avec systemd et Quadlet.

PODMAN COMPOSE — ORCHESTRATION ROOTLESS podman pod (espace de noms utilisateur rootless) 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 démarrage auto unités utilisateur Pas de daemon root — les conteneurs s'exécutent sous votre utilisateur via les espaces de noms

Podman Compose apporte le workflow familier de Docker Compose au moteur de conteneurs Podman, qui est sans daemon et rootless par défaut. Si vous cherchez une alternative à Docker qui ne nécessite pas de daemon privilégié en arrière-plan, n’expose pas de surface d’attaque root et s’intègre nativement à systemd, ce guide est fait pour vous. Vous apprendrez à installer Podman et podman-compose, configurer les espaces de noms utilisateur rootless, migrer des projets Docker Compose existants, gérer des pods et activer le démarrage automatique via Quadlet.

Prérequis

Avant de commencer, assurez-vous d’avoir :

  • Un système Linux : Ubuntu 22.04/24.04, Fedora 39+ ou RHEL/Rocky Linux 9
  • Un compte utilisateur normal (root n’est pas nécessaire pour les opérations quotidiennes)
  • Une connaissance de base de la syntaxe YAML de Docker Compose
  • Accès à sudo uniquement pour l’installation initiale

Pourquoi Utiliser Podman Plutôt que Docker?

L’architecture de Docker repose sur un daemon privilégié (dockerd) s’exécutant en tant que root. Chaque appel CLI docker passe par un socket Unix appartenant à root. Cela signifie que tout processus pouvant accéder au socket Docker dispose effectivement du root sur l’hôte.

Podman adopte une approche fondamentalement différente :

AspectDockerPodman
ArchitectureClient-serveur daemonFork/exec, sans daemon
Privilège par défautS’exécute en tant que rootRootless par défaut
Support ComposePlugin docker composepodman-compose ou podman compose
Format d’imageOCI (compatible Docker)OCI (compatible Docker)
Exigence de socket/var/run/docker.sock (root)Socket utilisateur optionnel
Intégration systemdFichiers d’unité externesSupport natif avec Quadlet
Compatibilité CLIImplémentation de référenceDrop-in (alias docker=podman)

Installation

Ubuntu 22.04 / 24.04

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

Pour Podman 5.x sur Ubuntu 22.04, ajoutez le dépôt officiel Kubic :

. /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

Alias Drop-in pour Docker

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

Configuration des Conteneurs Rootless

L’opération rootless dépend des espaces de noms utilisateur Linux et des mappages UID/GID définis dans /etc/subuid et /etc/subgid.

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

Si les entrées sont manquantes :

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

Pour les ports inférieurs à 1024 :

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

Installation de podman-compose

# Via pip (toutes distributions)
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+ inclut une sous-commande podman compose intégrée qui délègue automatiquement à podman-compose ou docker-compose :

podman compose version

Création d’un compose.yaml pour Podman

Podman Compose prend en charge la Spécification Compose (syntaxe v2/v3). Vos fichiers docker-compose.yml existants fonctionnent sans modification dans la grande majorité des cas.

Exemple complet de stack de production — API Node.js avec PostgreSQL et 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:

Notes spécifiques à Podman :

  • Préfixe docker.io/library/ : Podman n’ajoute pas Docker Hub comme registre implicite. Utilisez toujours des références d’images entièrement qualifiées.
  • Étiquette de volume :Z : Sur les systèmes SELinux (Fedora, RHEL, Rocky), le suffixe :Z réétiquette le volume pour que le processus conteneur puisse y accéder.

Démarrez le stack :

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

Gestion des Pods

Quand podman-compose démarre un stack multi-services, il crée un pod Podman qui regroupe les conteneurs et partage un espace de noms réseau :

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

Construction d’Images avec Buildah et Containerfiles

# 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

Intégration systemd : Quadlet

Quadlet est la méthode moderne pour exécuter des conteneurs Podman comme des services systemd sans écrire manuellement des fichiers d’unité. Il est inclus avec Podman 4.4+.

Créez ~/.config/containers/systemd/myapp-db.container :

[Unit]
Description=Base de données MyApp

[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

Activez :

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

Comparaison : Outils d’Orchestration Compose

OutilRootlessDaemonIntégration systemdCompose SpecExport Kubernetes
Docker ComposeNon (rootful)Oui (dockerd)Externe seulementCompletNon
podman-composeOuiNonVia Quadletv2/v3Non
podman composeOuiNonVia Quadletv2/v3Non
Nerdctl + containerdPartielOui (containerd)LimitéCompletNon
Podman QuadletOuiNonNatifDéclaratifVia podman kube generate
Kubernetes (k3s)PartielOuiExterneVia KomposeOui (natif)

Migration depuis Docker Compose

# Étape 1 — Alias docker vers podman
alias docker=podman
alias docker-compose=podman-compose

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

Mettez à jour les références d’images :

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

# Après (bonne pratique Podman)
image: docker.io/library/postgres:16-alpine

Cas Particuliers et Mises en Garde

Différences réseau : Le mode rootless de Podman utilise pasta/slirp4netns à la place des réseaux bridge du noyau. Les réseaux macvlan et ipvlan nécessitent le mode root.

Ports inférieurs à 1024 : Les conteneurs rootless ne peuvent pas lier des ports hôtes inférieurs à 1024 par défaut. Configurez net.ipv4.ip_unprivileged_port_start=80 ou utilisez un proxy inverse.

Compatibilité docker.sock : Des outils comme Portainer nécessitent le socket Docker. Podman le fournit via podman system service. Démarrez avec systemctl --user start podman.socket.

Refus SELinux : Si un montage de volume échoue sur RHEL/Fedora, ajoutez l’étiquette :Z. Ne désactivez jamais SELinux.

Résolution de Problèmes

Erreurs “short-name resolution” : Podman exige des noms d’images entièrement qualifiés. Ajoutez unqualified-search-registries = ["docker.io"] à /etc/containers/registries.conf.

“newuidmap/newgidmap not found” : Installez le paquet uidmap (sudo apt install uidmap).

Le conteneur n’accède pas à internet : Installez slirp4netns (sudo apt install slirp4netns) ou passt sur Ubuntu 24.04 (sudo apt install passt).

Résumé

  • Podman est un moteur de conteneurs sans daemon et rootless par défaut, compatible OCI et avec le CLI Docker
  • podman-compose prend en charge Compose Spec v2/v3 et exécute des stacks multi-services sans privilèges root
  • Configurez /etc/subuid et /etc/subgid pour le mappage UID rootless avant d’exécuter des charges de travail multi-conteneurs
  • Utilisez toujours des références d’images entièrement qualifiées et ajoutez des étiquettes de volume :Z sur les systèmes SELinux
  • Quadlet fournit une intégration native avec systemd pour le démarrage automatique et la journalisation des services conteneurisés
  • Pour les charges de travail en production, préférez Quadlet à podman generate systemd pour des définitions de services déclaratives et maintenables

Articles Connexes