Skip to content
Learni
View all tutorials
DevOps

Comment maîtriser Podman expert en 2026

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

Maîtriser Podman expert 2026 (guide complet) | Learni