DIGITAL AVENIR · Livre de cours

Docker — livraison et exploitation des applications

Comprenez les processus conteneurisés, construisez des images contrôlées et exploitez une application multi-service avec données persistantes, santé et procédure de reprise.

Docker Engine · Compose v2 · 8 leçons

Parcours pratique fondé sur la documentation officielle Docker Engine, Build et Compose. Il n’est pas présenté comme un examen de certification officiel ou une accréditation Docker ; ses questions sont originales.

Référence consultée le 2026-10-29.

https://docs.docker.com/get-started/

Support indépendant d’autoformation. Les exemples sont destinés à un laboratoire autorisé ; les fragments ne constituent pas une configuration universelle de production. Les corrections sont incluses dans ce livre. Chaque leçon commence sur une nouvelle page à l’impression.

Programme du cours

  1. Processus, images et cycle de vie
  2. Dockerfile, couches, cache et multi-stage
  3. Registres, tags, digests et provenance
  4. Réseaux, DNS et publication de ports
  5. Volumes, montages et sauvegardes cohérentes
  6. Compose, dépendances, santé et configuration
  7. Privilèges, secrets et limites du runtime
  8. Logs, arrêt propre et retour de version

Module 1 / 8 · 90 min

Processus, images et cycle de vie

Distinguer l’artefact immuable et l’instance qui s’exécute.

Comprendre le mécanisme

Une image est un modèle de système de fichiers et de configuration ; un conteneur est une instance avec un processus et une couche d’écriture. Arrêter une instance n’équivaut pas à supprimer son image. Les conteneurs utilisent les mécanismes du noyau hôte pour isoler des processus et ne sont pas des machines virtuelles complètes par nature. Le comportement exact de l’hôte varie notamment selon la plateforme d’exécution.

Raisonner et vérifier

Le processus principal détermine la vie du conteneur : lorsqu’il termine, l’instance s’arrête. Un processus en arrière-plan lancé par un shell peut donc disparaître avec son parent ou laisser une instance terminée. Préférez une commande principale au premier plan et comprenez la réception des signaux. Les données importantes ne doivent pas dépendre uniquement de la couche jetable de l’instance.

Modèle distribué et instance exécutée

Une image décrit un contenu et des paramètres utiles au lancement ; un conteneur exécute une instance selon une configuration. Deux conteneurs fondés sur la même image peuvent avoir des montages, variables et états différents. Pour diagnostiquer, notez donc l’identité de l’image et la configuration effective de l’instance. Le nom du projet ne suffit pas à décrire le processus réellement servi.

Erreur fréquente à comprendre Une image est nécessairement un processus en cours.

Le conteneur exécute une instance fondée sur une image.

Une isolation qui dépend de l’environnement

Un conteneur ne doit pas être assimilé systématiquement à une machine virtuelle disposant de son propre noyau complet. Les mécanismes d’isolation et l’environnement d’exécution définissent les frontières réelles. Cette distinction compte pour les droits et l’impact d’un code compromis. Dessinez les accès à l’hôte, aux volumes et au réseau ; le seul mot conteneur ne décrit pas toutes les capacités disponibles.

Erreur fréquente à comprendre Tout conteneur possède toujours son propre noyau complet de VM.

L’isolation ne correspond pas systématiquement à une machine virtuelle.

La couche écrivable n’est pas l’archive source

Les modifications de fichiers d’une instance ne republient pas automatiquement une nouvelle image dans le registre. La couche écrivable possède un cycle distinct et peut être jetable lors du remplacement du conteneur. N’y conservez pas l’unique copie de données métier durables. Définissez stockage, sauvegarde et restauration selon le besoin, puis testez le remplacement complet de l’instance avec ces données.

Erreur fréquente à comprendre Écrire un fichier modifie automatiquement le registre source.

Les changements d’instance ne republient pas l’image.

Le processus principal porte le cycle de vie

Lorsque le processus principal termine normalement selon ce modèle, le conteneur s’arrête. Un service lancé en arrière-plan peut donc laisser son wrapper terminer alors que l’intention était de maintenir le service disponible. Gardez le processus principal au premier plan selon son contrat. Les tests doivent observer démarrage, fin nominale et échec, sans conclure qu’une image construite reste automatiquement en exécution.

Erreur fréquente à comprendre Un conteneur reste toujours actif après la fin de tout processus.

Son cycle dépend de l’exécution principale.

Le tag est une référence qui peut bouger

Un tag comme latest est un nom dont le contenu cible peut évoluer selon le registre. L’utiliser ne prouve pas que deux déploiements successifs exécutent le même artefact. Pour une analyse d’incident, conservez l’identité du contenu réellement résolu. Une politique de mise à jour doit être explicite : la commodité d’un nom stable ne remplace pas une trace de version.

Erreur fréquente à comprendre Un tag est une identité de contenu immuable par définition.

Le registre peut associer le même nom à un autre contenu.

Le digest identifie, sans certifier la qualité

Un digest relie une référence à un contenu selon le format concerné. Il aide à vérifier l’identité de l’artefact, mais ne prouve pas l’absence de vulnérabilité ni la légitimité de l’éditeur. Ces propriétés demandent d’autres contrôles et une politique de confiance. Pour une image multi-plateforme, notez aussi la plateforme effectivement choisie afin de décrire l’instance réelle.

Erreur fréquente à comprendre Un digest prouve automatiquement la confiance dans l’éditeur.

L’identité de contenu et la provenance sont distinctes.

Transmettre les signaux au bon acteur

La forme de lancement et les wrappers influencent la réception des signaux d’arrêt. Un shell ajouté sans gestion adaptée peut rendre le cycle moins direct que la forme exec prévue pour le processus principal. Définissez l’arrêt gracieux et son délai, puis observez le comportement réel. Un arrêt forcé qui semble rapide ne prouve pas que les travaux en cours ont été terminés ou repris correctement.

Erreur fréquente à comprendre Tout wrapper shell transmet toujours parfaitement les signaux.

Le mode de lancement et le wrapper influencent le comportement.

Une variable d’environnement reste une donnée sensible

Injecter un secret par environnement ne le rend pas impossible à observer. Le processus qui le consomme et certains outils de diagnostic peuvent y avoir accès selon les droits. Limitez distribution, journalisation et conservation. Les exemples de laboratoire doivent utiliser des valeurs publiques fictives. Retirer une variable d’une nouvelle release ne révoque pas une capacité déjà exposée dans une ancienne copie.

Erreur fréquente à comprendre Une variable d’environnement est impossible à observer par tout outil.

Sa distribution et sa visibilité demandent une politique.

Ajouter les restrictions nécessaires

L’isolation disponible doit être complétée par des choix de runtime : utilisateur, capacités, montages, accès au socket et ressources selon le besoin. Un processus non privilégié peut encore présenter des vulnérabilités métier. La défense doit donc limiter les conséquences tout en maintenant les contrôles applicatifs. Vérifiez les restrictions effectives plutôt que leur seule présence dans un commentaire de configuration.

Erreur fréquente à comprendre Le mot conteneur garantit toute sécurité contre tout code hostile.

Les capacités et interfaces exposées comptent.

Tester le conteneur réellement livré

Une construction réussie ne démontre pas le démarrage ni le comportement du service. Lancez l’artefact avec une configuration représentative et vérifiez le parcours utile, les erreurs et l’arrêt. Conservez image, paramètres et résultat dans la preuve. Tester depuis le poste avec des fichiers non embarqués peut masquer une dépendance manquante ; un environnement propre rend ces hypothèses visibles.

Erreur fréquente à comprendre Une image construite prouve la disponibilité du service.

Construction et exécution sont des étapes différentes.

Atelier guidé : lire, expliquer et vérifier le code

FROM php:8.4-cli
COPY worker.php /app/worker.php
CMD ["php", "/app/worker.php"]

Le CMD de l’atelier est écrit en forme JSON dite exec. Il décrit le lancement du processus PHP avec son script, sans demander ici une forme shell qui interpréterait la commande comme une ligne de shell. L’extrait ne publie aucun port et ne déclare aucun volume ; ces propriétés demanderaient leur propre configuration.

Dans le laboratoire, lancez un script qui attend puis traite un arrêt contrôlé. Comparez la forme de lancement et la transmission des signaux en observant les événements du processus. Remplacez ensuite entièrement le conteneur et examinez les fichiers persistants attendus. Ces expériences séparent contenu d’image, cycle de processus et stockage, au lieu de considérer qu’un seul Dockerfile démontre le fonctionnement complet du service.

Exemple commenté

docker run --name lab-hello --rm alpine:3.22 echo "reservation lab"
# La commande termine ; le conteneur est supprimé grâce à --rm.

L’instance n’est pas un service permanent : elle exécute echo puis termine. L’image et le conteneur ont des cycles de vie distincts.

Exercice de mise en pratique

Lancez un conteneur au premier plan, observez sa sortie puis comparez docker ps et docker ps -a.

Voir une proposition de correction

