glossaire-linux

Conteneurs

Lancer des applications dans des conteneurs Linux sans démon root. podman est l'outil de référence côté Red Hat (Fedora/RHEL/CentOS) — compatible Docker en CLI mais rootless par défaut et sans démon. La majorité des commandes Docker fonctionnent à l'identique sous podman : passer de l'un à l'autre se résume souvent à alias docker=podman.

Cycle de vie d'un conteneur

Lancer, lister, inspecter, entrer dedans, arrêter, supprimer. Le quotidien d'un container engine.

podman run · ps · exec · logs · stop · rm

Démarrer un conteneur et le piloter au quotidien

Un conteneur = un processus isolé du reste du système (réseau, FS, namespaces utilisateur) démarré à partir d'une image. podman run télécharge l'image si nécessaire, crée le conteneur et le démarre. podman est rootless par défaut : un utilisateur normal peut lancer un conteneur sans sudo, contrairement à Docker historiquement.

Flags de podman run essentiels

-dDetached : tourne en arrière-plan, renvoie l'ID. Sans -d, on est attaché à stdout.
--name NOMNom symbolique (sinon nom aléatoire type quirky_einstein).
-p HOTE:CONTAINERPublie un port. -p 8080:80 = port 80 du conteneur exposé sur le 8080 de l'hôte.
-v CHEMIN:CHEMIN[:ro]Monte un volume. :Z ou :z ajoutent un label SELinux (RHEL/Fedora).
-e VAR=VALVariable d'environnement passée au conteneur.
--rmSupprime automatiquement le conteneur quand il s'arrête (idéal pour les tests éphémères).
-itMode interactif + TTY — pour ouvrir un shell ou lancer une commande qui attend de l'input.
--network=hostConteneur sur la pile réseau de l'hôte (pas d'isolation), équivalent ip a de l'hôte visible dedans.
--restart=alwaysRedémarre tout seul s'il crash. unless-stopped = sauf si on l'a arrêté volontairement.
$ podman run --rm -it docker.io/library/alpine sh
Lance un shell dans un conteneur Alpine éphémère. Le nom qualifié docker.io/library/alpine évite la résolution des noms courts, qui dépend des alias et de registries.conf. --rm supprime le conteneur à sa sortie, pas l’image.
$ podman run -d --name web -p 8080:80 docker.io/library/nginx
Publie le port TCP 80 du conteneur sur le port 8080 de toutes les adresses de l’hôte, pas seulement localhost. Pour un accès local uniquement : -p 127.0.0.1:8080:80. En rootless, les ports autorisés dépendent notamment de net.ipv4.ip_unprivileged_port_start ; 8080 évite les ports bas habituels.
$ podman ps
CONTAINER ID  IMAGE                          STATUS         PORTS                  NAMES
7a3f1c2e8b4d  docker.io/library/nginx:latest Up 2 minutes   0.0.0.0:8080->80/tcp   web
Liste les conteneurs en cours ; -a inclut ceux arrêtés et -q n’affiche que les identifiants. Pour arrêter tous les conteneurs de cet utilisateur, podman stop --all évite une substitution vide si aucun conteneur ne tourne.
$ podman logs -f web
Suit les logs (stdout/stderr) du conteneur en temps réel — équivalent tail -f. Sans -f, dump tout puis sort. --tail 100 limite aux 100 dernières lignes.
$ podman exec -it web sh
Ouvre un shell dans un conteneur déjà en cours. Indispensable pour déboguer : on inspecte le système de fichiers, on lit la config telle qu'elle est vue par l'application. À la sortie, le conteneur continue de tourner.
$ podman stop web
podman rm web
podman stop -a && podman rm -a    # tout d'un coup
Arrêt propre (SIGTERM puis SIGKILL après 10 s) puis suppression. -a = all. Les conteneurs supprimés ne sont pas récupérables, mais l'image elle reste — pour la supprimer aussi : podman rmi IMAGE.
Compatibilité Docker : La syntaxe des commandes de base est proche de Docker, mais un alias docker=podman ne garantit pas leur compatibilité complète. Pour Compose, podman compose délègue à un fournisseur externe tel que podman-compose ou docker-compose ; podman kube play prend en charge un sous-ensemble du format Kubernetes, qui est un autre format de description.

