ARCHITECTURE SANS DÉMON DE PODMAN Système d'exploitation Linux (Noyau : namespaces + cgroups) Sans Démon — fork/exec direct via conmon Conteneur 1 Sans root UID mappé Conteneur 2 Sans root UID mappé Pod (namespace réseau partagé) Conteneur 3 App :8080 Conteneur 4 BDD :5432 Chaque conteneur est un processus enfant — aucun démon central requis

Podman (Pod Manager) est un moteur de conteneurs open source et sans démon, développé par Red Hat, qui fournit une CLI compatible avec Docker pour construire, exécuter et gérer des conteneurs et pods OCI. Contrairement à Docker, Podman ne nécessite pas de démon en arrière-plan avec des privilèges root, ce qui le rend intrinsèquement plus sécurisé pour les postes de développement comme pour les serveurs de production. Si vous utilisez Docker et cherchez une alternative plus sécurisée, compatible avec systemd et qui exécute les conteneurs sous votre utilisateur standard, Podman est l’outil à adopter.

Ce guide couvre tout ce dont vous avez besoin pour démarrer avec Podman sur Ubuntu : installation, exécution de conteneurs sans root, gestion des images, création de pods, compatibilité Compose, intégration systemd, réseau et un parcours complet de migration depuis Docker.

Prérequis

Avant de commencer, assurez-vous d’avoir :

  • Un système sous Ubuntu 22.04 ou 24.04 (édition bureau ou serveur)
  • Un accès terminal avec des privilèges sudo
  • Une connexion internet stable
  • Une familiarité de base avec les conteneurs et la ligne de commande Linux
  • Au moins 2 Go d’espace disque libre pour les images

Remarque : Podman fonctionne sur n’importe quelle distribution Linux moderne, mais ce guide se concentre sur Ubuntu. Si vous migrez depuis Docker, aucune installation de Docker n’est nécessaire — Podman le remplace entièrement.

Qu’est-ce que Podman ?

Podman est un outil de gestion de conteneurs qui implémente la même interface CLI que Docker mais avec une architecture fondamentalement différente. Le nom vient de Pod Manager, reflétant son support natif des pods de style Kubernetes — des groupes de conteneurs partageant les namespaces réseau et IPC.

Caractéristiques principales de Podman :

  • Sans démon : Aucun service en arrière-plan ne s’exécute en root. Chaque commande podman lance les conteneurs directement comme processus enfants via conmon (le moniteur de conteneurs).
  • Sans root par défaut : Les conteneurs s’exécutent sous votre compte utilisateur standard en utilisant les user namespaces Linux, sans nécessiter de privilèges root.
  • Conforme OCI : Podman construit et exécute des images conformes à la spécification Open Container Initiative (OCI), garantissant une compatibilité totale avec les images et registres Docker.
  • Pods natifs : Podman peut regrouper les conteneurs en pods, reproduisant la sémantique des pods Kubernetes pour le développement et les tests locaux.
  • Intégration systemd : Podman génère des fichiers d’unité systemd à partir de conteneurs en cours d’exécution, facilitant la gestion du cycle de vie des conteneurs en tant que services système.

Podman vs Docker

Comprendre les différences architecturales entre Podman et Docker vous aide à prendre une décision éclairée et à planifier votre migration.

CaractéristiquePodmanDocker
ArchitectureSans démon (fork/exec)Client-serveur (démon dockerd)
Exigence rootSans root par défautNécessite un démon root (mode sans root optionnel)
Runtime de conteneurscrun / runc via conmoncontainerd + runc
Compatibilité CLIRemplacement direct (podman = docker)CLI native
Support des podsNatif (style Kubernetes)Non disponible
Support Composepodman-compose / podman composedocker compose (plugin intégré)
Intégration systemdNative (podman generate systemd)Nécessite des fichiers d’unité manuels
Format d’imageOCI / DockerOCI / Docker
Outil de constructionBuildah (intégré)BuildKit
Modèle de sécuritéPas de démon root, user namespacesDémon root, sans root optionnel
SocketOptionnel (podman.socket)Requis (docker.socket)

