Conteneurs : images, exécution et exploitation robuste

Un conteneur n’est pas un petit serveur, et une image n’est pas une sauvegarde. Techniquement, un runtime de conteneur exécute des processus ordinaires avec un système de fichiers préparé, des vues isolées des ressources du noyau et des limites de ressources et de sécurité définies. Le noyau hôte reste impliqué dans chaque opération. Cette architecture rend les environnements applicatifs reproductibles et rapidement remplaçables ; elle déplace toutefois la responsabilité vers la provenance des images, le runtime, le réseau, la persistance, les secrets, le contrôle des ressources et l’orchestration.

Pour les administrateurs, la distinction la plus importante est celle entre artefact, instance d’exécution et état d’exploitation. Une image décrit le système de fichiers démarrable et les métadonnées. Un conteneur est une exécution concrète. Les bases de données, files d’attente, clés, configurations et données d’audit ont leurs propres cycles de vie. Quiconque traite conjointement ces niveaux comme « le conteneur Docker » ne peut ni circonscrire un incident ni planifier entièrement une restauration.

L’explication commence par l’image en tant qu’artefact livrable et suit son parcours via le moteur et le runtime jusqu’au noyau, au réseau et au stockage. L’orchestration, la sécurité, le diagnostic et la reprise s’appuient sur ce déroulement.

Commandes adaptées

Des commandes prêtes à l’emploi autour de Docker pour PowerShell et le shell Unix, avec des exemples à copier.

Services et journauxCapture réseau

Articles sur Docker (1)

  1. 26 juil. 2026 Rclone dans Docker Exploiter de manière fiable des montages Rclone dans Docker

Positionnement technique

NIST décrit les conteneurs d’application comme une forme de virtualisation du système d’exploitation : les applications partagent le noyau, tandis que l’isolation et le contrôle des ressources reposent sur des mécanismes du système d’exploitation. Les machines virtuelles virtualisent en revanche le matériel pour leur propre noyau invité. Les conteneurs et les VM peuvent être combinés ; le choix modifie la surface d’attaque, la compatibilité, le coût de démarrage et le périmètre de défaillance (NIST SP 800-190 – Application Container Security Guide).

Un chemin Linux typique se compose de :

  1. registre ou magasin de contenu local avec manifestes, configurations et couches OCI ;
  2. moteur ou orchestrateur qui définit l’état souhaité, le réseau, les montages et les politiques ;
  3. runtime de haut niveau tel que containerd ou CRI-O pour la gestion des images et conteneurs ;
  4. runtime OCI tel que runc, qui crée le processus à partir du bundle et de config.json ;
  5. noyau hôte avec espaces de noms, cgroups, capabilities, Seccomp et un Linux Security Module ;
  6. processus de conteneur qui interagissent avec leur environnement via des systèmes de fichiers virtuels ou montés, des sockets et des périphériques.

L’Open Container Initiative standardise séparément les parties image, runtime et distribution. Ainsi, une image OCI peut être traitée par différents moteurs et runtimes sans que le réseau, l’orchestration ou la sauvegarde des données soient automatiquement standardisés (OCI Image Specification, OCI Runtime Specification, OCI Distribution Specification).

Image : manifeste, configuration et couches

Une image OCI est un graphe de contenu orienté. Un manifeste référence, par des descripteurs et des digests cryptographiques, une configuration d’image et des couches de système de fichiers ordonnées. Un index d’image facultatif peut regrouper plusieurs manifestes pour différents systèmes d’exploitation et architectures. Le type de média, le digest et la taille font partie du descripteur ; les tags relèvent en revanche de la résolution de noms du registre et ne constituent pas une identité immuable (OCI Image Manifest, OCI Image Configuration).

Les couches contiennent des modifications du système de fichiers. Au démarrage, elles sont assemblées par un pilote de stockage en une vue racine commune, complétée par une couche de conteneur inscriptible. Un secret ou un contenu de paquet supprimé peut continuer d’exister dans une couche antérieure. Les builds multi-étapes réduisent les outils de build et les artefacts intermédiaires dans l’image finale, mais ne remplacent pas la vérification des secrets et de la provenance (Docker – Storage drivers, Docker – Multi-stage builds).

Tags, digests et sélection de plateforme