Exécutez une commande courte sans --rm pour inspecter ensuite son état et son code de sortie. Supprimez uniquement les ressources nommées du laboratoire.

Contrôle de connaissances

Que se passe-t-il normalement quand le processus principal termine ?

Réponse expliquée : Le conteneur s’arrête — Le cycle de vie suit le processus principal.

Cours associé : Processus, images et cycle de vie ↗

Documentation de référence ↗ https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/

Module 2 / 8 · 90 min

Dockerfile, couches, cache et multi-stage

Construire un runtime sans embarquer tout l’outillage de construction.

Comprendre le mécanisme

Chaque étape d’un Dockerfile participe à la construction d’une image et à son cache. Copier les fichiers de dépendances avant le code changeant peut éviter de recalculer une installation coûteuse. Un build multi-stage nomme plusieurs étapes puis copie uniquement les artefacts nécessaires vers le runtime. Un fichier supprimé dans une couche ultérieure peut rester récupérable dans une couche antérieure : supprimer un secret après COPY ne suffit pas.

Raisonner et vérifier

Réduisez le contexte avec .dockerignore et fournissez les secrets de build par un mécanisme temporaire adapté. Le processus de build ne doit pas recopier le secret dans un artefact ou un log. Une image petite n’est pas une preuve de sûreté ; vérifiez aussi provenance, dépendances, permissions et fonctionnement. N’exécutez pas une résolution libre de versions si vous recherchez un artefact reproductible.

Séparer construction et exécution

Un build multi-stage permet de placer l’outillage de construction dans une étape puis de copier les artefacts utiles vers une étape runtime. Cette copie ciblée peut réduire ce qui est distribué. Elle ne doit pas oublier les dépendances nécessaires à l’exécution. Décrivez le contenu attendu de chaque étape et testez l’image finale seule ; un succès dans l’étape de build ne prouve pas qu’elle contient le bon livrable runtime.

Erreur fréquente à comprendre Toute étape de build est forcément copiée intégralement dans l’image finale.

Les copies peuvent sélectionner les artefacts utiles.

Réduire le contexte envoyé au build

Le contexte peut inclure des fichiers locaux inutiles ou sensibles avant même les instructions du Dockerfile. .dockerignore aide à en exclure des éléments selon son contrat. Vérifiez les chemins réellement envoyés et évitez de compter seulement sur une suppression ultérieure. Un répertoire de développement peut contenir logs, sauvegardes et credentials qui n’appartiennent pas au périmètre de distribution du code.

Erreur fréquente à comprendre Tout fichier local est sûr à envoyer au build.

Le contexte peut contenir des données sensibles.

Une suppression tardive ne retire pas toute trace

Copier un secret dans une couche puis le supprimer dans une instruction ultérieure ne garantit pas qu’il a disparu de l’historique d’image. La vue finale n’est pas toute l’archive distribuée. La bonne question est de savoir où la capacité a été exposée et quelles copies existent. Si le secret a réellement fuité, changer le build futur doit accompagner une procédure de retrait et de rotation.

Erreur fréquente à comprendre Supprimer plus tard garantit l’absence du secret dans toute couche.

L’historique d’image doit être considéré.

Utiliser un mécanisme de secret adapté au build

Les montages de secrets ou mécanismes SSH prévus pour la construction peuvent exposer temporairement une capacité à l’instruction qui en a besoin. ARG et ENV ne constituent pas un coffre universel. Configurez l’entrée du secret et son usage sans le recopier dans l’artefact ou les logs. Un outil de build peut toujours divulguer une valeur qu’un script imprime ; le mécanisme demande donc une utilisation cohérente.

Erreur fréquente à comprendre ARG est toujours un coffre de secret sans exposition possible.

Les paramètres de build ne sont pas une garantie universelle de confidentialité.

Verrouiller les dépendances utiles

Des manifestes et versions verrouillées aident à reproduire les dépendances installées. Une résolution flottante peut changer l’image alors que le code applicatif paraît identique. Conservez les versions, l’outil de construction et la plateforme. Cette reproductibilité ne démontre pas l’absence de défauts : elle rend leur identification et la comparaison de deux builds plus précises.

Erreur fréquente à comprendre Une contrainte flottante produit toujours le même artefact.

La résolution peut évoluer dans le temps.

Organiser les étapes pour le cache

L’ordre des instructions influence les possibilités de réutilisation du cache. Copier les manifestes de dépendances avant le code qui change souvent peut éviter de réinstaller tout lorsque ces manifestes restent identiques. Cette stratégie doit conserver le bon contrat : une entrée réellement nécessaire ne doit pas être cachée hors du calcul. Mesurez le gain et vérifiez que l’artefact contient effectivement la version attendue.

Erreur fréquente à comprendre Toute modification invalide nécessairement toutes les couches antérieures.

Le cache dépend des étapes et de leurs entrées.

Conserver les besoins du runtime

Copier un binaire ou un répertoire ne prouve pas que toutes les bibliothèques, fichiers de configuration et ressources utiles sont présents. Les dépendances dynamiques et la plateforme comptent. Lancez la dernière étape sans les répertoires du poste ni les outils de build, puis exercez le parcours utile. Une image plus petite n’est une amélioration que si elle conserve les capacités prévues.

Erreur fréquente à comprendre Copier seulement un binaire garantit toujours toute dépendance dynamique.

Les besoins d’exécution doivent être vérifiés.

Construire n’est pas tester la santé

Le succès de docker build indique que les instructions ont abouti dans le contexte de construction. Il ne prouve pas que la base est joignable, que le serveur accepte les demandes ou que l’application expose la bonne release. Ajoutez une exécution contrôlée et un health check représentatif. Le diagnostic doit distinguer erreur de construction, configuration runtime et panne de dépendance.

Erreur fréquente à comprendre La construction valide toutes les routes en production.

Les contrôles runtime demandent une exécution.

Choisir la plateforme cible

Une image et ses artefacts doivent correspondre à l’architecture et aux capacités de l’environnement d’exécution. Un build réalisé sur une machine ne prouve pas une exécution native sur toutes les autres. Documentez la plateforme demandée et celle réellement servie, notamment avec les images multi-plateformes. Les tests hors de l’IDE doivent vérifier l’artefact destiné au déploiement, pas seulement un assemblage local différent.

Erreur fréquente à comprendre Toute image s’exécute nativement sur toute architecture.

Architecture et compatibilité influencent l’exécution.

Inspecter sans exposer les secrets

Le contenu final et les métadonnées d’image doivent pouvoir être revus avec des fixtures publiques de laboratoire. Cherchez fichiers inattendus, logs et traces de credentials selon le périmètre de votre outil. Une absence dans la vue courante ne prouve pas toute l’histoire des couches. Les preuves doivent montrer la propriété recherchée et ses limites sans publier elles-mêmes la capacité que la revue voulait protéger.

Erreur fréquente à comprendre Un test d’image exige les credentials de production embarqués.

Le laboratoire peut utiliser des valeurs fictives.

Atelier guidé : lire, expliquer et vérifier le code

FROM composer:2 AS build
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts
FROM php:8.4-cli
COPY --from=build /app/vendor /app/vendor

La dernière étape de l’exemple copie seulement le répertoire vendor issu de build. Elle ne reçoit pas automatiquement tout le système de fichiers de cette étape. L’extrait montre une séparation et une sélection d’artefact, mais ne suffit pas à démarrer un service HTTP complet : le code applicatif, ses ressources et sa commande doivent encore être définis selon le produit.

Construisez une image de laboratoire avec un fichier témoin présent uniquement dans l’étape de build. Vérifiez qu’il n’apparaît pas dans la dernière étape si aucune copie ne le sélectionne. Examinez ensuite les besoins runtime réels et lancez le livrable dans un environnement propre. Une copie ciblée est une technique de distribution, pas une garantie automatique de complétude ni de sécurité du contenu copié.

Secrets de build : une suppression ultérieure ne retire pas la couche

Une image est construite à partir de couches et de métadonnées. Copier un token dans une couche puis le supprimer dans une instruction ultérieure peut le laisser récupérable dans l’historique de construction ou les artefacts intermédiaires.

Utilisez un secret de build monté temporairement à l’étape qui en a besoin. Le montage évite son inscription automatique comme fichier de l’image, mais la commande exécutée pourrait toujours le recopier dans une sortie, un cache ou un log. Contrôlez donc le comportement du gestionnaire de dépendances et les fichiers conservés dans l’image finale.

Vérifiez également contexte de build et fichiers exclus : un secret ne doit pas être envoyé inutilement au builder. Testez avec une valeur factice identifiable et examinez image finale, couches et logs selon votre pipeline. Si une valeur réelle a déjà été publiée, corriger le Dockerfile traite les prochains builds ; la capacité exposée demande séparément retrait et rotation.