La différence la plus significative est le démon. Docker nécessite que le démon dockerd s’exécute en permanence en root, créant un point de défaillance unique et un vecteur potentiel d’escalade de privilèges. Podman élimine cela entièrement — lorsque vous exécutez podman run, il crée directement un nouveau processus pour le conteneur en utilisant conmon comme moniteur de conteneurs. Si Podman lui-même plante, les conteneurs en cours d’exécution continuent de fonctionner.

Installer Podman sur Ubuntu

Podman est disponible dans les dépôts officiels d’Ubuntu à partir d’Ubuntu 22.04. Installez-le avec ses outils de support :

sudo apt update
sudo apt install -y podman

Vérifiez l’installation :

podman --version

Sortie attendue :

podman version 4.9.3

Vérifiez les informations système pour confirmer que le mode sans root est disponible :

podman info --format '{{.Host.Security.Rootless}}'

Cela devrait retourner true lorsqu’exécuté en tant qu’utilisateur non root.

Pour la dernière version de Podman (si la version du dépôt Ubuntu est trop ancienne), vous pouvez ajouter le dépôt officiel Kubic :

sudo mkdir -p /etc/apt/keyrings
curl -fsSL "https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/Release.key" \
  | gpg --dearmor \
  | sudo tee /etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg > /dev/null

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg] \
  https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/ /" \
  | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list > /dev/null

sudo apt update
sudo apt install -y podman

Configurer les Registres de Conteneurs

Par défaut, Podman exige des noms d’images entièrement qualifiés (par ex., docker.io/library/nginx). Pour activer les noms courts comme nginx, configurez les registres de recherche non qualifiés :

sudo tee /etc/containers/registries.conf.d/00-unqualified-search.conf <<'EOF'
[registries.search]
registries = ['docker.io', 'quay.io', 'ghcr.io']
EOF

Alternativement, éditez /etc/containers/registries.conf et ajoutez les registres de recherche sous la section [registries.search].

Exécuter Votre Premier Conteneur

Avec Podman installé, exécutez un conteneur de test en tant qu’utilisateur standard (non root) :

podman run --rm docker.io/library/hello-world

Vous devriez voir le message familier “Hello from Docker!”, confirmant que Podman peut récupérer et exécuter des images OCI. Notez qu’aucun sudo n’est nécessaire.

Exécutez un conteneur interactif :

podman run -it --rm docker.io/library/ubuntu:24.04 bash

Dans le conteneur, vérifiez l’utilisateur :

whoami
# root (dans le user namespace du conteneur)
id
# uid=0(root) gid=0(root) groups=0(root)

Bien que vous apparaissiez comme root à l’intérieur du conteneur, vous vous exécutez en réalité en tant qu’utilisateur standard sur l’hôte. C’est la puissance des conteneurs sans root avec le mappage de user namespaces.

Quittez le conteneur avec exit ou Ctrl+D.

Conteneurs sans Root

Les conteneurs sans root sont la caractéristique déterminante de Podman. Comprendre leur fonctionnement vous aide à résoudre les problèmes de permissions et à concevoir des déploiements de conteneurs sécurisés.

Comment Fonctionnent les Conteneurs sans Root

Lorsque vous exécutez un conteneur en tant qu’utilisateur non root, Podman utilise les user namespaces Linux pour créer un environnement isolé où :

  1. Le processus du conteneur se voit comme root (UID 0) à l’intérieur du conteneur.
  2. Sur l’hôte, le processus s’exécute en tant qu’UID subordonné mappé depuis la plage autorisée de votre utilisateur.
  3. Le mappage est défini dans /etc/subuid et /etc/subgid.

Vérifiez les mappages d’UID/GID subordonnés de votre utilisateur :

cat /etc/subuid
# jc:100000:65536