Un tag tel que stable, 3 ou latest peut être déplacé vers un autre digest de manifeste. Une production reproductible épingle donc le digest approuvé ou documente au minimum le digest résolu lors du déploiement. Pour les images multi-architectures, le client sélectionne une plateforme dans l’index ; une architecture incorrecte, des fonctionnalités CPU manquantes ou l’émulation peuvent provoquer un comportement différent malgré un tag identique.

Un digest répond à « quels octets ? », non à « qui les a construits ? » ou « sont-ils sûrs ? ». Les signatures et attestations peuvent lier identité, provenance de build et matériaux. SLSA décrit la provenance comme une information vérifiable indiquant où, quand et comment un artefact a été produit ; cosign de Sigstore peut signer et vérifier des artefacts de conteneur (SLSA Specification, Sigstore cosign).

$image = $env:CONTAINER_IMAGE
docker buildx imagetools inspect $image
docker image inspect $image --format '{{json .RepoDigests}}'
cosign verify $image --certificate-identity $env:EXPECTED_IDENTITY `
  --certificate-oidc-issuer $env:EXPECTED_ISSUER

docker buildx imagetools inspect affiche les listes de manifestes et les plateformes, docker image inspect les métadonnées locales de l’image. cosign verify vérifie la signature et l’identité attendue ; jq formate le JSON dans l’exemple Unix.

À partir de l’image immuable, le runtime crée le conteneur réellement exécuté. Ce n’est qu’alors que la couche inscriptible, les espaces de noms, les cgroups, les montages et les paramètres du processus sont réunis.

Runtime, bundle et cycle de vie du conteneur

L’OCI Runtime Specification décrit un conteneur comme un environnement pour un processus. Un bundle contient config.json et un système de fichiers racine. La configuration définit les arguments du processus, l’environnement, l’utilisateur, les montages, les espaces de noms, les ressources et d’autres options de plateforme. Le cycle de vie distingue la création, le démarrage, l’arrêt et la suppression ; un processus ayant le statut created ne s’exécute pas encore (OCI Runtime Specification).

runc est une implémentation de référence de cette interface bas niveau. containerd gère par-dessus les images, snapshots, conteneurs, tâches et événements. Docker Engine fournit une API de plus haut niveau avec réseau, volumes, build et modèle d’utilisation. Sur un nœud, Kubernetes communique avec un runtime compatible via la Container Runtime Interface (CRI) ; kubelet ne s’adresse pas simplement à la CLI Docker (runc, containerd, Kubernetes – Container Runtime Interface).

Ces couches possèdent des états distincts. Un pod Kubernetes peut signaler Running alors qu’un processus de conteneur se trouve dans une boucle de redémarrage ; un moteur peut connaître un conteneur dont la tâche runtime n’est plus active ; un processus peut être en cours d’exécution alors que le service n’accepte aucun trafic. Le diagnostic commence donc par la question : état souhaité, objet moteur, tâche runtime, processus ou application ?

Espaces de noms : vue isolée, pas machine autonome

Les espaces de noms Linux isolent les ressources globales dans des vues distinctes. Les pages de manuel du noyau citent notamment les espaces de noms Mount, PID, Network, IPC, UTS, User, cgroup et Time. Un processus ne peut appartenir qu’à un seul espace de noms de chaque type ; les relations peuvent être examinées via /proc/<pid>/ns (namespaces(7)).

Espace de nomsVue isoléePertinence administrative
MountPoints de montage et système de fichiers racineBind Mounts, propagation, chemins hôte masqués
PIDIdentifiants et hiérarchie de processusPID 1, comportement des signaux et récupération des processus enfants
NetworkInterfaces, routes, ports, état du pare-feuLe conteneur peut écouter en interne sans être accessible de l’extérieur
UTSNom d’hôte et nom de domaineIdentité cosmétique, ni DNS ni principal de sécurité
IPCIPC System V et files de messages POSIXIPC partagé uniquement avec une configuration explicite
UserMappage des UID/GIDLe root du conteneur peut être mappé comme non privilégié à l’extérieur
cgroupVue sur la hiérarchie cgroupN’empêche pas à lui seul l’utilisation des ressources
TimeDécalages de temps monotone/de démarrage sélectionnésRarement utilisé ; aucune isolation générale de fuseau horaire

L’isolation est configurable. Le réseau hôte, le PID hôte, --privileged, les autorisations de périphériques, les Bind Mounts étendus ou des capabilities supplémentaires ouvrent délibérément des frontières. Le nom du conteneur et un UID interne ne constituent pas un principal de sécurité à travers l’hôte, le registre et l’orchestrateur.

PID 1, signaux et arrêt propre

Dans l’espace de noms PID, le premier processus assume des tâches particulières. Il reçoit les signaux différemment et doit récupérer les processus enfants orphelins. Les wrappers shell qui ne démarrent pas le programme réel avec exec peuvent absorber les signaux d’arrêt. Les orchestrateurs envoient généralement d’abord un signal de terminaison, attendent une période de grâce, puis forcent l’arrêt. L’application doit cesser d’accepter du nouveau travail, terminer les opérations en cours dans un délai limité et vider les états.

Docker peut utiliser un petit processus init avec --init ; cela ne corrige pas une application, mais rend plus explicites le relais des signaux et la récupération des processus enfants (Docker run reference – --init). Pour les files d’attente de courrier, les bases de données et les indexeurs, la durée maximale d’arrêt sûre doit faire partie du modèle de déploiement.

cgroups : contrôle et comptabilisation

Les cgroups regroupent des processus et appliquent des contrôleurs aux ressources. Dans cgroup v2, les processus forment une hiérarchie unifiée. Les contrôleurs CPU, mémoire, E/S et PID ont des sémantiques différentes : une limite CPU ralentit, une limite mémoire peut déclencher un OOM kill, une limite PID empêche de nouveaux processus ou threads, et les limites d’E/S dépendent du chemin réel du périphérique de bloc (Linux kernel – Control Group v2).

Il ne faut pas confondre request/réservation et limit. Kubernetes utilise les requests pour la planification et les limits pour les limites d’exécution ; pour la mémoire, la limite est réactive et appliquée par le noyau sous pression. Un pod peut être évincé ou arrêté malgré une capacité totale suffisante en raison d’une pression sur le nœud ou le cgroup (Kubernetes – Resource Management for Pods and Containers).

docker container inspect $env:CONTAINER_NAME --format '{{json .State}}'
docker container top $env:CONTAINER_NAME
docker stats --no-stream $env:CONTAINER_NAME
Get-Process -Name $env:HOST_PROCESS_NAME -ErrorAction SilentlyContinue

docker container inspect affiche la configuration et l’état runtime, docker container top la vue des processus et docker stats les valeurs de ressources en cours. Get-Process et ps vérifient le processus hôte ; le PID hôte et le PID du conteneur peuvent différer.

Capabilities, Seccomp et Linux Security Modules

Linux décompose les privilèges root classiques en capabilities. CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_SYS_ADMIN ou CAP_SYS_PTRACE ouvrent des opérations très différentes ; CAP_SYS_ADMIN confère un pouvoir particulièrement étendu. Un processus qui ne s’exécute pas comme root peut posséder des capabilities, et un processus root peut se les voir presque toutes retirer (capabilities(7)).

Seccomp filtre les appels système. Docker utilise par défaut un profil qui bloque certains syscalls ; unconfined supprime cette couche. AppArmor ou SELinux peuvent en outre limiter les accès liés aux objets. Ces contrôles se complètent : une capability autorise une classe d’opérations, Seccomp peut bloquer le syscall correspondant, et le Security Module peut refuser l’accès à un objet précis (Docker – Seccomp security profiles, Docker – AppArmor security profiles).

--privileged n’est pas une correction pratique d’erreur. Il étend l’accès aux périphériques et aux capabilities et assouplit les profils de sécurité. Si une application ne requiert qu’un port, un périphérique unique ou un chemin en lecture seule, seule cette capacité est accordée et justifiée dans le modèle de menace.

Root, espaces de noms utilisateur et exploitation rootless

L’UID 0 dans le conteneur est, sans espace de noms utilisateur, le même UID numérique 0 évalué par le noyau hôte. Les espaces de noms limitent les vues et les opérations, mais une erreur de noyau ou de configuration affecte toujours l’hôte. Un espace de noms utilisateur peut mapper les UID du conteneur vers des UID hôte non privilégiés ; les moteurs rootless exécutent le daemon et les conteneurs sans root sur l’hôte (user_namespaces(7), Docker – Rootless mode).

Le mode rootless modifie les prérequis de réseau, de liaison de ports, de cgroups et de stockage ; il s’agit donc d’un modèle d’exploitation, non d’un commutateur universel de durcissement. Indépendamment de cela, les règles suivantes s’appliquent : supprimer les capabilities inutiles, exploiter le système de fichiers racine en lecture seule, monter individuellement les chemins inscriptibles, définir no-new-privileges et ne pas intégrer le socket runtime aux workloads. L’accès au socket Docker ou CRI équivaut de fait à l’accès au plan de contrôle de l’hôte.

Après l’isolation des processus et des droits vient l’accessibilité. Un espace de noms réseau propre ne crée d’abord qu’une vue séparée ; le routage, la résolution de noms et les ports publiés doivent être mis en place en plus.

Réseau : espace de noms, CNI et publication de ports

Selon le mode, un conteneur Linux possède son propre espace de noms réseau. Un moteur le relie souvent à un bridge via une paire veth et effectue du NAT ou une publication de ports. Les réseaux overlay encapsulent le trafic entre hôtes ; les proxies de service ou les chemins de données eBPF répartissent les adresses de service virtuelles. CNI standardise la manière dont un runtime appelle les plugins réseau pour ajouter et retirer un conteneur d’un réseau ; il ne standardise pas l’architecture réseau complète d’un cluster (CNI Specification).

Quatre adresses sont documentées séparément :

  • adresse d’écoute dans le processus, par exemple 127.0.0.1:8080 ou 0.0.0.0:8080 dans l’espace de noms ;
  • IP du conteneur/pod, dont la durée de vie peut être liée à l’instance ;
  • adresse de service ou de load balancer comme couche d’accès plus stable ;
  • adresse et port hôte publiés, qui déterminent le pare-feu, le NAT et l’accessibilité externe.

EXPOSE dans le Dockerfile ne publie aucun port ; il documente uniquement les ports prévus. La publication de ports est une décision d’exécution. De même, un port hôte ouvert ne prouve pas que la readiness, TLS ou l’authentification de l’application fonctionnent (Docker – Container networking).

docker network inspect $env:CONTAINER_NETWORK
docker container port $env:CONTAINER_NAME
Get-NetTCPConnection -State Listen | Sort-Object LocalPort
Test-NetConnection $env:SERVICE_HOST -Port $env:SERVICE_PORT

docker network inspect et docker container port affichent l’affectation du moteur et les ports publiés. Get-NetTCPConnection ou ss affichent les écouteurs ; Test-NetConnection et nc vérifient TCP. Pour DNS et TLS, leurs propres chemins de diagnostic s’appliquent ensuite.

Stockage : couche inscriptible, volumes et Bind Mounts

La couche inscriptible du conteneur appartient à l’instance. Elle convient aux modifications temporaires à l’exécution, mais ni aux charges fortement intensives en écriture ni au stockage durable des données. Docker distingue les volumes, Bind Mounts, tmpfs et la couche inscriptible ; les volumes sont gérés par le moteur, les Bind Mounts montent un chemin hôte concret (Docker – Storage overview).

FormePropriétaire du cheminRisque typique
Couche inscriptiblePilote de stockage/instance du conteneurPerte lors du remplacement ; coûts de copy-on-write et de capacité
VolumeMoteur ou plugin de volumeNom/plugin/liaison hôte non sauvegardés avec l’image
Bind MountAdministrateur de l’hôteChemin hôte, droits, label SELinux et ordre de démarrage
tmpfsMémoire vivePerte à l’arrêt ; consommation mémoire et résidus de secrets dans le modèle de swap
Service externeBase de données, stockage objet ou réseauRéseau, identité, cohérence, quota et plan de reprise propre

Un montage masque les fichiers existants au chemin cible. Si un montage réseau attendu est absent au démarrage, un chemin de Bind Mount peut se trouver sur l’hôte local et l’application peut y écrire sans s’en apercevoir. Un conteneur démarré avec succès ne prouve donc pas que le bon backend de stockage est actif.

Le standard Container Storage Interface définit une interface orchestrateur/plugin pour les volumes. Il ne garantit ni la mise au repos de l’application, ni la cohérence après crash, ni la capacité de restauration réussie. Les bases de données nécessitent toujours leurs procédures documentées de sauvegarde et de restauration (Container Storage Interface Specification, Sauvegarde et reprise après sinistre).

docker container inspect $env:CONTAINER_NAME --format '{{json .Mounts}}'
docker volume inspect $env:VOLUME_NAME
docker exec $env:CONTAINER_NAME powershell -NoProfile -Command `
  'Get-Volume | Select-Object DriveLetter,FileSystem,SizeRemaining,Size'