Points de vigilance : Base64 ne protège pas un secret récupérable dans une couche. Le montage fournit le secret à l’étape nécessaire sans l’inscrire automatiquement dans l’image ; l’étape ne doit pas le divulguer. ARG et une copie vers l’image ne constituent pas un mécanisme approprié pour les secrets. Le contrôle du registre limite l’accès, mais ne supprime pas les octets des couches.

Documentation de référence ↗

Exemple commenté

FROM alpine:3.22 AS build
RUN mkdir /out && printf "reservation lab" > /out/message
FROM alpine:3.22
COPY --from=build /out/message /message
CMD ["cat", "/message"]

Seul l’artefact explicitement copié passe vers l’étape finale. Dans une application réelle, remplacez la fabrication de texte par la compilation ou l’installation vérifiée des dépendances.

Exercice de mise en pratique

Dessinez les étapes d’une application nécessitant un compilateur au build mais pas au runtime.

Voir une proposition de correction

Placez le compilateur dans une étape nommée, copiez le binaire et ses dépendances runtime utiles dans une autre étape. Vérifiez l’exécution et l’absence des fichiers de travail non nécessaires.

Contrôle de connaissances

Quel mécanisme sépare outillage de build et artefact runtime ?

Réponse expliquée : Un build multi-stage avec copie ciblée — Les étapes permettent de sélectionner les artefacts finaux.

Cours associé : Dockerfile, couches, cache et multi-stage ↗

Documentation de référence ↗ https://docs.docker.com/build/building/multi-stage/

Module 3 / 8 · 90 min

Registres, tags, digests et provenance

Identifier précisément l’artefact livré et sa chaîne de confiance.

Comprendre le mécanisme

Un tag est un nom de référence susceptible d’être déplacé ; un digest identifie un contenu de manifeste. Utiliser une référence par digest aide à retrouver l’artefact attendu, sans démontrer à lui seul qu’il est sans vulnérabilité. Une image multi-plateforme peut pointer vers des variantes : identifiez aussi la plateforme effectivement utilisée. La provenance et la politique de confiance font partie du choix d’image.

Raisonner et vérifier

Conservez le lien entre commit, tests, build et image poussée au registre. Un scan et une nomenclature de dépendances apportent des informations à une date donnée, pas une garantie éternelle. Une mise à jour doit être reconstruite, testée et promue de façon contrôlée. Le retour de version doit cibler un artefact connu, avec vérification de compatibilité des données.

Comprendre la mutabilité d’un nom

Un tag est une référence nommée qui peut être réaffectée selon la politique du registre. Deux lancements séparés d’un même nom ne prouvent donc pas un contenu identique. Conservez la résolution effective lors du déploiement et prévoyez la politique de mise à jour. Cette trace aide à distinguer changement de configuration et changement d’artefact lorsque le nom apparent du service reste inchangé.

Erreur fréquente à comprendre latest désigne toujours le même contenu.

Le nom est une référence mutable selon le registre.

Fixer un contenu ne le rend pas exempt de défauts

Un digest aide à identifier précisément le contenu choisi. Il ne corrige pas les vulnérabilités que ce contenu peut déjà posséder ou qui seront découvertes plus tard. La maintenance doit donc savoir quel artefact est exécuté puis décider de sa mise à jour. L’immuabilité d’une référence facilite cette décision ; elle ne remplace pas l’analyse des risques et la vérification du nouveau comportement.

Erreur fréquente à comprendre Fixer un digest garantit une absence de vulnérabilités.

Le contenu exact peut encore avoir des défauts.

Établir une provenance de confiance

Une empreinte correcte montre une relation avec des octets attendus, pas automatiquement la légitimité de leur producteur. Une image malveillante possède aussi une identité de contenu. Définissez les éditeurs et processus admis ainsi que les preuves pertinentes pour votre distribution. Le téléchargement depuis un emplacement connu ne doit pas devenir une confiance indéfinie dans toute future publication portant un nom ressemblant.

Erreur fréquente à comprendre Un hash valide prouve tout auteur légitime.

L’intégrité ne fournit pas seule l’identité de l’éditeur.

Limiter les credentials du registre

Lire une image, publier un nouveau contenu et supprimer des artefacts sont des capacités différentes. Distribuez aux consommateurs le périmètre nécessaire plutôt qu’un credential universel. Les outils de diagnostic et de build ne doivent pas recopier ces secrets dans leurs sorties. Une compromission doit pouvoir être reliée à ses opérations possibles et à une procédure de retrait adaptée.

Erreur fréquente à comprendre Un lecteur d’image doit toujours pouvoir supprimer tout registre.

Les opérations demandent des privilèges différents.

Conserver ce qui permet la reprise

Une politique de rétention peut supprimer un ancien artefact nécessaire à un retour arrière. Définissez les versions qui doivent rester accessibles et leur durée utile, sans conserver aveuglément toutes les données indéfiniment. Le test de rollback doit récupérer et lancer la référence réellement conservée. L’existence d’un nom de version dans un document ne prouve pas la disponibilité de ses couches dans le registre.

Erreur fréquente à comprendre Supprimer tout ancien artefact ne peut gêner aucun rollback.

La reprise peut dépendre d’un contenu antérieur disponible.

Décrire l’image multi-plateforme exécutée

Une référence multi-plateforme peut conduire à des contenus adaptés à des architectures différentes. Pour une release traçable, notez la plateforme cible effectivement choisie en plus de la référence générale. Une panne spécifique à une architecture peut rester invisible sur le poste de build. Les preuves doivent donc relier la machine, le contenu résolu et le parcours exécuté.

Erreur fréquente à comprendre Le même tag impose toujours la même architecture à tous les clients.

La sélection peut dépendre de la plateforme.

Vérifier une signature avec une politique

La présence d’une signature ne suffit pas si le consommateur accepte n’importe quelle clé ou n’importe quel éditeur. La politique doit définir les autorités et usages admis, puis vérifier les éléments pertinents avant exécution. Le contenu signé peut encore comporter des défauts ; authenticité de distribution et sécurité de l’application restent des propriétés différentes. Documentez ce que votre contrôle de signature démontre exactement.

Erreur fréquente à comprendre Toute signature quelconque suffit quel que soit son auteur.

Le consommateur doit connaître les autorités admises.

Un scan possède une date et un périmètre

Un scan compare un contenu à un référentiel et des règles à un moment donné. Un rapport vert ne garantit pas toute sécurité future ni l’absence de défauts inconnus. Conservez l’identité analysée, la version de l’outil et les limites du contrôle. Lorsqu’un nouveau risque apparaît, cette traçabilité permet de déterminer quelles releases sont concernées et quel contrôle complémentaire devient nécessaire.

Erreur fréquente à comprendre Un scan vert garantit toute sécurité future.

Les connaissances et dépendances peuvent évoluer.

Relier le commit à l’image déployée

Une chaîne de preuve utile relie source, tests, build et identité de l’image effectivement lancée. Un succès de test sur un commit ne couvre pas un autre contenu construit manuellement ensuite. Évitez les substitutions silencieuses entre étapes et vérifiez l’identité servie après la bascule. Le nom du projet ne suffit pas pour diagnostiquer quelle version a produit un incident.

Erreur fréquente à comprendre Le nom du projet suffit à identifier exactement la release.

La référence et le contenu doivent être enregistrés.

Protéger le téléchargement et son destinataire

Le transport vers le registre doit vérifier le pair prévu selon le modèle TLS utilisé. Désactiver la vérification de certificat pour contourner une erreur retire une garantie importante. Corrigez la chaîne, le nom ou le magasin de confiance en conservant le contrôle. Cette vérification de canal complète la politique de provenance du contenu ; elle ne donne pas, seule, une assurance sur tout ce que l’image exécutera.

Erreur fréquente à comprendre Désactiver TLS rend tout téléchargement authentique.

Le contournement retire une protection de transport.

Atelier guidé : lire, expliquer et vérifier le code

services:
  api:
    image: example/lab-api:latest

Le fichier Compose de l’atelier utilise le tag latest. Cette référence peut rester identique dans le texte tout en visant un autre contenu au registre. Le YAML ne constitue donc pas une preuve d’immutabilité de l’artefact. Il ne dit pas non plus que le contenu est sans vulnérabilité ou que toute mise à jour est interdite.

Pour le laboratoire, relevez la référence résolue puis comparez deux publications contrôlées sous un même tag. Définissez ensuite une référence et une trace adaptées à votre processus de release. Si plusieurs plateformes sont proposées, notez celle réellement exécutée. La conclusion doit permettre de retrouver ce qui a été testé et servi, sans confondre identité des octets et légitimité ou qualité de leur producteur.

Exemple commenté

docker image inspect lab-app:release
# Relever notamment l’identité, la plateforme et les références de digest disponibles.

Une inspection rend l’artefact observable. Pour une référence distribuée, enregistrez le digest réellement publié plutôt que supposer qu’un tag nomme toujours les mêmes octets.

Exercice de mise en pratique

Définissez une fiche de release liant révision Git, digest publié, plateforme et résultats de tests.

Voir une proposition de correction