cat /etc/subgid
# jc:100000:65536

Cela signifie que l’utilisateur jc peut mapper les UIDs 100000 à 165535 à l’intérieur des conteneurs. L’UID 0 du conteneur correspond à l’UID de votre utilisateur sur l’hôte, et les UIDs 1-65535 dans le conteneur correspondent aux UIDs 100000-165535 de l’hôte.

Vérifier le Fonctionnement sans Root

Exécutez un conteneur et vérifiez le processus depuis l’hôte :

podman run -d --name test-rootless docker.io/library/nginx:alpine

Depuis un autre terminal sur l’hôte :

ps aux | grep nginx
# jc  12345  ... nginx: master process

Le processus nginx s’exécute sous votre utilisateur (jc), pas en root. Si le conteneur était compromis, l’attaquant n’aurait que les privilèges de votre utilisateur — pas l’accès root à l’hôte.

Configurer les User Namespaces

Si /etc/subuid ou /etc/subgid ne contiennent pas d’entrées pour votre utilisateur, ajoutez-les :

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

Après avoir modifié ces fichiers, réinitialisez le stockage Podman pour appliquer les changements :

podman system migrate

Travailler avec les Images

Podman utilise le même format d’image que Docker et peut récupérer depuis n’importe quel registre conforme OCI.

Récupérer des Images

# Récupérer depuis Docker Hub
podman pull docker.io/library/nginx:alpine

# Récupérer depuis Quay.io
podman pull quay.io/podman/hello

# Récupérer depuis GitHub Container Registry
podman pull ghcr.io/actions/actions-runner:latest

Lister les Images

podman images

Sortie :

REPOSITORY                        TAG       IMAGE ID      CREATED       SIZE
docker.io/library/nginx           alpine    a2bd6d6e82f0  2 weeks ago   43.3 MB
quay.io/podman/hello              latest    5dd467fce50b  3 months ago  787 kB

Construire des Images

Podman utilise Containerfile (ou Dockerfile — les deux sont pris en charge) et Buildah en interne :

# Containerfile
FROM docker.io/library/python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]

Construisez l’image :

podman build -t my-python-app:latest .

Construire avec un nom de fichier spécifique :

podman build -f Containerfile.prod -t my-python-app:prod .

Pousser des Images vers un Registre

Étiquetez et poussez une image vers un registre :

podman tag my-python-app:latest quay.io/myuser/my-python-app:latest
podman login quay.io
podman push quay.io/myuser/my-python-app:latest

Supprimer des Images

# Supprimer une image spécifique
podman rmi docker.io/library/nginx:alpine

# Supprimer toutes les images inutilisées
podman image prune -a

Gestion des Pods

Les pods sont un concept emprunté à Kubernetes. Un pod regroupe un ou plusieurs conteneurs partageant le même namespace réseau, ce qui signifie qu’ils peuvent communiquer via localhost et partager les mappages de ports.

Créer un Pod

Créez un pod avec les mappages de ports définis au niveau du pod :

podman pod create --name my-web-pod -p 8080:80 -p 5432:5432

Ajouter des Conteneurs à un Pod

Ajoutez un conteneur nginx et un conteneur PostgreSQL au pod :

podman run -d --pod my-web-pod --name web-server docker.io/library/nginx:alpine

podman run -d --pod my-web-pod --name db-server \
  -e POSTGRES_PASSWORD=secretpass \
  -e POSTGRES_DB=appdb \
  docker.io/library/postgres:16-alpine

Les deux conteneurs partagent désormais le même namespace réseau. Le conteneur nginx peut se connecter à PostgreSQL sur localhost:5432, et les clients externes accèdent à nginx via host:8080.

Gérer les Pods

# Lister tous les pods
podman pod ls

# Afficher les détails du pod
podman pod inspect my-web-pod

# Arrêter tous les conteneurs d'un pod
podman pod stop my-web-pod

# Démarrer un pod
podman pod start my-web-pod