Get-PSDrive -PSProvider FileSystem

docker volume inspect fournit le pilote de volume et le point de montage. Get-Volume, Get-PSDrive, findmnt et df vérifient la situation de stockage effectivement visible et la capacité.

Configuration et secrets

Les variables d’environnement sont pratiques, mais sont souvent visibles via les sorties Inspect, l’environnement de processus, les rapports de crash ou les bundles de support. Un objet secret dans un orchestrateur n’est pas automatiquement chiffré, rotatif ou caché aux administrateurs de nœuds privilégiés. Kubernetes documente explicitement que les secrets sont stockés par défaut sans chiffrement dans etcd, sauf si Encryption at Rest est configuré (Kubernetes – Secrets).

La configuration est inventoriée en quatre classes :

  1. configuration de déploiement non sensible et versionnable ;
  2. références de secrets et leur source externe ;
  3. état produit à l’exécution, comme les clés hôte, schémas de base de données ou autorités de certification internes ;
  4. valeurs par défaut intégrées à l’image, susceptibles de changer lors des mises à jour.

La rotation est une machine à états : fournir le nouveau secret, mettre à jour ou recharger le consommateur, démontrer le bon fonctionnement, révoquer l’ancien secret et tenir compte des caches ou connexions longue durée. Un simple redémarrage du conteneur ne garantit pas une rotation dans le service distant.