Voir aussi : podman build · image podman pod · systemd ps

docker compose

Décrire et piloter une application multi-conteneurs

docker compose lit un fichier compose.yaml pour gérer plusieurs services, leurs réseaux et leurs volumes. Compose v2 s'utilise comme sous-commande du CLI Docker. Pour Podman, les alternatives courantes sont podman-compose et podman play kube ; la compatibilité n'est pas toujours complète.

$ docker compose config
Valide et affiche la configuration fusionnée sans démarrer les services.
$ docker compose up -d
Crée et démarre les services en arrière-plan à partir du fichier Compose du répertoire courant.
$ docker compose ps
docker compose logs --tail 100 web
docker compose exec web sh
Liste les services, affiche les 100 dernières lignes de logs puis ouvre un shell du service web. Pour un suivi continu, exécuter séparément docker compose logs -f web ; cette commande bloque jusqu’à son interruption.
$ docker compose down
Arrête et supprime les conteneurs et réseaux créés par le projet. Les volumes nommés sont conservés sauf si l'on ajoute --volumes.
Attention à la suppression des volumes docker compose down --volumes supprime aussi les volumes déclarés par le projet et peut donc effacer des données persistantes. Vérifier la configuration avant de l'utiliser.

Images

Une image est un <em>template</em> en lecture seule. On en télécharge depuis un registre (Docker Hub, Quay, GHCR…) ou on en construit avec un <code>Containerfile</code> (=<code>Dockerfile</code>, même syntaxe).

podman build · pull · images · rmi

Récupérer, construire, lister, supprimer des images

Trois sources d'image : un registre public (docker.io, quay.io, ghcr.io…) avec pull, un Containerfile local avec build, ou un export d'un autre hôte avec load. Les images sont stockées dans ~/.local/share/containers/ (rootless) ou /var/lib/containers/ (root).