# Supprimer un pod et ses conteneurs
podman pod rm -f my-web-pod

Générer du YAML Kubernetes depuis des Pods

L’une des fonctionnalités uniques de Podman est la génération de manifestes Kubernetes à partir de pods en cours d’exécution :

podman generate kube my-web-pod > my-web-pod.yaml

Cela crée un fichier YAML compatible Kubernetes que vous pouvez déployer directement sur un cluster Kubernetes avec kubectl apply -f my-web-pod.yaml. Cela fait de Podman un excellent outil pour le développement local lorsque votre cible de production est Kubernetes.

Podman Compose

Podman prend en charge les fichiers Docker Compose pour les stacks d’applications multi-conteneurs. Il existe deux approches :

Utiliser podman-compose

Installez podman-compose (une réimplémentation communautaire en Python) :

sudo apt install -y python3-pip
pip3 install podman-compose

Utilisez-le comme docker-compose :

podman-compose up -d
podman-compose ps
podman-compose logs -f
podman-compose down

Utiliser la Commande Intégrée podman compose

Podman 4.7+ inclut une commande intégrée podman compose qui délègue à un fournisseur compose externe (docker-compose ou podman-compose) :

podman compose up -d
podman compose down

Exemple de docker-compose.yml

Un fichier docker-compose.yml standard fonctionne sans modification :

version: "3.8"
services:
  web:
    image: docker.io/library/nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api

  api:
    image: docker.io/library/node:20-alpine
    working_dir: /app
    volumes:
      - ./api:/app
    command: node server.js
    environment:
      - DB_HOST=db
      - DB_PORT=5432

  db:
    image: docker.io/library/postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: secretpass
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Exécuter avec Podman Compose :

podman-compose up -d

Générer des Unités systemd depuis des Conteneurs

Podman s’intègre avec systemd pour gérer les conteneurs en tant que services système. Cela est particulièrement utile pour les serveurs où vous avez besoin que les conteneurs démarrent au boot et redémarrent en cas d’échec.

Générer un Fichier d’Unité depuis un Conteneur en Cours d’Exécution

Tout d’abord, démarrez un conteneur :

podman run -d --name my-nginx -p 8080:80 docker.io/library/nginx:alpine

Générez l’unité systemd :

podman generate systemd --new --name my-nginx > ~/.config/systemd/user/container-my-nginx.service

L’option --new garantit que le fichier d’unité crée un conteneur neuf à chaque fois (plutôt que de redémarrer un conteneur existant), ce qui est la pratique recommandée.

Activer et Démarrer le Service

mkdir -p ~/.config/systemd/user
systemctl --user daemon-reload
systemctl --user enable --now container-my-nginx.service

Activer le Lingering pour les Sessions non Interactives

Par défaut, les services systemd utilisateur s’arrêtent lorsque l’utilisateur se déconnecte. Activez le lingering pour les maintenir en fonctionnement :

sudo loginctl enable-linger $USER

Vérifier le Service

systemctl --user status container-my-nginx.service

Quadlet (Podman 4.4+)

Pour Podman 4.4 et ultérieur, Quadlet fournit un format déclaratif plus simple. Créez un fichier .container dans ~/.config/containers/systemd/ :

# ~/.config/containers/systemd/my-nginx.container
[Container]
Image=docker.io/library/nginx:alpine
PublishPort=8080:80
Volume=./html:/usr/share/nginx/html:ro

[Service]
Restart=always

[Install]
WantedBy=default.target

Rechargez systemd et démarrez le service :

systemctl --user daemon-reload
systemctl --user start my-nginx.service

Migrer de Docker vers Podman

Si vous utilisez actuellement Docker, le parcours de migration vers Podman est simple.

Installer le Paquet de Compatibilité Docker

sudo apt install -y podman-docker

Cela installe une commande docker qui est un alias vers podman et crée un socket d’émulation /var/run/docker.sock. Les scripts existants qui appellent docker utiliseront Podman à la place.