Construisez une fois, poussez l’image puis enregistrez son identité. Déployez cette référence et vérifiez l’image en exécution. Simulez un tag déplacé pour montrer la limite d’un nom seul.

Contrôle de connaissances

Un tag identifie-t-il nécessairement le même contenu pour toujours ?

Réponse expliquée : Non, il peut être déplacé — Le nom de référence est mutable.

Cours associé : Registres, tags, digests et provenance ↗

Documentation de référence ↗ https://docs.docker.com/dhi/explore/security-concepts/digests/

Module 4 / 8 · 90 min

Réseaux, DNS et publication de ports

Relier les services sans publier inutilement les dépendances.

Comprendre le mécanisme

Le réseau d’un conteneur est distinct du contexte réseau de l’application hôte. Dans un conteneur, localhost désigne normalement ce conteneur, pas un autre service. Sur un réseau utilisateur approprié, les services peuvent se joindre par leurs noms. Publier un port associe une écoute hôte à une écoute de conteneur ; EXPOSE documente une intention dans l’image mais ne crée pas à lui seul cette publication.

Raisonner et vérifier

Ne publiez une base sur l’hôte que si un besoin explicite le justifie et contrôlez l’interface d’écoute. Une communication interne entre services n’exige pas nécessairement une ouverture publique. Vérifiez les chemins réels : navigateur vers reverse proxy, proxy vers application, application vers base. Un test depuis l’hôte ne démontre pas toute la résolution DNS interne.

EXPOSE est une indication de l’image

EXPOSE documente un port attendu par le service ; cette instruction ne publie pas automatiquement ce port sur les interfaces de l’hôte. La publication demande une configuration de lancement distincte. Lors d’une revue, séparez ce que l’image décrit de ce que l’instance expose réellement. Une ligne présente dans le Dockerfile ne prouve donc ni accessibilité depuis Internet ni isolement complet du service.

Erreur fréquente à comprendre EXPOSE publie automatiquement le port sur toutes les interfaces hôtes.

La publication réseau demande une configuration distincte.

L’adresse de binding fixe une portée

Publier un port avec une adresse hôte explicite choisit une portée d’écoute selon le contexte. Une liaison à 127.0.0.1 n’a pas le même périmètre qu’une écoute générale. Vérifiez les règles du moteur et de l’hôte réellement utilisés. Le test doit provenir d’un point de réseau pertinent : une connexion locale réussie ne prouve pas l’accès depuis l’extérieur, et l’inverse ne doit pas être supposé.

Erreur fréquente à comprendre Publier un port implique toujours localhost seulement.

La portée dépend de l’adresse et des paramètres.

Localhost appartient au contexte courant

Dans le modèle réseau habituel du conteneur, localhost désigne son propre contexte de boucle locale. Il ne signifie pas automatiquement le conteneur voisin ni le serveur de base. Pour joindre une dépendance, utilisez le nom et le réseau prévus par le déploiement. Exécutez le diagnostic depuis le conteneur applicatif afin d’exercer sa résolution et sa connectivité, pas seulement celles du poste hôte.

Erreur fréquente à comprendre localhost désigne forcément le conteneur voisin.

Les espaces réseau ont leurs propres boucles locales.

Résoudre les services par leur contrat

Un réseau Compose peut fournir une résolution par nom de service. Ce nom permet d’éviter de traiter une adresse d’instance éphémère comme une identité fixe éternelle. La présence du nom ne prouve pas encore la disponibilité métier de la dépendance. Testez résolution, connexion et requête utile séparément pour localiser une panne sans attribuer à tout échec SQL une cause de mot de passe.

Erreur fréquente à comprendre Les IP de conteneurs doivent être supposées fixes pour toujours.

Le nom est une abstraction plus stable selon le contrat réseau.

Vérifier la frontière effectivement exposée

Les ports publiés, interfaces et règles de pare-feu participent à l’accès réel. Une étiquette private dans un document ne bloque pas une publication ouverte. Inventoriez les services qui ont besoin d’une entrée externe et ceux qui peuvent rester sur un réseau interne. Le contrôle doit observer le chemin déployé ; un fichier de configuration seul ne démontre pas que toutes ses règles sont appliquées.

Erreur fréquente à comprendre Une étiquette private rend toute exposition impossible.

Les accès effectifs dépendent de la configuration réelle.

TLS se termine quelque part

Une terminaison TLS au proxy protège le canal jusqu’à cette frontière. Elle ne chiffre pas automatiquement la connexion interne vers l’application. Décrivez chaque saut et les hypothèses de confiance correspondantes. La configuration du proxy doit aussi maîtriser les champs de contexte transmis. Le schéma annoncé par un client non fiable ne doit pas décider librement de la sécurité perçue du parcours.

Erreur fréquente à comprendre La présence d’un proxy chiffre automatiquement tout réseau interne.

Chaque saut doit avoir son propre modèle de protection.

Communiquer sans publication hôte

Deux services connectés à un réseau prévu peuvent communiquer sans que chaque port soit publié vers l’hôte ou Internet. Une base réservée à l’application n’a donc pas nécessairement besoin d’une exposition externe. Cela ne supprime pas l’authentification et les permissions SQL. Limitez les voies d’accès utiles, puis testez le parcours réellement utilisé par le consommateur plutôt qu’ouvrir une interface supplémentaire uniquement pour faciliter un diagnostic.

Erreur fréquente à comprendre Absence de port hôte signifie absence de toute communication.

Les réseaux internes peuvent permettre des échanges.

L’absence de port public ne bloque pas les sorties

Une politique d’entrée et une politique de sortie répondent à des directions différentes. Un conteneur sans port publié peut encore appeler des services distants selon sa configuration. Pour un client HTTP piloté par des données reçues, limitez les destinations et les budgets. La confidentialité d’une dépendance interne ne doit pas être supposée à partir de la seule absence d’une publication de port sur l’application.

Erreur fréquente à comprendre Un conteneur sans port publié ne peut contacter aucune destination.

Entrée et sortie sont des directions distinctes.

DNS et redirections peuvent changer la destination

Un nom initialement admis peut conduire à d’autres adresses, et une redirection peut choisir un autre hôte. Le client doit suivre un contrat de sortie maîtrisé sur tout le parcours. Évitez de considérer HTTPS comme une autorisation universelle de destination. Les tests doivent simuler un partenaire qui redirige hors du périmètre et vérifier que le service ne contacte pas librement une ressource interne.

Erreur fréquente à comprendre Un nom autorisé prouve toute destination réseau future.

La résolution et les sauts peuvent modifier la destination effective.

Observer depuis les bons points

Un diagnostic réseau doit préciser d’où la demande est émise et quel saut il mesure. L’hôte, un conteneur applicatif et un navigateur distant peuvent avoir des résolutions et règles différentes. Conservez les versions, noms et erreurs expurgées. Cette chronologie évite les corrections aveugles, comme publier la base mondialement alors que le défaut concernait seulement le nom de service utilisé dans le conteneur.

Erreur fréquente à comprendre Un fichier YAML suffit à prouver toute connectivité déployée.

Les règles et le runtime doivent être confrontés.

Atelier guidé : lire, expliquer et vérifier le code

services:
  api:
    image: example/lab-api:1
    ports:
      - "127.0.0.1:8080:80"

La publication montrée utilise 127.0.0.1 comme adresse hôte et 8080 comme port hôte, vers le port 80 du conteneur. Elle demande donc une portée locale dans ce contexte, pas une écoute générale du port 80 de l’hôte. Le registre d’image n’est pas l’interface de publication et ne décide pas de cette adresse.

Vérifiez le mapping dans un laboratoire depuis l’hôte puis depuis un autre point réseau prévu pour le test. Comparez avec une communication entre services qui utilise le réseau interne plutôt que le port publié. Documentez les résultats sans les extrapoler à toute topologie. Une configuration peut être correcte pour un proxy local et insuffisante ou trop large pour un autre mode de déploiement.

Exemple commenté

docker network create lab-network
# Deux services du laboratoire peuvent ensuite rejoindre lab-network.
# Une publication locale illustrative :
docker run --rm -p 127.0.0.1:8081:80 nginx:alpine

Le port 80 du conteneur est accessible ici via 8081 sur la boucle locale de l’hôte. Ce fragment ne publie pas le service sur toutes les interfaces hôte.

Exercice de mise en pratique

Dessinez le réseau de trois services et n’exposez vers l’hôte que le point d’entrée nécessaire.

Voir une proposition de correction

Placez application et base sur un réseau partagé, utilisez le nom de service pour la connexion et testez depuis le conteneur appelant. Contrôlez les ports réellement publiés.

Contrôle de connaissances

Dans un conteneur applicatif, localhost désigne normalement quoi ?

Réponse expliquée : Le même contexte réseau de conteneur — Il ne désigne pas automatiquement un autre service.

Cours associé : Réseaux, DNS et publication de ports ↗

Documentation de référence ↗ https://docs.docker.com/engine/network/

