Skip to content
Learni
Voir tous les tutoriels
DevOps

Comment maîtriser Podman expert en 2026

Read in English

Introduction

Podman, l'outil conteneurs daemonless de Red Hat, révolutionne les déploiements en 2026 grâce à son mode rootless natif, sa compatibilité OCI et son intégration Kubernetes. Contrairement à Docker, Podman n'utilise pas de démon privilégié, éliminant les vulnérabilités root et simplifiant les environnements prod multi-utilisateurs.

Ce tutoriel expert cible les DevOps seniors : on passe des pods multi-containers aux quadlets systemd pour services persistants, en intégrant secrets TLS et podman play kube. Pourquoi c'est crucial ? En prod, 70% des breaches viennent de daemons ; Podman réduit ce risque à zéro tout en supportant Compose et Buildah.

Apprenez à configurer storage cgroups v2, networks macvlan, et monitorer avec podman stats. À la fin, déployez un stack NGINX-Postgres rootless scalable. Temps estimé : 2h pour un setup pro bookmarquable. (142 mots)

Prérequis

  • OS : Fedora 40+, RHEL 9+, Ubuntu 24.04 (cgroups v2 activé : systemd.unified_cgroup_hierarchy=1 dans GRUB)
  • Utilisateur : Non-root avec subUID/subGID (vérifiez id -u et /etc/subuid)
  • Connaissances : Docker CLI, YAML Kubernetes, systemd units
  • Outils : podman 5.0+ (dnf install podman ou apt install podman), buildah, skopeo optionnels
  • Espace disque : 10GB pour images/layers

Installer et configurer Podman rootless

terminal-install.sh
#!/bin/bash
# Fedora/RHEL
dnf install -y podman podman-compose buildah skopeo fuse-overlayfs

# Ubuntu
# apt update && apt install -y podman podman-compose buildah skopeo fuse-overlayfs

# Activer linger pour services persistants
loginctl enable-linger $USER

# Config storage rootless (fuse-overlayfs pour perf)
mkdir -p ~/.config/containers
cat > ~/.config/containers/storage.conf << EOF
[storage]
driver = "overlay"
runroot = "/run/user/$(id -u)/containers"
graphroot = "/home/$(id -u)/.local/share/containers/storage"
[storage.options.overlay]
ignore_sizes = true
mount_program =
/usr/bin/fuse-overlayfs
mountopt = "nodev=ro,nosuid,size=100000k"
EOF

# Vérifier
podman info | grep -E 'cgroup|rootless'

Ce script installe Podman et dépendances, configure le storage fuse-overlayfs pour rootless haute perf (évite perf loss vs overlayfs natif). enable-linger permet pods persistants post-logout. Vérifiez podman info : doit montrer 'rootless' et cgroup v2. Piège : sans subUID, podman run faille avec 'permission denied'.

Vérification et premier container

Exécutez le script ci-dessus. Analogie : Podman est comme un 'Docker personnel' sans root, chaque user son namespace isolé. Testez avec podman run --rm alpine echo 'Podman OK'. Prochaine étape : pods pour multi-services.

Créer un pod multi-containers

terminal-pod.sh
#!/bin/bash
# Créer pod avec NGINX + sidecar logs
podman pod create --name monpod -p 8080:80 --hostname monpod

# NGINX principal
podman run -d --pod monpod --name nginx \
  docker.io/nginx:alpine \
  sh -c 'echo "<h1>Podman Expert 2026</h1>" > /usr/share/nginx/html/index.html && nginx -g "daemon off;"'

# Sidecar logs vers volume partagé
podman run -d --pod monpod --name logsidecar \
  docker.io/alpine \
  sh -c 'while true; do echo "$(date)" >> /shared/logs.txt; sleep 5; done'

# Volume pour partage intra-pod
podman volume create sharedlogs
podman run -d --pod monpod --name logsidecar \
  -v sharedlogs:/shared \
  docker.io/alpine \
  sh -c 'while true; do echo "$(date)" >> /shared/logs.txt; sleep 5; done'

# Inspecter
podman pod ps
podman logs monpod -f

Crée un pod (Kubernetes-like) avec NGINX exposé 8080 et sidecar logs persistant via volume. --pod lie containers au même network/pid/cgroup. Accédez http://localhost:8080. Piège : sans volume, logs perdus au restart ; utilisez podman volume ls pour lister.

Gestion avancée pods et networks

Pods partagent IPC/net/UTS comme un mini-K8s. Pour prod, ajoutez macvlan : podman network create -d macvlan -o parent=eth0 macnet. Analogie : pod = appartement partagé, containers = pièces communicantes via localhost.

Build image multi-stage personnalisée

Containerfile
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/bin/server .

FROM alpine:3.20
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/bin/server .
EXPOSE 3000
USER 1001
CMD ["./server"]

Containerfile (pas Dockerfile) pour build Go app multi-stage rootless. USER 1001 sécurise non-root. Build : podman build -t monapp:v1 .. Lancez podman run -d -p 3000:3000 --userns=keep-id monapp:v1. Piège : sans CGO_ENABLED=0, binaire trop gros ; testez layers avec podman image inspect.

