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 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 à
sudouniquement 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 :
| Aspect | Docker | Podman |
|---|---|---|
| Architecture | Client-serveur daemon | Fork/exec, sans daemon |
| Privilège par défaut | S’exécute en tant que root | Rootless par défaut |
| Support Compose | Plugin docker compose | podman-compose ou podman compose |
| Format d’image | OCI (compatible Docker) | OCI (compatible Docker) |
| Exigence de socket | /var/run/docker.sock (root) | Socket utilisateur optionnel |
| Intégration systemd | Fichiers d’unité externes | Support natif avec Quadlet |
| Compatibilité CLI | Implémentation de référence | Drop-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:Zréé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
| Outil | Rootless | Daemon | Intégration systemd | Compose Spec | Export Kubernetes |
|---|---|---|---|---|---|
| Docker Compose | Non (rootful) | Oui (dockerd) | Externe seulement | Complet | Non |
| podman-compose | Oui | Non | Via Quadlet | v2/v3 | Non |
podman compose | Oui | Non | Via Quadlet | v2/v3 | Non |
| Nerdctl + containerd | Partiel | Oui (containerd) | Limité | Complet | Non |
| Podman Quadlet | Oui | Non | Natif | Déclaratif | Via podman kube generate |
| Kubernetes (k3s) | Partiel | Oui | Externe | Via Kompose | Oui (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/subuidet/etc/subgidpour 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
:Zsur 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 systemdpour des définitions de services déclaratives et maintenables