Module 5 / 8 · 90 min

Volumes, montages et sauvegardes cohérentes

Séparer persistance des données et durée de vie de l’instance.

Comprendre le mécanisme

Un volume géré par Docker persiste indépendamment d’une instance donnée selon son cycle de vie. Un bind mount expose un chemin de l’hôte et lie davantage le conteneur à cet environnement. Monter un volume au-dessus d’un répertoire existant masque le contenu visible sous ce point de montage. La persistance n’est pas une sauvegarde : suppression, corruption ou erreur métier peuvent affecter les données durables.

Raisonner et vérifier

Pour une base active, copier des fichiers à un moment arbitraire n’est pas forcément une sauvegarde cohérente. Utilisez une procédure supportée par le moteur ou un instantané cohérent selon son contrat. Testez la restauration dans une instance et un volume séparés. Les options de lecture seule et permissions limitent certains accès, sans remplacer le choix du propriétaire des données et les droits du processus.

Le stockage possède son propre cycle de vie

Un volume peut survivre au remplacement d’un conteneur selon sa configuration et les opérations effectuées. Cette persistance permet de séparer les données de l’instance, mais ne promet pas une survie à toute suppression ou perte d’hôte. Définissez qui possède le volume, comment il est conservé et comment il est restauré. Un test doit remplacer réellement l’instance tout en vérifiant les données attendues.

Erreur fréquente à comprendre Supprimer un conteneur détruit nécessairement tout volume nommé.

Les cycles de vie sont distincts.

Le bind mount dépend du chemin hôte

Un bind mount relie un emplacement de l’hôte à une vue dans le conteneur. Sa disponibilité et ses permissions dépendent donc aussi de cet hôte. Un chemin existant sur le poste peut manquer sur le serveur ou contenir un autre contenu. Documentez la source et la destination, puis testez l’environnement cible proprement au lieu de déduire la portabilité depuis une exécution locale confortable.

Erreur fréquente à comprendre Un bind mount est indépendant de toute arborescence hôte.

La source pointe vers le système hôte.

Persistance et sauvegarde sont deux capacités

Un volume conservé n’est pas automatiquement une copie indépendante et restaurable. Il peut subir une suppression logique, une corruption ou une perte avec son support. Une sauvegarde doit avoir un périmètre, une conservation et une procédure de restauration vérifiée. Les tests doivent observer cette reprise, pas seulement la présence d’un nom de volume dans un fichier de configuration.

Erreur fréquente à comprendre Un volume présent prouve la restauration après perte d’hôte.

La reprise demande une copie et un test adaptés.

Ce qui est visible sous un montage

Monter une ressource sur un répertoire déjà rempli peut masquer le contenu présent dans l’image sous ce point. Cela explique certains écarts entre inspection d’image et comportement d’instance. Comparez les deux vues avant de conclure que le build a oublié des fichiers. Le montage n’est pas une fusion universelle de tous les contenus ; ses options et son type doivent être compris selon le contrat utilisé.

Erreur fréquente à comprendre Monter un répertoire fusionne toujours toute donnée visible sans effet.

Le point monté change la vue des chemins concernés.

Aligner les permissions avec l’utilisateur runtime

Le conteneur utilise un utilisateur et des droits qui doivent permettre les écritures réellement nécessaires, sans élargir tout le stockage. Un volume ne rend pas magiquement tous ses fichiers accessibles à tous les processus. Testez la création, la lecture et la reprise avec l’identité runtime déployée. Une correction qui accorde tous les droits sans limite peut cacher le défaut initial et agrandir le périmètre d’impact.

Erreur fréquente à comprendre Un volume rend tous les fichiers lisibles par tout utilisateur sans contrôle.

Les droits du système de fichiers restent pertinents.

La lecture seule limite une direction

Un montage en lecture seule peut refuser des modifications par ce point d’accès. Il ne chiffre pas les données et ne décide pas si l’acteur métier peut les consulter. Le service peut aussi disposer d’autres chemins d’écriture selon sa configuration. Décrivez précisément la propriété visée et testez l’opération interdite, puis maintenez les contrôles d’autorisation et de confidentialité nécessaires à la distribution.

Erreur fréquente à comprendre Read-only chiffre automatiquement les données.

Une restriction d’écriture n’est pas une confidentialité.

Sauvegarder une base dans un état cohérent

Copier arbitrairement les fichiers d’une base active peut produire une copie qui ne respecte pas les conditions de reprise du moteur. Utilisez une méthode de sauvegarde adaptée et conservez ses préconditions, journaux et versions nécessaires. La taille d’une archive ne prouve pas sa cohérence. Restaurez-la dans un laboratoire et vérifiez des invariants métier pour démontrer une capacité utile.

Erreur fréquente à comprendre Copier au hasard des fichiers actifs garantit toute base restaurable.

Le moteur et son état doivent être pris en compte.

Partager ne sérialise pas les opérations

Plusieurs conteneurs peuvent accéder à des données communes selon le montage choisi. Cette accessibilité ne rend pas atomiques les écritures concurrentes du domaine. Deux travailleurs peuvent lire le même état puis produire des effets incompatibles. Définissez un protocole de coordination adapté au stockage et testez le scénario concurrent. Le mot shared n’est pas un verrou ni une règle de déduplication métier.

Erreur fréquente à comprendre Un volume partagé sérialise automatiquement toute écriture métier.

La concurrence reste à gérer.

Prévoir les suppressions destructives

Certaines commandes de nettoyage peuvent supprimer des volumes et leurs données. La possibilité de recréer un conteneur depuis une image ne signifie pas que ce contenu métier est récupérable. Définissez les ressources éphémères et durables avant une opération, puis vérifiez ses cibles. Une procédure de reprise doit être connue et testée avant de considérer un nettoyage comme réversible.

Erreur fréquente à comprendre Supprimer un volume est toujours une opération sans effet sur les données.

Le stockage persistant peut être perdu.

Valider le résultat restauré

Une restauration techniquement terminée doit encore fournir le résultat utile : rôles, relations, fichiers et parcours applicatifs prévus. Mesurez le délai avec un volume représentatif et conservez les limites de l’exercice. Un succès sur trois fichiers ne justifie pas un objectif de reprise pour toutes les données. La preuve doit relier contenu retrouvé, environnement et contrôles métier observés.

Erreur fréquente à comprendre La présence de l’archive prouve tout RTO.

Le délai et les invariants doivent être testés.

Atelier guidé : lire, expliquer et vérifier le code

services:
  db:
    image: postgres:18
    volumes:
      - lab-data:/var/lib/postgresql
volumes:
  lab-data: {}

La syntaxe de l’exercice nomme lab-data comme volume et le monte à la destination indiquée dans le conteneur. Elle ne désigne pas un chemin absolu du poste comme le ferait un bind mount. Cette configuration de persistance ne crée pas non plus une sauvegarde distante automatique ni une preuve que la base restaurera correctement toutes ses données.

Dans un laboratoire, écrivez une donnée témoin, remplacez le conteneur selon une procédure qui conserve le volume puis vérifiez la lecture. Étudiez séparément une suppression explicite du stockage et une restauration depuis une copie adaptée. Cette séparation rend visibles trois capacités différentes : recréer le processus, conserver son état et récupérer cet état après un incident qui détruit le support courant.

Exemple commenté

docker volume create lab-data
docker run --rm --mount source=lab-data,target=/data alpine:3.22 sh -c 'printf "R1" > /data/reservation'
docker run --rm --mount source=lab-data,target=/data alpine:3.22 cat /data/reservation

Deux instances distinctes lisent ici le même volume persistant. L’exemple porte sur un fichier simple, pas sur une méthode universelle de sauvegarde d’une base active.

Exercice de mise en pratique

Recréez l’instance de l’application puis prouvez la persistance du fichier et la restauration depuis une copie séparée.

Voir une proposition de correction

Conservez un volume nommé et remplacez seulement l’instance. Pour une vraie base, appliquez sa procédure de dump ou snapshot cohérent et vérifiez une restauration de laboratoire.

Contrôle de connaissances

Un volume est-il automatiquement une sauvegarde indépendante ?

Réponse expliquée : Non, il assure une persistance selon son cycle de vie — La persistance ne fournit pas à elle seule une copie récupérable.

Cours associé : Volumes, montages et sauvegardes cohérentes ↗

Documentation de référence ↗ https://docs.docker.com/engine/storage/volumes/

Module 6 / 8 · 90 min

Compose, dépendances, santé et configuration

Distinguer ordre de lancement et disponibilité réelle.

Comprendre le mécanisme

Compose décrit plusieurs services, leurs réseaux, volumes et configuration. Une dépendance ordonne le démarrage mais le simple état running ne prouve pas qu’une base accepte déjà des requêtes. Un healthcheck et une condition de dépendance adaptée peuvent aider au démarrage. L’application doit néanmoins gérer les indisponibilités ultérieures : le succès initial ne garantit pas la disponibilité permanente d’une dépendance.