Migrer les Images Docker

Exportez les images depuis Docker et importez-les dans Podman :

# Sur le système Docker
docker save my-app:latest -o my-app.tar

# Sur le système Podman
podman load -i my-app.tar

Convertir les Fichiers Docker Compose

La plupart des fichiers docker-compose.yml fonctionnent sans modification. Les principaux ajustements à surveiller :

  1. Qualifier entièrement les noms d’images : Remplacez nginx:alpine par docker.io/library/nginx:alpine
  2. Mode réseau : Certains modes réseau spécifiques à Docker peuvent différer
  3. Plugins de volumes : Les plugins de volumes Docker ne sont pas pris en charge ; utilisez les pilotes de volumes natifs de Podman

Mettre à Jour les Pipelines CI/CD

Remplacez les commandes docker par podman dans vos scripts de pipeline, ou installez podman-docker pour que l’alias docker s’en charge :

# Exemple GitHub Actions
steps:
  - name: Install Podman
    run: sudo apt install -y podman podman-docker

  - name: Build image
    run: podman build -t my-app:${{ github.sha }} .

  - name: Push image
    run: |
      podman login -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_PASS }} ghcr.io
      podman push my-app:${{ github.sha }} ghcr.io/${{ github.repository }}:${{ github.sha }}

Réseau

Le modèle réseau de Podman diffère entre les modes avec root et sans root.

Réseau sans Root

En mode sans root, Podman utilise slirp4netns ou pasta (Podman 5.0+) pour fournir la connectivité réseau sans privilèges root :

  • slirp4netns : Crée un périphérique TAP dans un user namespace, fournissant un réseau basé sur NAT. La redirection de ports au-dessus de 1024 fonctionne sans root.
  • pasta : Une alternative plus récente et plus rapide offrant de meilleures performances et une surcharge réduite.

Mapper des ports en mode sans root :

podman run -d -p 8080:80 docker.io/library/nginx:alpine

Remarque : Le binding aux ports inférieurs à 1024 (par ex., 80, 443) nécessite des privilèges root ou l’ajustement du seuil de ports non privilégiés avec sudo sysctl net.ipv4.ip_unprivileged_port_start=80.

CNI et Netavark

Podman prend en charge deux backends réseau :

  • CNI (Container Network Interface) : Le backend historique utilisant les plugins CNI.
  • Netavark : La pile réseau moderne basée sur Rust (par défaut dans Podman 4.0+).

Créer un réseau personnalisé :

podman network create my-network

Exécuter des conteneurs sur le réseau personnalisé :

podman run -d --network my-network --name container-a docker.io/library/alpine sleep 3600
podman run -d --network my-network --name container-b docker.io/library/alpine sleep 3600

Les conteneurs sur le même réseau peuvent se joindre par nom :

podman exec container-a ping -c 3 container-b

Inspecter les Réseaux

# Lister les réseaux
podman network ls

# Inspecter un réseau
podman network inspect my-network

# Supprimer un réseau
podman network rm my-network

Référence des Commandes Podman

Le tableau suivant liste les commandes Podman les plus utilisées et leurs équivalents Docker :

Commande PodmanÉquivalent DockerDescription
podman rundocker runCréer et démarrer un conteneur
podman psdocker psLister les conteneurs en cours d’exécution
podman ps -adocker ps -aLister tous les conteneurs
podman imagesdocker imagesLister les images locales
podman pulldocker pullRécupérer une image depuis un registre
podman builddocker buildConstruire une image depuis un Containerfile/Dockerfile
podman pushdocker pushPousser une image vers un registre
podman execdocker execExécuter une commande dans un conteneur en cours d’exécution
podman logsdocker logsAfficher les journaux du conteneur
podman stopdocker stopArrêter un conteneur en cours d’exécution
podman rmdocker rmSupprimer un conteneur
podman rmidocker rmiSupprimer une image
podman volume createdocker volume createCréer un volume nommé
podman network createdocker network createCréer un réseau
podman pod createN/ACréer un pod
podman pod lsN/ALister les pods
podman generate systemdN/AGénérer des fichiers d’unité systemd
podman generate kubeN/AGénérer du YAML Kubernetes
podman system prunedocker system pruneSupprimer les données inutilisées
podman logindocker loginSe connecter à un registre de conteneurs
podman inspectdocker inspectAfficher les informations détaillées d’un conteneur/image