Health, readiness, liveness et startup

L’état du processus, la disponibilité du service et la santé fonctionnelle sont des signaux différents. Docker HEALTHCHECK exécute une commande dans le conteneur et enregistre le code de sortie ainsi qu’une sortie limitée. Kubernetes distingue les probes Startup, Readiness et Liveness : Startup protège un démarrage lent contre une Liveness prématurée, Readiness pilote les endpoints, Liveness peut déclencher un redémarrage (Dockerfile reference – HEALTHCHECK, Kubernetes – Configure Liveness, Readiness and Startup Probes).

Une bonne probe est peu coûteuse, limitée dans le temps et répond exactement à une question d’exploitation. Une probe Liveness ne doit pas déclencher des redémarrages à chaque incident externe partiel ; sinon elle amplifie les problèmes DNS, de base de données ou de fournisseur. Une probe Readiness doit retirer le service du trafic lorsqu’il ne peut pas accepter de nouveau travail de manière sûre. Les vérifications de bout en bout approfondies relèvent davantage du monitoring que de probes locales exécutées chaque seconde.

Compose depends_on contrôle l’ordre de création et de démarrage ; avec des conditions, il peut attendre la santé ou l’exécution réussie d’une tâche de dépendance. Il ne remplace pas la logique de reconnexion : les services peuvent aussi tomber indépendamment après le démarrage (Docker Compose – Control startup order).

