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=1dans GRUB) - Utilisateur : Non-root avec subUID/subGID (vérifiez
id -uet/etc/subuid) - Connaissances : Docker CLI, YAML Kubernetes, systemd units
- Outils :
podman5.0+ (dnf install podmanouapt install podman),buildah,skopeooptionnels - Espace disque : 10GB pour images/layers
Installer et configurer Podman rootless
#!/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
#!/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 -fCré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
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
#!/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 -aBuild, 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
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: 80YAML 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
#!/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.yamlDé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
[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=alwaysQuadlet .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
#!/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-idpour vols host, audit avecpodman system migrate. - Quadlets > Compose : Préférez systemd pour prod HA ;
podman generate systemdpour migrer. - Networks isolés : Créez
podman network create --driver bridge privatepar app. - Pruning auto : Ajoutez cron
podman system prune -afhebdo. - 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 runcrash ; éditez/etc/subuidavecusermod --add-subuids 100000-165535 $USER. - Fuse-overlayfs lent : Sur SSD, forcez
overlaysi 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
- Docs officielles : Podman Desktop pour GUI experte.
- Avancé : Podman Desktop extensions.
- Formations : Maîtrisez Podman en prod avec nos formations Learni DevOps.
- Ressources :
podman machinepour Mac/Windows,podman podman-desktoppour VSCode.