Dépannage

Erreur : short-name resolution enforced

Problème : Podman refuse de récupérer une image en utilisant un nom court comme nginx.

Solution : Utilisez le nom d’image entièrement qualifié ou configurez les registres de recherche :

# Utiliser le nom entièrement qualifié
podman pull docker.io/library/nginx:alpine

# Ou configurer les registres de recherche
sudo tee /etc/containers/registries.conf.d/00-unqualified-search.conf <<'EOF'
[registries.search]
registries = ['docker.io', 'quay.io']
EOF

Erreur : cannot find UID/GID mapping

Problème : Les conteneurs sans root échouent car les mappages d’UID/GID subordonnés ne sont pas configurés.

Solution : Ajoutez les mappages pour votre utilisateur :

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
podman system migrate

Erreur : permission denied on volume mount

Problème : Un conteneur sans root ne peut pas accéder à un répertoire monté en bind.

Solution : Ajoutez le suffixe d’étiquette SELinux :Z ou :z, ou assurez-vous que le répertoire appartient à votre utilisateur :

# Corriger la propriété
podman unshare chown -R 0:0 /path/to/volume

# Ou utiliser le flag Z pour SELinux
podman run -v /path/to/volume:/data:Z my-image

Le Conteneur ne Peut pas se Lier au Port 80

Problème : Podman sans root ne peut pas se lier aux ports inférieurs à 1024.

Solution : Abaissez la valeur du seuil de ports non privilégiés :

sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80
# Rendre persistant
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/99-podman-ports.conf
sudo sysctl --system

Podman Compose Échoue avec une Erreur Réseau

Problème : podman-compose génère des erreurs lors de la création de réseaux.

Solution : Assurez-vous que le backend réseau de Podman fonctionne et réinitialisez si nécessaire :

podman network ls
podman system reset --force
# Recréez vos conteneurs après la réinitialisation

Les Conteneurs ne Démarrent pas Après le Redémarrage

Problème : Les conteneurs systemd au niveau utilisateur ne démarrent pas après un redémarrage.

Solution : Activez le lingering pour votre utilisateur :

sudo loginctl enable-linger $USER

Téléchargement Lent des Images

Problème : Le téléchargement des images est lent en mode sans root.

Solution : Activez fuse-overlayfs pour de meilleures performances de stockage :

sudo apt install -y fuse-overlayfs

Vérifiez qu’il est utilisé :

podman info --format '{{.Store.GraphDriverName}}'
# Devrait afficher : overlay

Résumé

Podman est un moteur de conteneurs mature, sécurisé et compatible avec Docker qui élimine le besoin d’un processus démon privilégié. Son approche sans root par défaut, le support natif des pods et l’intégration systemd en font un excellent choix pour les environnements Linux de développement et de production. Pour quiconque exécute des conteneurs sur des serveurs Linux, Podman offre un avantage de sécurité évident sans sacrifier la compatibilité avec l’écosystème Docker.

Dans ce guide, vous avez appris à installer Podman sur Ubuntu, exécuter des conteneurs sans root, gérer des images et des pods, utiliser Podman Compose avec des fichiers docker-compose.yml existants, générer des unités systemd pour la gestion automatique du cycle de vie des conteneurs, configurer le réseau et migrer depuis Docker.

Pour des sujets liés aux conteneurs, consultez nos guides sur Comment Installer Docker sur Ubuntu et Docker Compose : Guide Pratique pour les Administrateurs Système.