docker container inspect $env:CONTAINER_NAME --format '{{json .State.Health}}'
docker container logs --since 30m --timestamps $env:CONTAINER_NAME
docker events --since 30m --filter "container=$env:CONTAINER_NAME"
docker compose ps --all

docker container logs lit le chemin de journalisation configuré, docker events les événements du moteur et docker compose ps l’état Compose. journalctl affiche le contexte du daemon sous systemd. Docker documente séparément les pilotes de journalisation, la rotation et le Dual Logging ; des journaux JSON illimités peuvent remplir l’hôte (Docker – Configure logging drivers).

Les healthchecks peuvent détecter un processus défaillant et un orchestrateur peut le redémarrer. Les données perdues, une configuration incorrecte ou une dépendance externe défaillante ne sont toutefois pas réparées pour autant.

Le redémarrage n’est pas une stratégie de reprise

Les politiques de redémarrage réagissent à l’arrêt du processus. Elles ne connaissent ni les données corrompues, ni les files d’attente bloquées, ni les identifiants erronés. Docker indique en outre qu’une Restart Policy ne devient effective que lorsqu’un conteneur a fonctionné avec succès pendant au moins dix secondes ; les arrêts manuels la suppriment jusqu’au redémarrage du daemon ou au démarrage manuel (Docker – Start containers automatically).

Les boucles de redémarrage consomment du CPU, génèrent des journaux et peuvent surcharger les services dépendants. Les orchestrateurs utilisent un backoff, mais l’administrateur a néanmoins besoin de la première erreur, du code de sortie, de la raison de l’OOM/de l’éviction, de la dernière configuration et de la chronologie des événements. Un CrashLoop est un état symptomatique, non une cause.

Orchestration : pod, nœud et état souhaité