Raisonner et vérifier

Les variables d’environnement et les fichiers dotenv de Compose participent à l’interpolation et à la configuration selon leurs règles propres. Ne confondez pas leur traitement avec celui de Symfony. Pour un secret, choisissez un montage ou gestionnaire adapté et évitez l’exposition dans les images et logs. Vérifiez le rendu de configuration sans diffuser de valeurs sensibles.

Une déclaration décrit des intentions

Compose organise des services et ressources selon un fichier et un environnement donnés. Un YAML syntaxiquement valide ne prouve pas la disponibilité réelle d’une API ou de sa base. Les images, variables, volumes et réseaux doivent aussi être corrects. Lisez la configuration effective puis lancez le parcours utile ; la présence des bons noms de sections n’est pas une observation du comportement déployé.

Erreur fréquente à comprendre Un YAML valide prouve toute disponibilité métier.

La syntaxe ne démontre pas l’exécution réelle.

Démarrer n’est pas être prêt

Une dépendance peut être en exécution alors que son initialisation n’est pas terminée. Un ordre de démarrage simple ne garantit donc pas que la base accepte déjà la première requête métier. Définissez le critère de disponibilité et les conditions que l’application peut attendre. Un délai fixe choisi au hasard peut masquer le problème sur une machine rapide sans le résoudre sur une autre.

Erreur fréquente à comprendre depends_on sans analyse garantit toute base prête à requêter.

Le processus peut être démarré mais pas opérationnel.

Observer une santé pertinente

Un health check doit correspondre à une propriété clairement définie. Vérifier seulement qu’un processus existe ne démontre pas l’accès aux données nécessaires au parcours. À l’inverse, un contrôle trop lourd ou mutateur peut perturber le service. Choisissez une observation bornée et interprétable, avec un diagnostic minimisé. Le succès doit rester limité aux dépendances et conditions réellement exercées.

Erreur fréquente à comprendre Tout processus existant garantit une route fonctionnelle.

Le contrôle doit correspondre au contrat du service.

Comprendre la condition de démarrage

Une condition comme service_healthy peut organiser le démarrage d’un service consommateur selon la santé déclarée de sa dépendance. Cette coordination ne garantit pas sa disponibilité éternelle. Vérifiez la définition du health check et le comportement du mode de déploiement ciblé. Une configuration porte des règles ; les tests doivent montrer ce qu’elles font lors d’un démarrage lent et d’un refus persistant.

Erreur fréquente à comprendre healthy constitue une preuve universelle de toute dépendance future.

La santé est une observation limitée dans le temps.

Les pannes peuvent arriver après le démarrage

Une dépendance initialement saine peut tomber en panne pendant le service. L’application doit donc conserver des délais, erreurs et reprises adaptées indépendamment de l’ordre initial. Tester uniquement docker compose up ne couvre pas cette phase. Simulez une indisponibilité après un parcours réussi et vérifiez le refus borné, la récupération et l’absence de répétition incontrôlée d’un effet métier sensible.

Erreur fréquente à comprendre Un démarrage ordonné empêche toute panne ultérieure.

Les dépendances peuvent tomber en panne ensuite.

Deux usages différents des fichiers dotenv

L’interpolation de variables par Compose et la lecture de configuration par Symfony ne sont pas nécessairement le même mécanisme ni le même moment. Une valeur disponible pour construire le YAML ne se retrouve pas automatiquement dans tout processus. Définissez la chaîne d’injection attendue et contrôlez les variables effectives sans publier les secrets. Un nom de fichier identique ne rend pas deux contrats de configuration interchangeables.

Erreur fréquente à comprendre Une valeur absente produit toujours la bonne configuration.

Les valeurs par défaut et erreurs doivent être maîtrisées.

Un nom de service n’exige pas un port public

Sur le réseau prévu, les services peuvent utiliser leur résolution interne pour communiquer. La dépendance db n’a pas toujours besoin d’une publication vers Internet. Cette possibilité de connexion ne remplace ni authentification ni disponibilité SQL. Testez depuis le consommateur réel afin de distinguer erreur de nom, refus réseau et erreur de credentials sans élargir inutilement la surface exposée.

Erreur fréquente à comprendre Tout port hôte est obligatoire pour une communication interne.

Les réseaux de services peuvent suffire.

La politique de redémarrage a des limites

Relancer un processus peut aider après certains échecs, mais ne répare pas une donnée invalide ou une mauvaise configuration permanente. Une boucle de redémarrages peut consommer des ressources et masquer la cause. Définissez les conditions et l’observation de reprise. Un test doit inclure un défaut persistant et montrer que l’exploitation peut le diagnostiquer, au lieu d’interpréter toute nouvelle tentative comme un progrès.

Erreur fréquente à comprendre Une politique restart corrige tout défaut de données.

Elle relance un processus sans réparer nécessairement la cause.

Vérifier les ressources dans le runtime choisi

Les options de limite doivent être effectivement prises en compte par le moteur et le mode de déploiement utilisés. Leur présence dans un exemple ne prouve pas la même application partout. Mesurez consommation, refus et comportement sous pression dans l’environnement cible. Un budget mémoire borne certaines conséquences mais ne corrige pas la fuite qui les provoque ; il peut conduire à un arrêt qu’il faut aussi gérer.

Erreur fréquente à comprendre Tout champ YAML est appliqué identiquement par tout runtime.

Le moteur et le mode de déploiement comptent.

Construire des scénarios dégradés

Un démarrage nominal ne couvre pas dépendance silencieuse, réponse lente et erreur durable. Utilisez des services simulés ou un laboratoire pour provoquer ces états sans toucher les données réelles. Pour chaque scénario, écrivez durée maximale et effet interdit. Cette matrice permet de vérifier la résilience comme un contrat observable, plutôt que l’attribuer au seul fait d’utiliser un orchestrateur ou une politique de restart.

Erreur fréquente à comprendre Un seul démarrage nominal prouve toute résilience.

Les scénarios dégradés vérifient d’autres propriétés.

Atelier guidé : lire, expliquer et vérifier le code

services:
  api:
    image: example/lab-api:1
    depends_on:
      - db
  db:
    image: postgres:18

L’extrait déclare une dépendance de démarrage entre api et db. Il ne présente ni condition de santé ni preuve que PostgreSQL accepte une requête lorsque l’application effectue son premier appel. Il faut donc distinguer la relation déclarée, bien présente, de la disponibilité métier qui reste à définir et observer.

Dans un laboratoire, ralentissez l’initialisation de la base et relevez le comportement de l’API. Ajoutez une coordination adaptée si elle répond au besoin, puis provoquez une panne après un démarrage réussi. L’application doit encore respecter ses budgets et sa politique de reprise. Le test montre ainsi ce que l’organisation initiale apporte, et quelles responsabilités restent dans le consommateur pendant la durée du service.

Exemple commenté

services:
  app:
    image: lab-app:release
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:18
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/lab_password
    secrets: [lab_password]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      retries: 10
secrets:
  lab_password:
    file: ./lab-password.txt

Le fragment attend une santé définie de db au démarrage de app. Le fichier de secret de laboratoire est fourni séparément et ne doit pas être committé. Complétez avec le volume et les paramètres propres à votre projet.

Exercice de mise en pratique

Simulez une base qui devient indisponible après le démarrage correct de l’application.

Voir une proposition de correction

Vérifiez la stratégie de reconnexion, délais et erreurs applicatives. Le healthcheck ne remplace pas cette gestion. Documentez le comportement observable lors d’une reprise.

Contrôle de connaissances

Un conteneur running garantit-il que sa base accepte déjà les requêtes ?

Réponse expliquée : Non, il faut une vérification de disponibilité adaptée — Le processus peut être encore en initialisation.

Cours associé : Compose, dépendances, santé et configuration ↗

Documentation de référence ↗ https://docs.docker.com/compose/how-tos/startup-order/

Module 7 / 8 · 90 min

Privilèges, secrets et limites du runtime

Réduire les possibilités après une compromission du processus.

Comprendre le mécanisme

L’isolation repose notamment sur namespaces, cgroups et politiques de sécurité. Un utilisateur non root, des capacités minimales et des montages limités réduisent le périmètre accessible. L’accès au socket Docker peut permettre un contrôle très étendu de l’hôte selon la configuration ; ne le donnez pas à une application ordinaire par commodité. Le mode privilégié doit être justifié par un besoin précis, pas utilisé comme remède général aux erreurs de permission.

Raisonner et vérifier

Une racine en lecture seule exige de prévoir explicitement les répertoires temporaires ou données nécessaires. Les limites mémoire et CPU bornent certaines consommations, sans corriger une fuite mémoire ou un algorithme incorrect. Un conteneur n’est pas une preuve d’isolation absolue : maintenez aussi noyau, runtime et dépendances. Testez les droits nécessaires et les refus attendus sous le véritable utilisateur runtime.

Réduire les privilèges du processus