$ podman pull docker.io/library/postgres:16
Télécharge l'image Postgres 16 depuis Docker Hub. library/ est le namespace des images officielles. Le tag :16 fige une version majeure ; sans tag, :latest est sous-entendu (instable, à éviter en production).
$ podman images
REPOSITORY                       TAG     IMAGE ID      SIZE
docker.io/library/nginx          latest  a8758716bb6a  192 MB
docker.io/library/postgres       16      bb91eaf69b91  450 MB
docker.io/library/alpine         latest  9c6f07244728  7.34 MB
Affiche les images locales et leur taille. Des images peuvent partager des couches : la somme des tailles affichées n’est pas l’espace supplémentaire réellement consommé. Examiner podman system df -v pour détailler le stockage partagé et récupérable.
$ # Containerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Recette minimaliste pour une app Python. FROM = image de base, WORKDIR = répertoire de travail dans le conteneur, COPY = depuis le contexte de build (le répertoire courant), RUN = commande à l'exécution du build, CMD = commande par défaut au démarrage du conteneur.
$ podman build -t monapp:1.0 .
Construit l'image depuis le Containerfile dans le répertoire courant (. = contexte de build). -t monapp:1.0 donne un nom et un tag. podman détecte Containerfile en priorité, puis Dockerfile en fallback — les deux ont la même syntaxe.
$ podman rmi monapp:1.0
Supprime une image (les conteneurs basés dessus doivent être supprimés d'abord, sinon --force). podman image prune nettoie les images dangling (sans tag, résultats de builds intermédiaires). podman system prune -a nettoie agressivement tout ce qui n'est pas utilisé — à manier avec précaution.
$ podman login docker.io
podman tag monapp:1.0 docker.io/alice/monapp:1.0
podman push docker.io/alice/monapp:1.0
Publie une image : login authentifie, tag ajoute un nom à l’image locale sans supprimer le précédent et push l’envoie. Sous Linux, le fichier d’authentification par défaut est ${XDG_RUNTIME_DIR}/containers/auth.json, souvent temporaire ; pour une persistance explicite, utiliser --authfile avec un fichier protégé, par exemple ~/.config/containers/auth.json.
Réduire la taille : les images Python/Node officielles existent en variantes -slim et -alpine beaucoup plus petites. Sur du Go ou du Rust statiquement compilé, on peut même partir de scratch (image vide) — image finale qui pèse parfois 10 Mo au lieu de 500 Mo.

Voir aussi : podman run · ps · exec tar

Spécificités podman

Ce qui distingue podman de Docker : pods (groupes de conteneurs partagés), intégration native avec systemd pour démarrer des conteneurs au boot sans démon, et mode rootless par défaut.

podman pod · Quadlet · rootless

Groupes de conteneurs, démarrage au boot, mode utilisateur

Pod est un concept emprunté à Kubernetes : un groupe de conteneurs qui partagent la même pile réseau (localhost commun, ports exposés une fois pour tout le pod). Quadlet permet de décrire les conteneurs et pods dans des fichiers dédiés que systemd transforme en unités. Rootless : tout tourne dans les namespaces utilisateur, aucun privilège root requis.

$ podman pod create --name app -p 8080:80
podman run -d --pod app --name front docker.io/library/nginx
podman run -d --pod app --name api  monapp:1.0
Crée un pod et deux conteneurs partageant le même réseau. Ils peuvent communiquer via localhost si l’application écoute sur le port attendu. L’image nginx standard ne configure pas automatiquement un reverse proxy : monter un nginx.conf adapté pour transmettre à une API sur localhost:3000. Les deux applications ne peuvent pas écouter sur le même port du pod.
$ podman kube generate app > app.yaml
Exporte le pod existant. Pour le recréer sur un autre hôte préparé, utiliser podman kube play app.yaml après y avoir copié le manifeste, les données et les images nécessaires. Sur le même hôte, les noms et les ports du pod initial peuvent entrer en conflit. Les objets Kubernetes et les volumes pris en charge dépendent de Podman et de sa version.
$ # ~/.config/containers/systemd/web.container
[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80

[Install]
WantedBy=default.target
Quadlet (Podman 4.4+) décrit le conteneur dans un fichier systemd généré. Après création ou modification : systemctl --user daemon-reload, puis démarrer avec systemctl --user start web.service. Le bloc [Install] rattache le service à default.target au prochain démarrage du générateur ; les unités Quadlet ne s'activent pas avec systemctl enable. La disponibilité et le chemin de recherche dépendent de la version de Podman et du mode rootless/rootful.
$ podman generate systemd --new --name web --files
mkdir -p ~/.config/systemd/user
mv container-web.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable container-web.service
loginctl enable-linger $USER
Compatibilité ancienne : podman generate systemd est déprécié au profit de Quadlet. Copier le fichier généré dans ~/.config/systemd/user/ avant daemon-reload et enable. Garder cette procédure pour comprendre ou migrer des unités existantes. loginctl enable-linger permet au service utilisateur de tourner même sans session ouverte.
$ cat /etc/subuid
cat /etc/subgid
podman unshare cat /proc/self/uid_map
Le mappage dépend de /etc/subuid, /etc/subgid et de --userns. Exemple par défaut avec un utilisateur hôte 1000 et une plage commençant à 100000 : UID 0 du conteneur correspond à 1000 sur l’hôte ; UID 1 à 100000 ; UID 100 à 100099. Inspecter les tables uid_map et gid_map plutôt que supposer ces nombres.
Limites du rootless : Le seuil des ports accessibles sans privilèges est configurable via net.ipv4.ip_unprivileged_port_start (souvent 1024). Le modifier affecte tous les processus concernés du namespace réseau, pas seulement Podman. Utiliser un port haut ou un reverse proxy constitue une solution courante ; la transmission d’un socket systemd exige une application et une configuration compatibles.
Migration depuis Docker : En rootless, un bind mount reste soumis aux permissions de l’utilisateur hôte, aux mappages UID/GID et à SELinux. Un chemin sous /var peut être accessible s’il a été préparé avec les bons droits ; il n’est pas interdit par son emplacement. Choisir un dossier accessible ou un volume géré, puis adapter les droits et labels sans basculer automatiquement en root.

Voir aussi : podman run · ps · exec systemctl loginctl sysctl