Kubernetes regroupe un ou plusieurs conteneurs dans un pod. Les conteneurs d’un pod partagent l’espace de noms réseau et peuvent partager des volumes ; ils sont planifiés ensemble. Les deployments gèrent les ReplicaSets et les mises à jour progressives. Sur le nœud, kubelet met en œuvre le PodSpec via CRI, CNI et les plugins de stockage (Kubernetes – Pods, Kubernetes – Deployments).

NiveauPropriétaireIncident typique
Plan de contrôleAPI, scheduler, contrôleurL’état souhaité n’est pas calculé ou planifié
Nœud/kubeletMise en œuvre localePull d’image, pression disque/PID/mémoire, erreur runtime ou CNI
Sandbox de podRéseau de pod partagéCréation de sandbox/IP ou perte d’espace de noms
ConteneurImage et processusErreur de démarrage, configuration, sortie ou OOM
Service/IngressAccessibilité et routageAucun endpoint prêt, port ou politique incorrecte
Volume persistantChemin de donnéesAttach/mount, zone, droits, snapshot ou backend

La phase Running signifie qu’au moins un conteneur principal s’exécute ou démarre ; ce n’est pas un SLA applicatif. Les statuts de conteneur, conditions, événements, probes et état du contrôleur sont évalués ensemble (Kubernetes – Pod Lifecycle).

kubectl get pod $env:POD -n $env:NAMESPACE -o wide
kubectl describe pod $env:POD -n $env:NAMESPACE
kubectl logs $env:POD -n $env:NAMESPACE --all-containers --previous
crictl ps --all
crictl inspectp $env:POD_SANDBOX_ID

kubectl get, kubectl describe et kubectl logs affichent les perspectives API, événements et conteneur. crictl examine la vue CRI sur le nœud. Un kubectl exec modifie et observe l’instance d’exécution ; il ne remplace ni une image reproductible ni un runbook.

Compose et systèmes déclaratifs sur hôte unique

Compose décrit les services, réseaux, volumes, secrets, configs et dépendances dans un modèle d’application. Il est précieux pour les systèmes à hôte unique et les flux de développement, mais n’est ni un registre ni un orchestrateur de cluster. La Compose Specification définit le modèle indépendamment d’une CLI donnée (Compose Specification).

Un dépôt Compose apte à la production contient :

  • des digests d’image ou une résolution de tag contrôlée et une plateforme documentée ;
  • des montages explicites, un système de fichiers racine en lecture seule et des chemins inscriptibles ;
  • la sémantique des ressources, redémarrages, arrêts et healthchecks ;
  • la configuration séparée et les références de secrets ;
  • les réseaux et ports publiés ;
  • les prescriptions de journalisation et de rotation ;
  • les procédures de sauvegarde/restauration et de mise à jour en dehors du fichier YAML.

docker compose config rend la configuration fusionnée et affiche la résolution des variables. La sortie peut contenir des secrets et est traitée en conséquence (Docker – docker compose config).

Pull d’image, registre et cache

Un registre distribue du contenu via des manifestes et des blobs. L’authentification, l’autorisation de dépôt, la résolution de tag, le mirror, le cache proxy et les magasins de contenu locaux peuvent échouer séparément. Kubernetes imagePullPolicy décide quand kubelet contacte le registre ; même Always utilise les couches déjà présentes localement si le digest résolu est disponible (Kubernetes – Images).

Un déploiement en production journalise le registre, le dépôt, le tag, le digest résolu, la plateforme, la décision concernant la signature/provenance et l’inventaire des nœuds. La garbage collection sur le registre ou le nœud ne doit pas supprimer les digests encore nécessaires à un rollback. L’exploitation air-gapped requiert en plus un processus de miroir, de clés, de révocation et de métadonnées.

Sécurité de la chaîne d’approvisionnement et de l’exécution

NIST distingue les risques liés aux images, aux registres, aux orchestrateurs, aux conteneurs et aux systèmes d’exploitation hôtes. Le résultat d’un scanner n’est qu’un signal : l’inventaire des paquets peut être incomplet, une CVE peut être inaccessible ou, inversement, une erreur propre à l’application peut rester invisible. Une politique relie provenance, signature, vulnérabilités connues, configuration et contexte d’exécution (NIST SP 800-190).