Exécuter le service avec un utilisateur non root peut limiter certaines opérations si le reste de la configuration respecte cette intention. Cela n’empêche pas toutes les vulnérabilités applicatives : le processus peut encore accéder aux données légitimement disponibles pour son rôle. Définissez les capacités nécessaires puis testez une opération refusée et un parcours nominal. Le durcissement doit réduire l’impact sans être confondu avec une preuve générale d’absence de bug.

Erreur fréquente à comprendre Non root rend impossible toute vulnérabilité applicative.

Le contrôle ne remplace pas les autres défenses.

Ne garder que les capacités utiles

Les capabilities et autres options de privilège doivent correspondre à un besoin réel du service. En ajouter toutes élargit les pouvoirs disponibles, même si une fonction nominale semble continuer à marcher. Inventoriez les opérations système attendues et retirez les capacités superflues selon une procédure vérifiée. Une configuration minimale doit être testée, pas simplement copiée d’un autre produit dont les dépendances diffèrent.

Erreur fréquente à comprendre Ajouter toutes les capabilities améliore l’isolation.

L’élargissement augmente les pouvoirs disponibles.

Définir les écritures nécessaires

Une racine de conteneur en lecture seule peut limiter des modifications inattendues, mais le programme a parfois besoin d’espaces temporaires ou de données explicitement montées. Identifiez-les et contrôlez leur durée et taille. Cette restriction ne chiffre pas les fichiers et ne filtre pas toutes les sorties réseau. Les tests doivent distinguer écriture interdite, écriture utile et chemin de reprise après une erreur de stockage.

Erreur fréquente à comprendre Read-only interdit toutes les sorties réseau.

Les surfaces de fichier et réseau sont distinctes.

Le socket donne une capacité, pas un fichier anodin

Monter le socket Docker peut exposer des opérations puissantes sur le démon et l’environnement hôte selon les droits et la configuration. Ce n’est pas une lecture ordinaire comparable à une image publique. Évitez ce montage pour une application qui n’a pas besoin de ce contrôle. Une revue doit considérer l’impact d’une RCE dans le service qui pourrait alors utiliser l’interface exposée.

Erreur fréquente à comprendre Monter le socket est une lecture ordinaire sans risque de contrôle.

L’API peut permettre des opérations puissantes sur l’hôte.

Distribuer les secrets selon leur usage

Un processus qui consomme un secret doit pouvoir l’obtenir d’une manière utile ; son injection ne le rend donc pas inaccessible à tout code exécuté dans ce périmètre. Limitez les détenteurs, les logs et la conservation. Séparez environnements et finalités pour réduire l’impact d’un incident. Une valeur publique de démonstration ne doit pas devenir le credential réel parce que le format d’injection paraît sécurisé.

Erreur fréquente à comprendre Tout secret injecté devient impossible à extraire par le processus.

Le consommateur dispose nécessairement d’une capacité de lecture utile.

Borner sans prétendre réparer

Des limites de CPU et de mémoire participent au partage de ressources et peuvent borner certaines conséquences d’un abus ou d’une fuite. Elles ne corrigent pas automatiquement la cause. Une limite mémoire peut conduire à un arrêt, qui demande une stratégie de diagnostic et de reprise. Mesurez aussi files, volume de travail et délais ; déplacer l’attente vers une autre ressource ne fournit pas une capacité infinie.

Erreur fréquente à comprendre Un conteneur possède une capacité infinie par isolation.

Les ressources physiques restent finies.

Comprendre le mode privilégié

Le mode privilégié élargit des possibilités au lieu de représenter une restriction maximale. Son utilisation doit donc être liée à un besoin explicite et à une analyse du périmètre. Un exemple qui fonctionne uniquement avec ce mode peut cacher un défaut de permissions ou une dépendance excessive. Cherchez la capacité minimale nécessaire et testez-la séparément, plutôt que rendre tout l’environnement accessible par facilité.

Erreur fréquente à comprendre Privileged constitue la restriction maximale du runtime.

Ce mode donne davantage d’accès.

Maintenir le contenu exécuté

Une image identifiée par digest peut rester vulnérable ou devenir concernée par une information de sécurité nouvelle. La traçabilité facilite le repérage des instances affectées ; elle ne retire pas le besoin de maintenance. Définissez construction, analyse et mise à jour avec des vérifications de comportement. Le nom d’une base réputée ou le résultat ancien d’un scan ne garantit pas tout état futur.

Erreur fréquente à comprendre Un digest fixé ne nécessite jamais une revue de vulnérabilités.

L’immuabilité n’efface pas les défauts découverts.

Garder l’autorisation dans le domaine

Un runtime durci limite des capacités système, pas les droits d’un utilisateur sur une facture. Une requête paramétrée et un compte non root peuvent encore renvoyer les données du mauvais tenant si le filtre métier est absent. Testez cette frontière directement avec deux acteurs. La défense doit combiner des propriétés complémentaires, sans attribuer à un mécanisme d’isolation la connaissance de toutes les règles du produit.

Erreur fréquente à comprendre Un runtime durci autorise tout accès aux données.

Le confinement ne définit pas la politique d’objet.

Observer la restriction effective

Le fichier de déploiement peut être surchargé ou interprété dans un contexte différent de celui du poste. Vérifiez l’utilisateur, les montages, capacités et limites de l’instance réellement exécutée. Une intention dans un commentaire ne prouve rien de ces décisions. La preuve doit conserver la version et les observations utiles sans exposer les secrets, afin qu’un autre opérateur puisse comprendre ce qui a été testé.

Erreur fréquente à comprendre Un commentaire non-root suffit à prouver l’utilisateur actif.

Le runtime peut être configuré autrement.

Atelier guidé : lire, expliquer et vérifier le code

services:
  api:
    image: example/lab-api:1
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Le volume de l’atelier ne monte pas seulement des données métier : il expose le socket de l’environnement Docker. Un processus compromis pourrait disposer de capacités de contrôle importantes par cette interface selon sa configuration. Aucun port 443 ni mécanisme de chiffrement du volume n’est défini dans cet extrait ; ces réponses décriraient d’autres propriétés.

Réalisez la revue sur une configuration de laboratoire et demandez si le service a réellement besoin d’opérer le démon. Retirez le montage lorsqu’il ne correspond pas à sa responsabilité, puis vérifiez le parcours nominal. Complétez avec utilisateur, capacités et ressources minimales. Le but est de limiter l’impact d’un code hostile tout en conservant les contrôles métier qui empêchent un utilisateur ordinaire d’accéder aux données d’un autre.

Après une RCE : réduire les capacités du processus

Une défense en profondeur suppose que la prévention puisse échouer. Un processus compromis dispose au minimum des droits de l’application ; l’objectif est de limiter les capacités supplémentaires accessibles depuis ce point.

Exécutez sans root, retirez les capacités inutiles, évitez mode privilégié et socket Docker, et rendez le système de fichiers en lecture seule lorsque possible. Fournissez seulement les répertoires temporaires nécessaires avec budgets de taille et durée. Limitez aussi sorties réseau et accès aux secrets selon les besoins réels du service.

Ces mesures ne rendent pas le conteneur invulnérable et ne retirent pas les données que l’application doit légitimement lire. Vérifiez le fonctionnement nominal sous ces restrictions puis simulez des opérations de laboratoire qui doivent échouer, comme une écriture hors répertoire admis. Une configuration déclarative doit être confrontée aux permissions et montages réellement présents sur le runtime déployé.

Points de vigilance : La réduction des droits et des accès hôte diminue les possibilités après RCE ; ce n’est pas une isolation absolue. Une image petite ne neutralise pas les privilèges du processus. L’accès au socket peut permettre de contrôler le démon et compromettre l’hôte selon sa configuration. Le mode privilégié et les montages sensibles compromettent le confinement attendu.

Documentation de référence ↗

Exemple commenté

docker run --rm --read-only --tmpfs /tmp \
  --cap-drop ALL --user 10001:10001 \
  alpine:3.22 sh -c 'id; printf "lab" > /tmp/check'

Le processus utilise un identifiant limité, une racine en lecture seule et un espace temporaire explicite. L’application réelle doit être testée avec ses besoins spécifiques.

Exercice de mise en pratique

Inventoriez les chemins d’écriture et capacités dont votre service a réellement besoin.

Voir une proposition de correction

Lancez-le avec des privilèges réduits, observez les refus puis autorisez seulement les besoins démontrés. Vérifiez qu’un accès au socket Docker n’est pas présent.

Contrôle de connaissances

Pourquoi éviter de monter le socket Docker dans une application ordinaire ?

Réponse expliquée : Il peut donner un contrôle étendu sur le démon et l’hôte — L’accès au démon est une frontière de privilèges majeure.

Cours associé : Privilèges, secrets et limites du runtime ↗

Documentation de référence ↗ https://docs.docker.com/engine/security/

Module 8 / 8 · 90 min

Logs, arrêt propre et retour de version

Relier l’état observable à une procédure d’exploitation testée.

Comprendre le mécanisme