Build et push avec Podman

terminal-build.sh
#!/bin/bash
# Avec Containerfile ci-dessus
podman build -t localhost/monapp:v1 .
podman run -d --name testapp -p 3000:3000 monapp:v1
curl localhost:3000

# Network macvlan pour prod-like
podman network create -d macvlan -o parent=lo macnet
podman network exists macnet && podman run -d --network macnet --ip 192.168.100.10 monapp:v1

# Export OCI vers registry (ex Quay.io)
# podman tag monapp:v1 quay.io/user/monapp:v1
# podman push quay.io/user/monapp:v1

podman ps -a

Build, run avec userns keep-id (mappe UID host), network macvlan pour IP dédiée. Curl teste endpoint. Piège : sans --userns=keep-id, volumes host fail en rootless ; podman system prune nettoie.

Intégration Kubernetes avec play kube

Podman importe YAML K8s natif. Créez pod-kube.yaml pour stacks complexes.

Podman play kube depuis YAML

pod-kube.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubepod
  labels:
    app: demo
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: /shared
      name: sharedvol
  - name: busybox
    image: busybox:1.36
    command: ['sh', '-c', 'while true; do echo "Log $(date)" >> /shared/app.log; sleep 10; done']
    volumeMounts:
    - mountPath: /shared
      name: sharedvol
  volumes:
  - name: sharedvol
    emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: kubepod-svc
spec:
  selector:
    app: demo
  ports:
  - port: 80
    targetPort: 80

YAML K8s Pod+Service valide. podman play kube pod-kube.yaml déploie rootless. Exposez podman play kube --service kubepod-svc. Piège : volumes emptyDir non-persistants ; mappez host vols avec hostPath.

Exécuter play kube et monitorer

terminal-kube.sh
#!/bin/bash
podman play kube pod-kube.yaml
podman kube play --service kubepod-svc

# Monitorer
podman pod ps
podman stats kubepod
podman logs kubepod/nginx

# Scale (Podman 5+)
podman play kube --replicas 3 pod-kube.yaml

# Cleanup
podman kube down pod-kube.yaml

Déploie YAML, expose service, stats cgroup/CPU. Scale replicas pour HA. Piège : sans --replicas, mono-instance ; podman events --filter pod=kubepod pour logs live.

Quadlets pour intégration systemd

Quadlets = units systemd auto-générées depuis .container/.pod files. Placez dans ~/.config/containers/systemd/. Analogie : cron meets Docker Compose.

Quadlet pod avec secrets

~/.config/containers/systemd/monpod.pod
[Pod]
PodName=monpod
PublishPort=8080:80
PublishPort=5432:5432
Network=macnet

[Container]nginx
Image=docker.io/nginx:alpine
Environment=NGINX_PORT=80

[Container]postgres
Image=postgres:16-alpine
Environment=POSTGRES_PASSWORD=secret123
Environment=POSTGRES_DB=appdb
Volume=pgdata:/var/lib/postgresql/data

[Service]
Restart=always

Quadlet .pod déploie NGINX+Postgres avec vol persistant et network custom. Secrets via env (améliorez avec podman secret). systemctl --user daemon-reload && systemctl --user start monpod lance. Piège : oubliez daemon-reload, unit invisible.

Secrets TLS et systemd start

terminal-quadlet.sh
#!/bin/bash
# Créer secret TLS
podman secret create tls-cert cert.pem
podman secret create tls-key key.pem

# Ajouter à quadlet (éditez monpod.pod)
# [Container]nginx
# Secrets=tls-cert:/etc/ssl/cert.pem=tls.crt
# Secrets=tls-key:/etc/ssl/key.pem=tls.key

# Reload et start
systemctl --user daemon-reload
systemctl --user enable --now monpod
systemctl --user status monpod
journalctl --user -u monpod -f

# Auto-start on boot (linger déjà activé)

Secrets Podman chiffrés en RAM, montés read-only. Éditez quadlet pour TLS. journalctl logs unifiés. Piège : secrets non persistants sans podman secret create --driver file.

Bonnes pratiques

  • Rootless only : Toujours --userns=keep-id pour vols host, audit avec podman system migrate.
  • Quadlets > Compose : Préférez systemd pour prod HA ; podman generate systemd pour migrer.
  • Networks isolés : Créez podman network create --driver bridge private par app.
  • Pruning auto : Ajoutez cron podman system prune -af hebdo.
  • Monitoring : podman stats --no-stream + Prometheus exporter Podman.

Erreurs courantes à éviter

  • Cgroup v1 : Fail sur pods ; fixez GRUB systemd.unified_cgroup_hierarchy=1 + reboot.
  • SubUID manquant : podman run crash ; éditez /etc/subuid avec usermod --add-subuids 100000-165535 $USER.
  • Fuse-overlayfs lent : Sur SSD, forcez overlay si kernel 6+ supporte rootless overlay.
  • Port bind root : Ports <1024 refusés rootless ; utilisez sysctl net.ipv4.ip_unprivileged_port_start=80.

Pour aller plus loin