Les Kubernetes Pod Security Standards définissent les profils Privileged, Baseline et Restricted. Restricted exige notamment l’exécution non-root, un profil Seccomp et des capabilities fortement limitées ; les workloads concrets doivent néanmoins être testés fonctionnellement (Kubernetes – Pod Security Standards).

Au minimum, il convient de vérifier :

  • registre de confiance et digest immuable ;
  • provenance de build, signature et source de clés/d’identité contrôlée ;
  • image de base minimale et absence de secrets de build dans les couches ;
  • non-root, suppression de capabilities, Seccomp/LSM, système de fichiers racine en lecture seule, périphériques et montages limités ;
  • aucun socket runtime ou espace de noms hôte sans exception explicite ;
  • Network Policies ou pare-feu hôte et egress contrôlé ;
  • limites de ressources et de PID contre l’épuisement local ;
  • chemin de patch, rebuild, rollout et rollback.

Conteneurs Windows

Les conteneurs Windows utilisent des images Windows et des mécanismes du noyau Windows. Microsoft distingue Process Isolation, où les conteneurs partagent le noyau hôte, et Hyper-V Isolation, où chaque conteneur s’exécute dans une VM optimisée avec son propre noyau. Les deux utilisent le même format d’image et les mêmes outils de gestion, mais ont des limites d’isolation et de compatibilité différentes (Microsoft Learn – Windows and containers, Microsoft Learn – Isolation modes).

Avec Process Isolation, les systèmes d’exploitation hôte et conteneur doivent être compatibles. Hyper-V Isolation peut découpler certaines différences de version, mais augmente les coûts de ressources et de démarrage. Microsoft documente les combinaisons hôte/image prises en charge ; « conteneur Windows » est donc incomplet sans indication de l’image de base, du build et du mode d’isolation (Microsoft Learn – Windows container version compatibility).

Les nœuds Linux et Windows ne partagent ni le même noyau ni les mêmes binaires d’image. Les clusters multi-OS nécessitent des labels de planification, des DaemonSets adaptés, des plugins réseau/de stockage et des chemins de diagnostic distincts.

Mises à jour, rollout et rollback

Une mise à jour de conteneur est un changement d’image assorti d’une transition d’état. Avant le rollout, il faut vérifier les notes de version, les modifications de schéma, les étapes de migration, les versions minimales des services externes, les nouveaux ports/scopes et la rétrocompatibilité. Un rollback de l’image peut être impossible après une migration de données non rétrocompatible.

Le déroulement contrôlé est le suivant :

  1. consigner le digest cible, la signature, la provenance et la décision de scan ;
  2. créer une sauvegarde ou un point de reprise testé des données persistantes ;
  3. vérifier le diff de configuration et de schéma ;
  4. déployer un canary ou des réplicas progressifs avec des probes et SLO réels ;
  5. observer la migration des données et la capacité à fonctionner avec des versions mixtes ;
  6. vérifier le digest, les instances, les événements, les erreurs, la latence et les ressources ;
  7. ne déclencher un rollback que dans les limites de compatibilité des données démontrées.

Ce processus relie Releases, Migration et Backup/DR. Les outils automatiques de mise à jour de tags sans barrières fonctionnelles ne font que déplacer le moment du changement, du processus de changement vers un bot.

Sauvegarde et reprise après sinistre

Un service de conteneurs complet comprend davantage que des volumes :

  • définitions de déploiement, politiques et objets réseau ;
  • digests d’image enregistrés ou miroir de registre restaurable ;
  • configuration non sensible et sources de secrets/clés ;
  • données persistantes avec une procédure cohérente avec l’application ;
  • bases de données externes, files d’attente, stockages objet, dépendances DNS et d’identité ;
  • versions de schéma, tâches ouvertes et état de réconciliation ;
  • runbooks pour la perte d’un nœud, d’un cluster, d’un registre ou d’un site.

Une archive tar du chemin de volume peut être incohérente lorsqu’une base de données est en cours d’exécution. Les snapshots de stockage nécessitent une sémantique de gel/mise au repos ou propre à la base de données. Un test de restauration reconstruit le service, le réseau et les identités dans un environnement cible propre, démarre avec le digest sauvegardé et vérifie les données fonctionnelles ainsi que les files d’attente ouvertes.

En cas d’incident, la vérification va de l’artefact au processus, puis vers l’extérieur : image, paramètres de démarrage, droits, montages, résolution de noms, chemin réseau et services externes.

Diagnostic par couches de dépendances