Une application conteneurisée doit exposer des journaux utiles et un comportement d’arrêt défini. La commande principale et la forme de lancement influencent la propagation des signaux. À l’arrêt, terminez ou annulez proprement le travail en cours dans un délai borné. Un redémarrage automatique peut aider à la disponibilité, sans résoudre une erreur de configuration ou une corruption répétée.

Raisonner et vérifier

La vérification de santé doit tester un contrat significatif sans divulguer de secret. Corrélez image exécutée, révision et événements métier minimisés. Pour revenir à une version précédente, utilisez un artefact identifié et vérifiez sa compatibilité avec les données et migrations. Une procédure n’est fiable qu’après exercice dans un environnement contrôlé ; documentez aussi le délai de retour et les limites.

Une identité de release retrouvable

Une release doit relier source, tests et contenu exécuté. Un tag mutable seul ne permet pas de retrouver exactement ce qui a été servi à une date donnée. Conservez les références pertinentes et vérifiez l’identité active après bascule. Cette preuve aide à distinguer un défaut du nouveau code d’un processus resté sur l’ancien artefact ou d’une configuration différente.

Erreur fréquente à comprendre latest seul prouve exactement tout contenu historique.

Le tag peut changer de cible.

Les logs sont un stockage à contrôler

Collecter stdout ne rend pas chaque donnée appropriée à une conservation ou un partage. Les traces peuvent contenir tokens, corps personnels et chemins sensibles. Définissez champs, accès et durée selon le besoin d’exploitation. Un incident doit être corrélable par des éléments minimisés. Les diagnostics d’échec demandent une attention particulière car ils traversent parfois des chemins moins contrôlés que les réponses nominales.

Erreur fréquente à comprendre stdout rend toute donnée automatiquement publique sans risque.

Les canaux de collecte demandent un contrôle d’accès.

Arrêt gracieux et travail en cours

Un arrêt propre possède un délai et un contrat sur les tâches commencées. Transmettre un signal ne garantit pas l’annulation d’une mutation distante déjà validée. Le service doit savoir ce qu’il termine, reporte ou réconcilie. Testez l’arrêt pendant une opération de laboratoire et observez effets, files et redémarrage. Un processus arrêté rapidement n’est pas forcément un état métier correctement repris.

Erreur fréquente à comprendre Tuer le processus annule forcément tout effet distant.

Des opérations peuvent avoir été validées ailleurs.

Le retour d’image ne rembobine pas les volumes

Revenir à une ancienne image modifie le code exécuté, pas automatiquement les écritures persistantes. Les volumes et bases peuvent conserver un format nouveau ou un effet déjà appliqué. Une procédure de rollback doit donc analyser la compatibilité avec l’état courant et les mécanismes de reprise. L’existence d’un ancien artefact ne démontre pas que sa réexécution est sûre sur toutes les données récentes.

Erreur fréquente à comprendre Revenir à l’image précédente annule toute écriture persistante.

Code et données ont des cycles distincts.

Prouver la sauvegarde par une restauration

Une archive doit être restaurée dans un environnement distinct avec les outils et préconditions nécessaires. Vérifiez un parcours fonctionnel et les invariants utiles après récupération. Mesurez le délai sur un volume représentatif et conservez les limites. Un redémarrage automatique ou une réplication active ne protège pas nécessairement contre une suppression logique qui a déjà été propagée.

Erreur fréquente à comprendre Une archive présente suffit à garantir tout retour arrière.

La restauration doit être observée.

Tester le bon endpoint de santé

Un résultat 200 sur une page statique ne prouve pas que l’application, sa base et la release attendue fonctionnent ensemble. Le contrôle doit porter sur une garantie précise et bornée. Conservez l’identité de version avec la réponse utile, sans publier de secrets. Le succès décrit ce parcours observé ; il ne remplace pas une suite d’autorisation ni une restauration de secours.

Erreur fréquente à comprendre Tout 200 statique prouve toutes les dépendances métier.

Le contenu du contrôle détermine sa portée.

Renouveler les processus avec le contenu

Modifier un tag dans un registre ne transforme pas automatiquement les conteneurs déjà actifs. La procédure doit récupérer la bonne référence et remplacer ou renouveler les instances selon le modèle choisi. Vérifiez ensuite le contenu réellement servi. Une simple copie de fichiers ou modification de configuration ne prouve pas que chaque processus a chargé l’état prévu.

Erreur fréquente à comprendre Changer le tag modifie automatiquement tout conteneur déjà actif.

Une instance existante garde son contenu tant qu’elle n’est pas remplacée.

Coordonner la migration de données

Une migration peut rendre une ancienne version incompatible avec le schéma courant. Définissez les phases compatibles et les critères qui autorisent le retrait de l’ancien contrat. Avant rollback, examinez cette situation avec les nouvelles écritures déjà effectuées. Un exercice doit simuler la panne à un point intermédiaire, car une démonstration sur une base vide ne couvre pas les données de production.

Erreur fréquente à comprendre Toute migration est automatiquement compatible avec toutes les anciennes images.

Les formats de données doivent être coordonnés.

Surveiller la capacité et les boucles de reprise

Un état running n’assure pas une capacité suffisante ni une configuration correcte. Le processus peut être saturé ou répéter le même échec après chaque redémarrage. Reliez ressources, files, délais et résultats métier dans le diagnostic. La reprise automatique doit être bornée et observable ; elle ne constitue pas une correction d’un défaut permanent de configuration ou de donnée.

Erreur fréquente à comprendre Un statut running garantit une capacité suffisante.

Le processus peut être saturé tout en restant vivant.

Conserver un dossier d’incident utile

Les preuves d’exercice doivent préciser actif, version, chronologie, observations et limites sans publier les credentials réels. Chaque action doit avoir une raison et un résultat vérifiable. Notez les risques résiduels et les étapes qui n’ont pas été testées. Ce dossier permet d’améliorer la procédure après l’incident, au lieu de conclure que tout est restaurable parce qu’une seule commande a terminé sans erreur.

Erreur fréquente à comprendre Une reprise exige de publier les credentials de production.

Les résultats et procédures peuvent rester sans secrets.

Atelier guidé : lire, expliquer et vérifier le code

# Plan proposé :
# 1. Déployer lab-api:2 et migrer la base.
# 2. En cas d’erreur, relancer lab-api:1.
# Aucune procédure de données n’est définie.

Le plan de l’atelier revient au code précédent après une migration annoncée comme incompatible. Cette seule action ne restaure ni schéma ni données. L’ancien binaire peut donc démarrer puis échouer ou mal interpréter l’état courant. Le défaut n’est pas le nom du tag ou celui du conteneur, mais l’absence d’une stratégie de compatibilité et de reprise de la couche persistante.

Préparez un jeu de données de laboratoire puis exercez les deux versions autour d’une migration contrôlée. Notez le point où le retour direct cesse d’être valable et quelles opérations supplémentaires sont nécessaires. Une stratégie progressive peut limiter cette fenêtre, mais elle doit être démontrée. Le contrôle de santé final doit confirmer une réponse applicative attendue liée à la version réellement active.

Exemple commenté

docker inspect lab-app
docker logs --tail 100 lab-app
docker stop --time 20 lab-app
# Utiliser uniquement les ressources de laboratoire nommées.

Ces opérations observent puis demandent un arrêt de l’instance. Elles ne restaurent pas une base ni ne prouvent qu’un ancien binaire est compatible avec son schéma.

Exercice de mise en pratique

Écrivez et exercez une procédure de retour de release comprenant code, données, santé et preuve de version.

Voir une proposition de correction

Déployez un digest précédent identifié, vérifiez son contrat de schéma, attendez la santé puis contrôlez une réponse applicative. Si les données ne sont pas compatibles, appliquez la stratégie de migration ou restauration prévue.

Contrôle de connaissances

Un redémarrage automatique corrige-t-il nécessairement une mauvaise configuration ?

Réponse expliquée : Non, il peut répéter le même échec — La cause peut persister après chaque démarrage.

Cours associé : Logs, arrêt propre et retour de version ↗

Documentation de référence ↗ https://docs.docker.com/engine/containers/run/

Projet de synthèse — Application de réservation conteneurisée

Emballez une petite application et sa base de laboratoire avec Compose. Séparez données, configuration et image ; simulez une panne applicative puis une restauration des données.

Voir une proposition de correction

Définissez un build multi-stage, une image runtime réduite et un utilisateur approprié. Utilisez un réseau interne, un volume de données et un secret monté selon le besoin. Ajoutez la santé de la base et une stratégie de reconnexion applicative. Testez recréation, restauration et retour de version en conservant la compatibilité du schéma.

Examen d’entraînement indépendant. Le nombre de questions, la durée et le seuil sont des choix pédagogiques DIGITAL AVENIR, sans équivalence avec un barème officiel. Les réponses sont présentes dans la page pour l’autoformation ; aucun titre de certification n’est délivré.

Accéder à l’examen blanc