Un incident de conteneur est circonscrit de l’extérieur vers l’intérieur :

  1. État souhaité : quelle définition et quel digest devraient s’exécuter ?
  2. Placement : sur quel hôte/nœud, avec quelle plateforme et quelle capacité ?
  3. Image : pull, authentification, manifeste, plateforme, signature et contenu local ?
  4. Runtime : sandbox, statut du conteneur, code de sortie, OOM, redémarrage et événements ?
  5. Processus : PID 1, signaux, utilisateur, capabilities et fichiers ouverts ?
  6. Stockage : montage attendu, backend, droits, capacité et E/S ?
  7. Réseau : espace de noms, DNS, route, politique, écouteur, service et TLS ?
  8. Application : santé, journaux, file d’attente, schéma, identifiant et dépendance externe ?
docker version
docker info
docker context show
docker compose config --images
docker compose ps --all
docker system df

docker version distingue les versions client et serveur, docker info affiche le contexte du moteur, du runtime, du stockage et de la sécurité, docker context show la cible effectivement administrée et docker system df la consommation de contenu local. uname établit, dans l’exemple Unix, le noyau et la plateforme.

Histoire technique

L’isolation des processus est plus ancienne que les images modernes. chroot d’Unix modifiait la racine du système de fichiers d’un processus, mais n’a jamais été conçu comme une limite de sécurité complète. Les jails FreeBSD ont étendu le modèle à la fin des années 1990, respectivement avec FreeBSD 4.0, par des vues hôte et réseau plus isolées ; les Solaris Zones ont associé l’isolation applicative et la gestion des ressources dans le système d’exploitation (FreeBSD Handbook – Jails, Oracle Solaris Zones Introduction).

Linux a introduit progressivement les espaces de noms et les Control Groups. LXC a combiné ces mécanismes du noyau en conteneurs système. Docker a popularisé à partir de 2013 les couches d’image, la distribution par registre, les Dockerfiles et une interface développeur cohérente ; il utilisait initialement LXC avant de passer ensuite à sa propre bibliothèque runtime (Linux Containers – LXC Introduction, Docker – What is a container?).

En 2015, des fabricants et fournisseurs de plateformes ont fondé l’Open Container Initiative afin de standardiser ouvertement les formats runtime et image. runc est devenu la base de runtime OCI ; containerd et CRI-O ont établi les runtimes de haut niveau. Kubernetes a abstrait les runtimes de nœud via CRI, les réseaux via CNI et le stockage via CSI. Aujourd’hui, « conteneur » ne désigne donc pas une pile de produits unique, mais une chaîne de spécifications et d’implémentations interopérables (Open Container Initiative – Overview, Kubernetes – Container Runtimes).

Checklist administrateur en un coup d’œil

Le conteneur n’est qu’une partie du service. Pour l’autorisation d’exploitation, l’artefact, le runtime, l’hôte, le réseau, le stockage et la reprise sont donc vérifiés comme une chaîne cohérente.

QuestionPreuve d’exploitation
Quel artefact s’exécute ?Registre, dépôt, tag, digest, plateforme, digest de configuration, signature/provenance
Quelle chaîne runtime s’applique ?Moteur/orchestrateur, CRI, runtime de haut niveau, runtime OCI, noyau hôte
Quelle isolation est active ?Espaces de noms, mode d’isolation Windows, mappage UID, capabilities, Seccomp, LSM
Où se trouve l’état ?Couche inscriptible, volume, Bind Mount, tmpfs et services externes par classe de données
Qu’est-ce qui est accessible ?Adresse d’écoute, IP de conteneur/pod, service, port publié, Ingress et politique d’egress
Qui possède l’identité ?UID/SID du processus, compte de service, identifiant de registre, jeton de workload et source de clés
Quelles limites s’appliquent ?CPU, mémoire, PID, E/S, disque, rotation des journaux, quota et éviction de nœud
Que signifie sain ?Processus, Startup, Readiness, Liveness, test fonctionnel et dépendances externes séparés
Comment modifier ?Digest approuvé, diff de schéma/configuration, canary, version mixte, fenêtre de rollback
Comment restaurer ?Définitions, registre/images, secrets/clés, données, files d’attente et test de restauration propre
Sources

Nouveaux articles par e-mail

Une courte notification lorsqu’un nouvel article pratique sur la messagerie, la sécurité ou Microsoft 365 paraît.

Adresse utilisée uniquement pour cette newsletter. Désinscription en un clic. Confidentialité

Infographie agrandie