Retour au catalogue
Season 29 18 Épisodes 1h 2m 2026

Docker Masterclass

Édition 2026. Un cours audio complet sur Docker, couvrant les bases des conteneurs, les images, Dockerfile, le réseau, Compose, la CI/CD, et les dernières fonctionnalités d'IA telles que MCP Toolkit, Docker Sandboxes et Docker Agent.

Conteneurisation DevOps
Docker Masterclass
Lecture en cours
Click play to start
0:00
0:00
1
La promesse Dev égale Prod
Découvrez pourquoi Docker a fondamentalement changé le développement logiciel. Cet épisode couvre la proposition de valeur principale consistant à séparer les applications de l'infrastructure et à atteindre une parité parfaite entre les environnements de développement et de production.
2m 59s
2
Conteneurs vs Machines Virtuelles
Comprenez les différences architecturales entre les conteneurs et les machines virtuelles. Découvrez comment les conteneurs parviennent à s'isoler en partageant le noyau hôte, ce qui les rend incroyablement légers par rapport aux hyperviseurs traditionnels.
3m 25s
3
L'anatomie d'une image Docker
Explorez ce qu'est réellement une image Docker. Cet épisode explique les principes d'immuabilité des images et de composition des couches, en montrant comment les modifications du système de fichiers sont empilées pour créer un modèle de conteneur.
3m 28s
4
Le plan de construction Dockerfile
Apprenez à écrire un Dockerfile pour construire des images personnalisées. Nous couvrons les instructions essentielles comme FROM, RUN et CMD, et expliquons la différence cruciale entre les formes shell et exec.
3m 23s
5
Maîtriser le cache de build
Optimisez la construction de vos images en utilisant le cache de build de Docker. Découvrez pourquoi l'ordre des instructions dans votre Dockerfile est essentiel pour éviter les installations de dépendances inutiles.
3m 23s
6
Les Multi-Stage Builds
Gardez vos images de production légères et sécurisées. Cet épisode présente les Multi-Stage Builds, en démontrant comment séparer votre environnement de compilation lourd de votre environnement d'exécution minimal.
3m 58s
7
Exécution et interaction
Apprenez la mécanique pratique de l'exécution des conteneurs. Nous couvrons les modes détaché et interactif, la publication de ports de base, et comment exécuter des commandes shell à l'intérieur d'un conteneur en cours d'exécution.
3m 41s
8
Les bases de la persistance des données
Évitez les pertes de données catastrophiques lors de la suppression de conteneurs. Cet épisode compare les Bind Mounts pour le rechargement à chaud en développement local avec les Docker Volumes pour la persistance sécurisée des bases de données.
3m 22s
9
Le réseau des conteneurs
Comprenez comment Docker gère le trafic réseau. Apprenez les bases de la publication de ports vers l'hôte et comment les conteneurs communiquent entre eux en toute sécurité sur des réseaux bridge isolés.
3m 21s
10
Introduction à Docker Compose
Allez au-delà des commandes pour un seul conteneur. Découvrez comment Docker Compose utilise un fichier YAML déclaratif pour définir, mettre en réseau et orchestrer plusieurs services simultanément.
3m 49s
11
Docker dans le pipeline CI/CD
Éliminez les tests instables avec des environnements de build conteneurisés. Cet épisode explique comment utiliser Docker dans les pipelines d'intégration continue (CI/CD) pour garantir des tests automatisés parfaitement reproductibles.
3m 08s
12
Images multi-plateformes
Résolvez l'incompatibilité entre Apple Silicon et les serveurs cloud. Découvrez comment Docker Buildx vous permet de faire de la compilation croisée et de packager des applications pour les architectures ARM et AMD64 simultanément.
3m 32s
13
Le Docker MCP Toolkit
Connectez vos agents d'IA à des outils locaux en toute sécurité. Cet épisode présente le Docker Model Context Protocol (MCP) Toolkit, en expliquant comment gérer des serveurs MCP conteneurisés à l'aide de catalogues et de profils.
3m 12s
14
L'auto-découverte Dynamic MCP
Explorez Dynamic MCP, une fonctionnalité expérimentale qui permet aux clients IA de rechercher dans le Docker MCP Catalog et d'installer dynamiquement de nouveaux serveurs d'outils pendant une conversation sans configuration manuelle.
4m 01s
15
Docker Sandboxes pour l'IA
Comprenez l'architecture des Docker Sandboxes. Découvrez pourquoi les agents de codage IA autonomes nécessitent des microVMs isolées avec des démons Docker dédiés au lieu des namespaces de conteneurs standards.
3m 15s
16
Construire des équipes d'agents IA
Arrêtez de vous fier à un seul modèle d'IA pour les tâches complexes. Cet épisode présente le framework Docker Agent, en montrant comment composer des équipes spécialisées d'agents définies en YAML.
3m 28s
17
Toolsets et workflows d'agents
Rendez vos agents IA réellement utiles en leur donnant les bonnes contraintes. Apprenez à configurer des toolsets de système de fichiers et à imposer des workflows de développement structurés dans Docker Agent.
3m 45s
18
Les modèles d'IA dans Compose
Traitez vos LLMs locaux comme n'importe quelle autre dépendance d'application. Apprenez à déclarer, configurer et lier des modèles d'IA directement dans votre fichier YAML Docker Compose.
3m 13s

Épisodes

1

La promesse Dev égale Prod

2m 59s

Découvrez pourquoi Docker a fondamentalement changé le développement logiciel. Cet épisode couvre la proposition de valeur principale consistant à séparer les applications de l'infrastructure et à atteindre une parité parfaite entre les environnements de développement et de production.

Télécharger
Salut, ici Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 1 sur 18. Tu viens de passer trois jours à traquer une erreur qui ne se déclenche que sur le serveur de staging. Le code s'exécute parfaitement sur ton laptop, mais dès qu'il atteint le pipeline de déploiement, il plante. Le coupable est presque toujours une librairie système incompatible, une version de runtime différente, ou une variable d'environnement manquante. C'est exactement cette friction que Docker a été conçu pour éliminer en tenant la promesse du dev equals prod. Docker est une plateforme ouverte pour développer, déployer et faire tourner des applications. Son but principal est de séparer tes applications de ton infrastructure. Historiquement, les développeurs écrivaient le code et les équipes ops provisionnaient les serveurs. Les développeurs passaient l'application, et l'équipe ops passait des heures ou des jours à configurer la machine hôte pour répondre aux prérequis du logiciel. Cet alignement manuel des environnements est fragile et lent. Docker résout ça en packageant l'application avec ses dépendances, ses outils système, ses librairies et son runtime dans une unité standardisée appelée container. Tu associes peut-être ce concept aux machines virtuelles traditionnelles. Bien qu'ils partagent le but d'isoler les applications, les containers sont beaucoup plus légers car ils ne nécessitent pas un système d'exploitation invité complet. On abordera cette différence d'architecture dans le prochain épisode. Pour l'instant, on va se concentrer sur ce que ce packaging permet d'accomplir. Voici l'idée clé. Parce que le container contient à la fois le code et l'environnement précis nécessaire pour l'exécuter, la machine hôte sous-jacente n'a plus vraiment d'importance. Docker garantit que si un container tourne sur ton laptop de dev local, il tournera exactement de la même manière sur un serveur de QA, et exactement de la même manière dans un datacenter de production. Tu élimines l'expression ça marche sur ma machine, parce que ta machine et la machine de production fournissent maintenant exactement le même environnement d'exécution. Le workflow ressemble à ça. Un développeur écrit du code en local et définit l'environnement requis dans un fichier de configuration en texte brut. Docker lit ce fichier et build un artefact statique appelé une image. C'est cette image unique et immuable qui est testée. Quand les tests passent, c'est exactement cette même image qui est déployée en production. Tu ne copies pas de code sur un serveur pour lancer un script de setup. Tu déplaces l'environnement de travail complet comme une seule unité scellée. Cette portabilité change la façon dont les systèmes scalent. Parce que les containers sont standardisés et légers, lancer de nouvelles instances d'une application en réponse à un pic de trafic se fait en quelques secondes. Tu peux facilement déplacer des workloads entre différents environnements, en passant une application d'un serveur de test local à un cloud provider sans changer une seule ligne de code ni reconfigurer l'hôte. Ce qu'il faut retenir, c'est que Docker transforme l'infrastructure en une ressource prévisible, créant une frontière stricte où les développeurs gèrent l'environnement complet à l'intérieur du container, et où les ops fournissent simplement la puissance de calcul pour le faire tourner. Si tu veux soutenir l'émission, cherche DevStoriesEU sur Patreon. C'est tout pour cet épisode. Merci pour ton écoute, et continue à développer !
2

Conteneurs vs Machines Virtuelles

3m 25s

Comprenez les différences architecturales entre les conteneurs et les machines virtuelles. Découvrez comment les conteneurs parviennent à s'isoler en partageant le noyau hôte, ce qui les rend incroyablement légers par rapport aux hyperviseurs traditionnels.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Docker Masterclass, épisode 2 sur 18. Tu n'as pas besoin de booter un système d'exploitation entier juste pour faire tourner un simple script Python. Pourtant, pendant des années, les développeurs ont accepté un gros overhead et des temps de boot super longs pour garder leurs applications isolées les unes des autres. Aujourd'hui, on règle ça en comparant les containers et les machines virtuelles. Imagine faire tourner une stack complexe en local. Tu as besoin d'un frontend React, d'une API Python et d'une base de données PostgreSQL qui tournent tous en même temps. Si tu les installes directement sur ta machine hôte, tu t'exposes à des conflits de dépendances. L'API peut avoir besoin d'une version spécifique d'une librairie système qui entre en conflit avec ce dont ta base de données a besoin. Un container résout ce problème en agissant comme un process sandboxé. Voici le truc à retenir. Un container n'est pas un mini-ordinateur. C'est strictement un process qui tourne nativement sur ta machine hôte. Toute la magie réside dans l'isolation. Grâce aux fonctionnalités intégrées au système d'exploitation, ce process reçoit son propre filesystem privé, sa propre stack réseau, et une vue isolée du système. Pour l'API Python qui tourne à l'intérieur, elle a l'impression d'être le seul logiciel sur la machine. Pour ton système d'exploitation hôte, c'est juste un autre process standard, un peu comme ton navigateur web ou ton éditeur de texte. Vu qu'un container est juste un process, il partage le kernel du système d'exploitation hôte. Quand la base de données PostgreSQL à l'intérieur d'un container a besoin d'allouer de la mémoire ou d'écrire un enregistrement sur le disque, elle parle directement au kernel hôte. Il n'y a pas d'intermédiaire, ni de système d'exploitation secondaire qui boote en arrière-plan. C'est pour ça que démarrer un container est presque instantané. Ça prend exactement le même temps que de démarrer l'application brute elle-même. Maintenant, compare ça directement avec une machine virtuelle. Une machine virtuelle gère l'isolation en simulant du hardware. Elle s'appuie sur un hyperviseur, un logiciel qui découpe un CPU virtuel, de la mémoire virtuelle et un disque dur virtuel. Par-dessus ce faux hardware, tu dois installer un système d'exploitation invité complet. Si tu veux faire tourner cette même API Python dans une VM isolée, tu dois booter une distribution Linux entière. La VM charge son propre kernel séparé, initialise les drivers de périphériques et lance les services système en arrière-plan avant même de penser à exécuter ton code Python. À chaque fois que l'application a besoin de lire un fichier, la requête passe par le système d'exploitation invité, descend vers l'hyperviseur, et arrive enfin au hardware hôte. Ça offre une isolation de sécurité incroyablement forte, mais ça a un coût énorme en cycles CPU, en utilisation de la mémoire et en temps de boot. À cause de ces différences, on pense souvent à tort que tu dois choisir l'un ou l'autre. En réalité, les containers et les machines virtuelles ne sont pas mutuellement exclusifs. Dans les environnements cloud modernes, ils sont presque toujours utilisés ensemble. Quand tu provisionnes une instance cloud, tu loues une machine virtuelle. Cette machine virtuelle fournit une frontière forte au niveau du hardware, qui sépare ton workload des autres clients sur le même serveur physique. Ensuite, tu installes un runtime de containers à l'intérieur de cette machine virtuelle pour faire tourner ton frontend React, ton API et ta base de données. La machine virtuelle isole l'infrastructure, pendant que les containers isolent les applications individuelles. Au final, la distinction se résume à une histoire de frontières. Les machines virtuelles virtualisent le hardware pour faire tourner plusieurs systèmes d'exploitation, alors que les containers virtualisent le système d'exploitation pour faire tourner plusieurs process isolés. Merci d'avoir passé quelques minutes avec moi. À la prochaine, et prends soin de toi.
3

L'anatomie d'une image Docker

3m 28s

Explorez ce qu'est réellement une image Docker. Cet épisode explique les principes d'immuabilité des images et de composition des couches, en montrant comment les modifications du système de fichiers sont empilées pour créer un modèle de conteneur.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 3 sur 18. Tu déploies une application et elle fonctionne parfaitement. Deux semaines plus tard, tu redémarres exactement la même application sur la même machine et elle plante parce qu'une library système s'est mise à jour en arrière-plan. Ce drift d'environnement silencieux est exactement ce que nous éliminons en comprenant l'anatomie d'une image Docker. Tout d'abord, clarifions le point de confusion le plus fréquent : une image n'est pas un container. Une image est un template statique. Elle contient le code de ton application, tes libraries, tes outils système et ton runtime. Un container est simplement une instance en cours d'exécution de cette image. Tu peux démarrer un millier de containers à partir d'une seule image, mais l'image elle-même reste simplement sur le disque, en attente d'être lue. La caractéristique fondamentale d'une image Docker est l'immuabilité. Une fois qu'une image est créée, elle n'est jamais modifiée. Tu ne peux pas modifier un fichier de configuration à l'intérieur d'une image existante. Si tu veux modifier une image, tu dois en builder une complètement nouvelle. Cette immuabilité garantit qu'une image testée sur ton laptop se comporte de manière identique en production. Le template ne peut pas dériver avec le temps. Si tu ne peux pas modifier une image, tu dois en construire de nouvelles. Une image Docker n'est pas un fichier unique et massif. C'est une composition de plusieurs layers indépendants empilés les uns sur les autres. Chaque layer représente un ensemble spécifique de modifications du filesystem, c'est-à-dire l'ajout, la modification ou la suppression de fichiers. Prends l'exemple d'une application Node.js. Tu buildes rarement le système d'exploitation toi-même. Tu pars plutôt d'une image de base. Cette image de base contient une distribution Linux minimale et le runtime Node. Cette base est en réalité composée de ses propres layers, mais pour toi, elle sert de fondation. Quand tu ajoutes ton application à cette fondation, Docker enregistre tes modifications sous forme de nouveaux layers empilés par-dessus. Tout d'abord, tu importes ton fichier de configuration de dépendances. Ça crée un nouveau layer. Ensuite, tu indiques au système de télécharger et d'installer tes dépendances. Toutes ces libraries téléchargées sont packagées dans le layer suivant. Enfin, tu copies le code source de ton application. Ça forme le layer supérieur. Quand tu démarres un container, Docker empile ces layers en utilisant un union filesystem. Ça donne l'impression que tous les layers indépendants forment une structure de répertoires standard et unique. Si exactement le même chemin de fichier existe dans deux layers, la version du layer supérieur masque la version du layer inférieur. Voici le point clé. Comme les layers sont immuables, ils sont fortement mis en cache et partagés. Si tu mets à jour le code source de ton application et que tu buildes une nouvelle image, Docker calcule ce qui a changé. Il constate que l'image Linux de base, le runtime Node et ton layer de dépendances sont identiques au build précédent. Il réutilise instantanément ces layers existants et ne crée un nouveau layer que pour ton code mis à jour. Ça transforme un deploy qui pourrait prendre des minutes en une opération de quelques millisecondes. Cette architecture permet aussi d'économiser de l'espace disque et de la bande passante réseau. Quand tu pushes ta nouvelle image sur un serveur, tu ne transmets que le layer unique contenant le nouveau code source. Le serveur possède déjà les layers de base. En imposant des layers immuables, Docker garantit que l'environnement de ton application ne peut pas changer silencieusement, tout en s'assurant que tu ne transmets ou ne stockes que les octets exacts que tu as modifiés. C'est tout pour cette fois. À la prochaine !
4

Le plan de construction Dockerfile

3m 23s

Apprenez à écrire un Dockerfile pour construire des images personnalisées. Nous couvrons les instructions essentielles comme FROM, RUN et CMD, et expliquons la différence cruciale entre les formes shell et exec.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 4 sur 18. L'environnement d'exécution complet de ton application complexe peut être décrit en seulement dix lignes de texte brut. Tu fournis un seul fichier à un build system, et tu obtiens un système parfaitement configuré, prêt à tourner n'importe où. C'est ça, le blueprint du Dockerfile. Un Dockerfile est un document texte qui contient toutes les commandes qu'un utilisateur pourrait taper en ligne de commande pour assembler une image. Le format est simple. Chaque ligne commence par une instruction, écrite en majuscules par convention, suivie des arguments pour cette instruction. Docker lit ce fichier ligne par ligne, de haut en bas. Tout Dockerfile valide doit commencer par une base. Tu la définis avec l'instruction FROM. Si tu écris FROM ubuntu, Docker pull l'image officielle Ubuntu et l'utilise comme point de départ. Chaque ligne suivante dans ton fichier va modifier cet environnement de base. Une fois ta base définie, tu as généralement besoin d'installer des dépendances. Tu fais ça avec l'instruction RUN. L'instruction RUN exécute n'importe quelle commande à l'intérieur de l'image actuelle et commit le résultat. Si tu écris RUN apt-get update suivi de tes commandes d'installation de paquets, Docker démarre l'environnement, lance le gestionnaire de paquets, installe les logiciels, et sauvegarde le nouvel état. Ensuite, tu as besoin de ton application elle-même. Un système d'exploitation avec des dépendances installées ne sert à rien sans ton code. C'est l'instruction COPY qui gère ça. Tu fournis un chemin source depuis ton workspace local et un chemin de destination à l'intérieur de l'image. Docker prend tes fichiers et les copie directement dans le filesystem du conteneur. Le build de l'image n'est que la première phase. Tu dois aussi dire à Docker quelle application lancer quand un conteneur démarre. Tu définis ce comportement par défaut en utilisant l'instruction CMD ou ENTRYPOINT. Et voici le point crucial. Il y a deux manières distinctes de formater ces instructions d'exécution, et les mélanger provoque des bugs subtils. La première approche, c'est la forme shell. Tu écris l'instruction suivie de la commande exactement comme tu la taperais dans un terminal. Quand Docker voit ça, il encapsule ta commande dans un shell, en l'exécutant via bin slash sh. C'est pratique parce que les variables d'environnement s'étendent automatiquement. Cependant, le process shell s'interpose entre Docker et ton application. Si Docker envoie un signal pour stopper proprement le conteneur, le shell l'attrape et ton application ne le reçoit jamais, ce qui mène à des arrêts forcés. La deuxième approche, c'est la forme exec. Ça s'écrit sous la forme d'un array JSON. Tu la formates avec des crochets, en passant l'exécutable comme première string et ses arguments comme les strings suivantes. Quand tu utilises la forme exec, Docker bypass le shell complètement. Il lance ton exécutable directement. Ton application devient le process ID un à l'intérieur du conteneur. Ça garantit que les signaux système passent directement à ton application, assurant des arrêts fluides et prévisibles. Si tu veux un conteneur de production stable, utilise toujours la forme exec pour tes commandes finales, pour que ton application contrôle son propre cycle de vie. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de builder !
5

Maîtriser le cache de build

3m 23s

Optimisez la construction de vos images en utilisant le cache de build de Docker. Découvrez pourquoi l'ordre des instructions dans votre Dockerfile est essentiel pour éviter les installations de dépendances inutiles.

Télécharger
Salut, ici Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 5 sur 18. Si ton build Docker prend dix minutes à chaque fois que tu modifies une seule ligne de code source, c'est que tu t'y prends mal. La solution réside entièrement dans la façon dont tu structures ton fichier, et ça veut dire maîtriser le build cache. Quand tu lances un build Docker, le builder traite ton Dockerfile séquentiellement, de haut en bas. Chaque instruction, que ce soit copier un répertoire ou exécuter un script, génère un layer distinct dans l'image finale. Comme l'exécution de ces étapes demande du temps de calcul et de la bande passante réseau, Docker sauvegarde automatiquement le résultat de chaque étape dans un build cache local. Lors des builds suivants, le moteur essaie de réutiliser ces layers sauvegardés pour éviter le travail redondant. Pour déterminer si un cache hit est possible, Docker évalue chaque instruction par rapport à l'historique du cache existant. Pour les instructions qui exécutent des commandes, il vérifie si la command string elle-même est identique à celle utilisée dans le build précédent. Pour les instructions qui copient des fichiers de ta machine hôte vers l'image, Docker va encore plus loin. Il calcule un checksum pour le contenu et les métadonnées de chaque fichier copié. Il compare ensuite ce nouveau checksum au checksum des fichiers du layer précédemment mis en cache. Si les checksums correspondent parfaitement, Docker réutilise le layer en cache et passe à la ligne suivante. Si même un seul byte diffère, le cache est invalidé. Fais bien attention à ça. L'invalidation du cache est une réaction en chaîne stricte. À l'instant où Docker détecte un changement et invalide un layer, il arrête de regarder le cache pour le reste du build. Chaque instruction qui vient après le layer invalidé est forcée de s'exécuter from scratch. Ça arrive parce que chaque layer dépend de l'état exact du layer qui le précède. Cette réaction en chaîne dicte la façon dont tu dois organiser ton Dockerfile. Prends l'exemple d'une application Node où tu gères des dépendances externes. Une erreur fréquente, c'est d'utiliser une seule instruction pour copier tout le dossier de ton projet dans l'image, suivie d'une instruction pour lancer ta commande d'installation de package. Si tu modifies une seule ligne dans un fichier texte quelque part dans ton code source, le checksum de l'instruction de copie change. Le cache casse à cette étape. Par conséquent, l'instruction suivante est forcée de s'exécuter. Tu attends que des centaines de mégaoctets de dépendances se téléchargent à nouveau, même si ta liste de dépendances est restée totalement intacte. L'approche optimale isole les dépendances du code de l'application. Premièrement, tu ajoutes une instruction pour copier uniquement ton fichier de configuration de dépendances, plus précisément ton package manifest, dans l'image. Deuxièmement, tu lances la commande pour télécharger les dépendances. Troisièmement, tu ajoutes une instruction séparée pour copier le reste de ton code source général. Maintenant, quand tu modifies ce même fichier texte et que tu fais un rebuild, Docker évalue la première instruction. Le manifest des dépendances n'a pas changé, donc le cache est utilisé. Il passe à l'étape d'installation. Comme le layer précédent était un cache hit et que la command string est identique, le cache est de nouveau utilisé ici, ce qui évite le téléchargement massif. Le cache ne casse qu'à l'instruction finale, là où le builder copie tes fichiers sources mis à jour. Une attente de dix minutes devient une mise à jour de deux secondes. Le moyen le plus efficace d'accélérer ton pipeline, c'est d'ordonner tes instructions strictement de la moins susceptible de changer à la plus susceptible de changer. C'est tout pour cette fois. Merci d'avoir écouté, et continue de builder !
6

Les Multi-Stage Builds

3m 58s

Gardez vos images de production légères et sécurisées. Cet épisode présente les Multi-Stage Builds, en démontrant comment séparer votre environnement de compilation lourd de votre environnement d'exécution minimal.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 6 sur 18. Faire le deploy de ton compilateur en production représente un risque de sécurité massif, et ça gonfle la taille de ton container de plusieurs gigaoctets. Tu écris du code propre, mais ton artifact final est plombé par tous les outils lourds juste nécessaires pour le build. La solution à ça, ce sont les multi-stage builds. Quand tu buildes des applications dans des langages compilés comme Java, Go ou C++, le processus de compilation nécessite des build tools, des Software Development Kits et du code source brut. Historiquement, les développeurs utilisaient une approche standard où ils installaient toutes ces dépendances dans le container, compilaient le code, puis lançaient l'application. Le problème, c'est que tous ces build tools restent dans l'image de production finale. Tu finis par faire le deploy de ton compilateur, de ton package manager et de tes fichiers intermédiaires en même temps que ton application elle-même. Ça rend ton container énorme. Les gros containers mettent plus de temps à faire un pull sur le réseau et consomment plus d'espace de stockage. Pire encore, ça crée une surface d'attaque massive. Si un attaquant pirate ton container, il a soudainement un environnement de développement tout équipé à sa disposition. Une idée reçue fréquente, c'est que pour corriger ça, tu dois maintenir deux fichiers séparés : un fichier pour le build du logiciel, et un script pour extraire le résultat et le passer à un deuxième fichier pour le deploy. Ce n'est pas le cas. Les multi-stage builds gèrent toute cette séparation des responsabilités à l'intérieur d'un seul fichier. Voici l'idée clé. Un multi-stage build te permet de définir plusieurs environnements distincts, ou stages, de manière séquentielle. Chaque stage commence par définir sa propre base image. Tu commences le premier stage avec une base image lourde qui contient tous tes outils de développement. Tu donnes un nom à ce stage, comme builder. À l'intérieur de ce stage builder, tu copies ton code source depuis ta machine locale et tu exécutes tes commandes de compilation. Le stage builder fait le gros du travail, en générant le fichier exécutable final. Ensuite, plus bas dans ce même fichier, tu définis une deuxième base image. Ça lance un tout nouveau stage. Pour ce stage, tu choisis une runtime image minimale. Cet environnement contient uniquement les dépendances exactes nécessaires pour faire tourner l'application, avec zéro build tools. Au lieu de copier à nouveau les fichiers depuis ta machine locale, tu utilises une instruction de copie spécialisée. Cette instruction dit au build engine de retourner dans le stage builder, de récupérer uniquement l'artifact compilé et terminé, et de le déposer dans ton nouveau stage minimal. Quand le build engine a terminé, il produit un container basé uniquement sur le stage final. Tout ce qui vient du premier stage — le compilateur, les packages téléchargés, le code source — est complètement jeté. Ça n'arrive jamais dans ton image de production. Prenons un scénario concret avec une application Java Spring Boot. Dans ton fichier, ton premier stage utilise une image Maven volumineuse. À l'intérieur de ce stage, tu lances la commande Maven pour packager ton application. Maven télécharge toutes les dépendances nécessaires au projet, compile le code Java et le package dans un fichier JAR final. Ensuite, tu lances le deuxième stage en utilisant une base image Java Runtime Environment légère. Tu n'installes pas Maven dans cet environnement. Tu n'y copies pas tes fichiers sources Java. À la place, tu dis à l'engine de copier uniquement le fichier JAR compilé directement depuis le stage Maven vers cet environnement runtime minimal. Enfin, tu définis la commande par défaut pour exécuter ce fichier JAR. En séparant strictement l'environnement de build de l'environnement runtime, tu garantis que ton container de production est totalement isolé de tes build tools. L'image finale ne voit que l'artifact compilé et le strict minimum du runtime, ce qui garde ton deploy rapide, léger et hautement sécurisé. C'est tout pour cet épisode. À la prochaine !
7

Exécution et interaction

3m 41s

Apprenez la mécanique pratique de l'exécution des conteneurs. Nous couvrons les modes détaché et interactif, la publication de ports de base, et comment exécuter des commandes shell à l'intérieur d'un conteneur en cours d'exécution.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Docker Masterclass, épisode 7 sur 18. Lancer un process en background, c'est exactement ce que tu veux pour un serveur web en production. Mais quand ce serveur refuse de charger ta page, il te faut un moyen de briser la vitre, d'entrer dans l'environnement et de voir ce qui est vraiment cassé. Cet épisode parle de l'exécution et de l'interaction avec les conteneurs. La commande de base pour démarrer n'importe quel conteneur, c'est docker run. Par défaut, si tu lances un conteneur, il attache son output directement à l'écran de ton terminal. Il prend le contrôle de ton prompt, et si tu fais contrôle C, le conteneur s'arrête. Pour un service qui tourne en continu comme un serveur web Nginx, c'est pas du tout pratique. Tu veux que le serveur tourne en background. Tu obtiens ça en utilisant le flag detached mode, que tu tapes avec un simple tiret d. Quand tu passes tiret d, Docker démarre le conteneur, affiche un long container ID unique à l'écran, et te rend immédiatement ton prompt. Le conteneur continue de tourner tranquillement en background. Cependant, ce conteneur qui tourne est isolé. Même si Nginx sert activement du trafic sur le port 80 à l'intérieur du conteneur, ta machine host ne peut pas le voir. Tu dois explicitement percer un trou à travers cette isolation réseau. Tu fais ça avec le flag publish, tapé comme tiret p. Ça te permet de mapper un port spécifique sur ton laptop host vers un port spécifique à l'intérieur du conteneur. Si tu spécifies tiret p 8080 deux-points 80, Docker intercepte tout le trafic web qui arrive sur ton laptop sur le port 8080 et le route directement vers le port 80 à l'intérieur du conteneur. Maintenant, tu as un serveur web detached que tu peux joindre sans problème depuis ton navigateur local. Mais que se passe-t-il quand tu charges la page et que tu vois une erreur de configuration ? Ton serveur Nginx tourne en background, mais tu as besoin de lire les fichiers de configuration sur son filesystem. Voici l'idée clé. Tu n'as pas besoin de stopper un conteneur pour regarder à l'intérieur. À la place, tu utilises la commande docker exec. Alors que docker run crée un tout nouveau conteneur, docker exec lance une toute nouvelle commande à l'intérieur d'un conteneur déjà existant et qui tourne. Pour obtenir un terminal utile et fonctionnel, tu dois combiner deux flags spécifiques en tiret i t. Le i signifie interactive. Ça garde le canal d'input standard ouvert, ce qui te permet de vraiment taper des commandes dans le conteneur. Le t alloue un pseudo-TTY. Ça fait croire au conteneur qu'il est connecté à un terminal physique, ce qui est nécessaire pour que les prompts et le formatage du texte s'affichent correctement. Si tu lances docker exec tiret i t, suivi du nom du conteneur et de la commande slash bin slash bash, tu tombes instantanément sur un prompt à l'intérieur du conteneur Nginx qui tourne. Tu es maintenant dans la boîte. Tu peux lire les fichiers de configuration, vérifier les logs d'erreur et inspecter le filesystem exactement comme tu le ferais sur un serveur Linux standard. Quand tu as fini, taper exit ferme ta session shell temporaire. Le conteneur Nginx lui-même n'est absolument pas affecté, il continue de tourner en background. Tôt ou tard, tu devras faire un peu de nettoyage. Lancer docker stop avec le nom du conteneur envoie un signal de terminaison, ce qui donne à l'application le temps de s'arrêter proprement. Cependant, stopper un conteneur ne le supprime pas de ton système. Le conteneur stoppé reste sur ton disque dur, en conservant ses logs et toutes les modifications internes de son filesystem. Pour le supprimer définitivement et libérer cet espace disque, tu lances la commande docker rm. La distinction la plus critique à mémoriser, c'est la différence entre run et exec. Docker run démarre un tout nouveau système isolé, alors que docker exec te permet d'entrer dans un système qui respire déjà. Merci d'avoir écouté. Prenez soin de vous, tout le monde.
8

Les bases de la persistance des données

3m 22s

Évitez les pertes de données catastrophiques lors de la suppression de conteneurs. Cet épisode compare les Bind Mounts pour le rechargement à chaud en développement local avec les Docker Volumes pour la persistance sécurisée des bases de données.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 8 sur 18. Tu fais un deploy d'une base de données dans un container, tu écris des milliers de lignes, et tout fonctionne parfaitement. Ensuite, tu supprimes le container pour mettre à jour l'image, et toute ta base de données disparaît pour toujours. Par défaut, le stockage d'un container est strictement temporaire. Pour éviter de perdre des données, on a besoin des bases de la persistance des données. Quand un container démarre, il crée une writable layer au-dessus de son image de base. Tous les fichiers que le container crée ou modifie sont stockés dans cette layer spécifique. Si le container est détruit, cette layer est détruite avec lui. Les données sont complètement éphémères. Elles n'existent pas en dehors du lifecycle du container. Pour garder tes données en sécurité, tu dois les sortir du container et les envoyer sur la machine host. Docker propose deux mécanismes principaux pour ça : les bind mounts et les managed volumes. Un bind mount mappe un path spécifique et explicite sur ta machine host directement vers un path à l'intérieur du container. Tu dis exactement à Docker quel dossier de ton ordi doit apparaître dans l'environnement du container. Ça dépend énormément de l'OS de ton host et de ta structure de fichiers locale. La machine host garde le contrôle total sur les fichiers. Cette approche est parfaite pour le développement en local. Tu fais un bind mount de ton dossier de code source local vers le path de l'application web de ton container. Quand tu édites et que tu sauvegardes un script sur ton ordi, le container lit immédiatement ce fichier mis à jour. Tu obtiens un hot-reloading instantané sans avoir à rebuild l'image du container à chaque fois que tu changes une ligne de code. Le deuxième mécanisme, c'est le managed volume. Au lieu de pointer vers un path spécifique que tu contrôles sur ton disque dur, tu demandes à Docker de créer une entité de stockage. Docker provisionne l'espace sur la machine host et le gère complètement. Tu n'as pas besoin de savoir où Docker place physiquement les fichiers sur ton système host. Tu donnes juste un nom au volume et tu dis au container où le mount en interne. Les volumes sont la solution standard pour la persistance d'une base de données. Quand tu fais tourner PostgreSQL, tu crées un volume en lançant une simple commande et en lui donnant un identifiant, comme db-data. Ensuite, au démarrage de ton container, tu passes un flag de configuration qui lie ce volume db-data au path interne où Postgres écrit les records de ses tables. Si tu stoppes et que tu supprimes le container de la base de données, Docker ne touche absolument pas au volume. Quand tu vas spin up un nouveau container plus tard, tu attaches simplement ce volume existant, et tous tes records sont intacts. Voici le point clé. Le choix entre ces deux méthodes dépend de qui a besoin d'accéder aux fichiers. Utilise les bind mounts quand ta machine host a besoin d'interagir activement avec les données, comme un développeur qui édite du code source. Utilise les managed volumes quand le container possède les données, comme un moteur de base de données qui écrit des records, et que tu veux juste que Docker garde ces fichiers en sécurité entre les restarts du container. Les containers éphémères sont un choix de design, pas un défaut, parce qu'ils te forcent à découpler tes données de ton compute au runtime. Pars toujours du principe que ton container sera détruit immédiatement, et mappe explicitement ton state persistant en dehors de celui-ci. Si tu trouves ces épisodes utiles, tu peux soutenir l'émission en cherchant DevStoriesEU sur Patreon. C'est tout pour aujourd'hui. Merci d'avoir écouté, et keep building !
9

Le réseau des conteneurs

3m 21s

Comprenez comment Docker gère le trafic réseau. Apprenez les bases de la publication de ports vers l'hôte et comment les conteneurs communiquent entre eux en toute sécurité sur des réseaux bridge isolés.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Docker Masterclass, épisode 9 sur 18. Par défaut, un container en cours d'exécution est totalement isolé du monde extérieur. Il tourne dans une bulle privée, et si tu veux qu'Internet puisse l'atteindre, tu dois intentionnellement percer des trous dans cette isolation. Gérer ces trous et les connexions entre les containers, c'est le boulot du Container Networking. Quand un container démarre, Docker lui assigne une adresse IP interne. Le container peut généralement accéder à Internet pour télécharger des updates ou faire des appels réseau, mais rien en dehors de la machine host ne peut y accéder. Pour accepter le trafic entrant, tu utilises le port publishing. Le publishing prend un port sur ta machine host physique et le bind directement à un port à l'intérieur du container. Si tu as un container de serveur web qui écoute en interne sur le port 80, tu peux le publish sur le port 8080 de ton host. Quand un utilisateur envoie une requête à ta machine host sur le port 8080, Docker l'intercepte et la forward directement à travers le firewall vers le container sur le port 80. Tu configures ce mapping au démarrage en utilisant le flag publish. Sans ce flag, le container reste inaccessible au réseau extérieur. Ça, ça couvre le trafic externe. Maintenant, la deuxième partie, c'est la communication interne. Les applications tournent rarement comme un process isolé. Tu as généralement plusieurs containers qui ont besoin de partager des data. Par défaut, Docker attache chaque nouveau container à un réseau intégré appelé le default bridge. Un bridge, c'est un switch réseau logiciel qui tourne sur ta machine host. Il connecte les containers pour qu'ils puissent échanger des paquets, tout en les isolant des réseaux externes. Voici le point clé. Le default bridge permet aux containers de communiquer en utilisant leurs adresses IP internes, mais les adresses IP des containers changent à chaque fois qu'un container redémarre ou se met à jour. Hardcoder une adresse IP dans la configuration de ton application va casser ton système presque immédiatement. Pour résoudre ça, tu crées un réseau user-defined bridge. Quand tu attaches plusieurs containers à un user-defined bridge custom, Docker fournit une résolution DNS interne automatique. Ça veut dire que les containers peuvent se trouver entre eux en utilisant exactement leurs noms de container. Prends un scénario où tu as un container d'application backend et un container de base de données. Tu crées un seul réseau bridge custom et tu y attaches les deux containers. Dans le code de ton application backend, tu n'écris pas une connection string de base de données en utilisant une adresse IP fragile. Tu utilises simplement le nom du container de base de données comme adresse host. Docker intercepte la requête DNS, trouve le container de base de données sur ce bridge spécifique, et route le trafic vers la bonne adresse IP interne dynamiquement. Ce design te donne un contrôle total sur la sécurité de l'application. Le backend et la base de données peuvent se parler librement à travers le bridge custom, mais aucun trafic externe ne peut atteindre la base de données. Pour faire tourner ton application de manière sécurisée, tu laisses la base de données cachée sur le bridge interne privé, sans aucun port published. Ensuite, tu publish uniquement le port du container backend sur ta machine host. Les utilisateurs externes tapent sur le port public du backend, et le backend requête la base de données de manière sécurisée via le bridge privé. L'architecture de ton application dicte ta topologie réseau : utilise les published ports pour inviter les utilisateurs externes à entrer, et les user-defined bridges custom pour laisser tes containers internes se parler de manière sécurisée par leur nom. C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !
10

Introduction à Docker Compose

3m 49s

Allez au-delà des commandes pour un seul conteneur. Découvrez comment Docker Compose utilise un fichier YAML déclaratif pour définir, mettre en réseau et orchestrer plusieurs services simultanément.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Docker Masterclass, épisode 10 sur 18. Tu ne devrais pas avoir besoin d'un document texte rempli de commandes terminal complexes juste pour démarrer ton environnement de développement local. Se fier à l'historique de ton shell pour te souvenir des flags, des ports et des noms de network exacts pour plusieurs containers est une façon de travailler très fragile. L'introduction à Docker Compose règle ce problème en transformant toute ton application stack en un seul fichier déclaratif. Quand tu lances une application, elle existe rarement de manière isolée. Tu as généralement un serveur web, une base de données, et peut-être une couche de cache. Les démarrer manuellement nécessite de lancer plusieurs commandes distinctes. Tu dois créer un network custom, y attacher chaque container, exposer les bons ports, et monter des disques de stockage. Si tu fais une faute de frappe dans l'une de ces étapes, les containers ne peuvent pas communiquer et l'application plante. Docker Compose remplace ce processus impératif par un fichier YAML déclaratif, normalement nommé compose dot yaml. Au lieu de dire à Docker exactement quoi faire étape par étape, tu déclares l'état final désiré pour tout ton système. Docker Compose trouve les étapes nécessaires pour atteindre cet état. Le fichier YAML est divisé en trois sections structurelles principales. La première section, et la plus importante, s'appelle services. Un service est simplement une définition pour un container spécifique dans ton application. Prends un scénario où tu fais tourner une application Node avec une base de données MySQL. Sous la section services, tu définis deux entrées. Tu nommes la première web, en spécifiant l'image Node et les ports locaux que tu veux exposer. Tu nommes la deuxième database, en spécifiant l'image MySQL et les variables d'environnement requises, comme le mot de passe root. Voici le point clé. Tu n'as pas besoin de lier ces containers manuellement. Par défaut, Docker Compose crée automatiquement un seul network interne pour ton application. Il attache tous les services définis à ce network et assigne à chaque container un hostname qui correspond à son nom de service. Le code de ton application Node peut se connecter à la base de données simplement en ciblant le hostname database, et le DNS interne le résout vers la bonne IP du container. Tu peux définir manuellement des networks custom dans la section networks du fichier YAML, mais pour la plupart des setups de développement standards, le comportement par défaut fait exactement ce dont tu as besoin. La dernière pièce structurelle est la section volumes. Les bases de données nécessitent un stockage persistant. Si le container MySQL s'arrête, tu ne veux pas que tes données soient effacées. Tout en bas de ton fichier YAML, tu déclares un volume nommé. Ensuite, dans la définition de ton service database, tu mappes un chemin spécifique à l'intérieur du container vers ce volume nommé. Docker Compose gère la création et le cycle de vie de ce stockage pour toi. Une fois que ton fichier est écrit, tu gères toute la stack avec deux commandes. Tu tapes docker compose up. Compose lit le fichier YAML, crée le network interne, configure les volumes, et démarre les containers MySQL et Node. Si tu veux continuer à travailler dans ton terminal, tu ajoutes le flag detach pour tout faire tourner en background. Quand tu as fini de travailler, tu n'arrêtes pas et tu ne supprimes pas chaque container individuellement. Tu tapes docker compose down. Compose arrête proprement l'app Node, arrête la base de données, et supprime les containers et le network par défaut, gardant ton système entièrement propre. Il laisse tes volumes nommés intacts, ce qui veut dire que les enregistrements de ta base de données t'attendent la prochaine fois que tu montes la stack. Docker Compose change ton mindset, passant de la gestion de containers isolés individuels à la gestion d'environnements applicatifs complets. Le setup de ton infrastructure devient un seul morceau de code que tu peux commit dans ton version control et partager instantanément avec ton équipe. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
11

Docker dans le pipeline CI/CD

3m 08s

Éliminez les tests instables avec des environnements de build conteneurisés. Cet épisode explique comment utiliser Docker dans les pipelines d'intégration continue (CI/CD) pour garantir des tests automatisés parfaitement reproductibles.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 11 sur 18. Tu push ton code, le pipeline tourne, et les tests plantent. Tu les lances en local, et ils passent parfaitement. Ton serveur de CI a une version de dépendance légèrement plus ancienne que ton laptop. Ce décalage est la cause principale des fameux tests flaky, mais conteneuriser ton environnement de build rend chaque run parfaitement prévisible. Aujourd'hui, on parle de Docker dans le pipeline CI/CD. Historiquement, l'intégration continue, ça voulait dire maintenir des serveurs de build statiques. Avec le temps, les ingénieurs se connectent à ces machines virtuelles pour installer des packages, mettre à jour les runtimes, et ajuster les configurations système. Ces serveurs se transforment en pet VMs. Ils accumulent du state caché et des restes de fichiers de cache. Quand un pipeline plante, tu perds du temps à chercher si le code est vraiment cassé ou si le serveur a juste besoin d'une mise à jour. Utiliser Docker comme environnement de build contourne complètement ce problème. Au lieu d'exécuter tes scripts de test directement sur l'OS hôte d'un worker CI, le worker lance un conteneur. Le runner CI pull une image Docker spécifique, démarre le conteneur, mount ton code source, et exécute tes étapes de build dans cet environnement isolé. Voici le point clé. Quand le job se termine, le conteneur est détruit. Le prochain run du pipeline obtient un environnement identique et complètement neuf. Il n'y a pas de processus en arrière-plan qui entrent en conflit avec les runs précédents. L'environnement est stateless et entièrement défini par l'image. Pense au processus de mise à jour d'un runtime. Supposons que tu doives passer ton projet de Node 18 à Node 20. Dans une configuration classique, quelqu'un doit se connecter au serveur de build, mettre à jour le logiciel sur tout le système, et espérer que ça ne casse pas d'autres projets qui partagent ce même worker. Avec Docker comme environnement de build, tout ce processus se résume à changer une string. Tu mets à jour le tag de l'image de base dans ta configuration, de Node 18 à Node 20. Le runner CI pull la nouvelle image. Ton build tourne instantanément dans l'environnement mis à jour. Si un test plante, tu revert le tag et tu réessaies plus tard. Tu gères l'infrastructure directement avec ton code. Il y a une autre dimension à ça. Si tu utilises Docker pour build ton application, ton pipeline CI doit pouvoir build et push des images. Si ton job CI tourne déjà dans un conteneur, comment tu lances des commandes Docker build ? Ça demande un pattern qu'on appelle Docker-in-Docker. Docker-in-Docker, ça veut dire faire tourner un daemon Docker isolé à l'intérieur de ton conteneur CI. Le conteneur externe fournit l'environnement contrôlé pour les étapes de ton pipeline, pendant que le daemon interne gère les builds de ton application. Ça permet à ton job CI de pull des images de base, de construire le conteneur de ton application, et de push l'artefact final vers un registry, tout ça sans polluer la machine hôte qui fait tourner le worker CI. Déplacer ton environnement CI dans un conteneur redonne le contrôle du système de build au développeur. Exactement la même image qui build ton code sur un serveur distant peut tourner sur ta machine locale, ce qui garantit que si un test plante dans la CI, tu peux reproduire exactement cette erreur en local. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de build !
12

Images multi-plateformes

3m 32s

Résolvez l'incompatibilité entre Apple Silicon et les serveurs cloud. Découvrez comment Docker Buildx vous permet de faire de la compilation croisée et de packager des applications pour les architectures ARM et AMD64 simultanément.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 12 sur 18. L'expression « Ça marche sur ma machine » prend un tout autre sens quand ta machine locale utilise un processeur ARM, mais que ton cloud de production tourne sur Intel. Tu testes ton conteneur en local, tu le push sur un registry, tu le pull sur le serveur, et il plante instantanément avec une erreur de format d'exécution. Le problème, c'est une incompatibilité d'architecture matérielle. Pour corriger ça, tu utilises des images multiplateformes. Une image de conteneur, c'est fondamentalement un ensemble de binaires et de systèmes de fichiers. Si tu build une image sur un Mac Apple Silicon, les binaires qui en résultent sont compilés pour l'architecture ARM64. Quand tu fais un deploy de cette image sur un serveur Linux cloud standard qui fait tourner un processeur AMD64, le CPU hôte ne comprend littéralement pas les instructions à l'intérieur du conteneur. Historiquement, tu devais maintenir des pipelines de build séparés pour différentes cibles matérielles. Docker Buildx supprime cette contrainte. Docker Buildx est un plugin en ligne de commande qui étend le système de build Docker standard. Il utilise un moteur backend appelé BuildKit pour exécuter les builds en simultané et gérer des tâches complexes comme cibler plusieurs plateformes en une seule passe. Quand tu build une image multiplateforme avec Buildx, tu ne mets pas deux systèmes de fichiers séparés dans un seul conteneur géant. À la place, Buildx crée une manifest list d'image. Vois ce manifest comme une table de routage. Il contient une liste de pointeurs vers différentes images spécifiques à l'architecture, stockées dans ton registry. Quand une machine pull ton image, son daemon Docker lit ce manifest, identifie sa propre architecture de CPU hôte, et télécharge automatiquement uniquement les layers d'image qui correspondent à son matériel. Pour cross-compiler et packager une API backend pour les deux architectures en même temps, tu utilises la commande docker buildx build. Tu inclus un flag platform, en lui passant une liste de tes cibles séparées par des virgules. Par exemple, tu tapes le flag, suivi de linux slash amd64 virgule linux slash arm64. Tu ajoutes ton tag d'image standard, et ensuite tu ajoutes un flag push. Voici le point clé. Quand tu build pour plusieurs plateformes en même temps, tu ne peux pas juste charger l'image multiplateforme finale dans le cache de ton moteur Docker local. Le daemon local n'est pas conçu pour contenir une manifest list pointant vers plusieurs architectures. Tu dois dire à Buildx de push les résultats directement vers ton container registry. Le registry agit comme le système de stockage qui organise correctement la manifest list et les images individuelles par architecture. Pour exécuter physiquement le build pour un processeur que tu n'as pas, Buildx s'appuie sur un émulateur appelé QEMU. Docker Desktop configure ça automatiquement. Quand ta machine ARM atteint une étape qui nécessite une instruction AMD64, l'émulateur la traduit à la volée. Ça demande zéro changement dans ton Dockerfile. Si tu as besoin de temps de build plus rapides, tu peux aussi utiliser des outils de cross-compilation directement dans un multi-stage build, ce qui évite l'émulation mais nécessite de configurer des flags de compilateur spécifiques dans ton code. La vraie puissance d'un manifest multiplateforme, c'est qu'il isole complètement le consommateur des détails matériels sous-jacents. Un développeur sur un Mac et un cluster de production qui tourne sous Intel pull exactement le même tag d'image, et le registry sert automatiquement le bon binaire à chacun, sans aucune configuration supplémentaire. Merci d'avoir passé quelques minutes avec moi. À la prochaine, à plus.
13

Le Docker MCP Toolkit

3m 12s

Connectez vos agents d'IA à des outils locaux en toute sécurité. Cet épisode présente le Docker Model Context Protocol (MCP) Toolkit, en expliquant comment gérer des serveurs MCP conteneurisés à l'aide de catalogues et de profils.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Docker Masterclass, épisode 13 sur 18. Donner à un agent IA un accès direct à ta base de données locale ou à ton filesystem est super puissant. Mais installer des scripts d'intégration non fiables directement sur ta machine host pour faire ça, c'est un désastre de sécurité qui t'attend. Le Docker MCP Toolkit règle ça en déplaçant ces intégrations dans des containers isolés. Le Model Context Protocol, ou MCP, est un standard ouvert qui permet aux clients IA, comme l'app desktop Claude ou l'éditeur Cursor, de se connecter à des sources de données et des tools externes. Pour donner une nouvelle capacité à ton IA, tu fais tourner une petite application qu'on appelle un serveur MCP. Historiquement, ça voulait dire télécharger des scripts Python ou Node tiers et les lancer directement sur ton OS. Ça introduit une grosse friction opérationnelle avec des conflits de dépendances, et surtout, ça donne à du code non fiable un accès illimité à ta machine. Le Docker MCP Toolkit résout ça en wrappant ces serveurs dans des containers Docker standards. La première brique de ce système, c'est le Catalog. Un Catalog est un registry de serveurs MCP conteneurisés et vérifiés. Au lieu de pull des repositories aléatoires sur Internet, tu pull des images Docker standardisées. Ces images sont pré-packagées pour faire tourner les tools requis sans avoir besoin de runtimes locaux sur ta machine host. Une fois que tu as accès à ces serveurs, il te faut un moyen de les organiser. Ça se fait avec des Profiles. Un Profile est un groupe de configuration qui définit exactement quels tools sont nécessaires pour un projet spécifique. Par exemple, tu pourrais créer un profile nommé web-dev. Dans cette configuration, tu spécifies que ce profile a besoin du serveur GitHub pour lire les repositories de code et du serveur Playwright pour l'automatisation du navigateur. Tu configures tes clés API et tes variables d'environnement pour les deux tools une seule fois dans la configuration du profile. Maintenant, tu as des tools isolés et un profile défini. Comment l'IA s'y connecte ? C'est là que ça devient intéressant. La connexion est gérée par la MCP Gateway. La Gateway agit comme un routeur central qui tourne sur ton host. Tu ne configures pas ton client IA pour lancer des containers individuels. À la place, tu pointes Claude ou Cursor vers la MCP Gateway et tu demandes le profile web-dev. Quand le client se connecte, la Gateway lit le profile, démarre automatiquement les containers GitHub et Playwright demandés en background, et établit la connexion. La Gateway gère la communication entre le client IA et les containers en utilisant le protocole standard. Le client IA croit qu'il parle à des tools locaux, mais toute l'exécution se passe de manière sécurisée dans Docker. Tu ne configures les tools qu'une seule fois dans le profile, et tu peux partager ce setup exact avec n'importe quel nombre d'applications IA différentes. Si un de ces tools plante ou est compromis, il est piégé dans un container, complètement aveugle au reste de ton système. La vraie valeur du MCP Toolkit, c'est qu'il sépare la configuration de tes tools IA des clients qui les utilisent, en offrant de grosses garanties d'isolation sans sacrifier l'intelligence de tes workflows. Merci d'avoir écouté. Prenez soin de vous, tout le monde.
14

L'auto-découverte Dynamic MCP

4m 01s

Explorez Dynamic MCP, une fonctionnalité expérimentale qui permet aux clients IA de rechercher dans le Docker MCP Catalog et d'installer dynamiquement de nouveaux serveurs d'outils pendant une conversation sans configuration manuelle.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 14 sur 18. Tu es en pleine conversation avec un coding agent IA et tu lui demandes d'interroger une base de données. Normalement, si tu as oublié de configurer l'outil de base de données au préalable, l'agent échoue et te demande d'intervenir. Le problème, c'est que la configuration manuelle des outils interrompt le workflow. Mais que se passerait-il si l'agent se rendait compte qu'il lui manque une fonctionnalité, consultait un catalogue et installait le serveur nécessaire entièrement à la volée ? C'est exactement ce qu'accomplit Dynamic MCP Auto-Discovery. En général, fournir des outils à un Large Language Model implique de les définir statiquement dans un fichier de configuration avant de démarrer la session. Si ton agent doit pouvoir lire un repository GitHub, publier un message Slack et interroger une base de données, tu dois charger tous ces serveurs Model Context Protocol à l'avance. Cette approche encombre la context window avec des outils qui risquent de ne jamais être utilisés et t'oblige à anticiper parfaitement les besoins de l'agent. Dynamic MCP change la donne. Cela permet à l'agent de découvrir et d'attacher les outils précisément lorsque la tâche l'exige, sans aucune intervention humaine. Lorsque tu actives la fonctionnalité dynamique, la Docker MCP Gateway expose un ensemble d'outils de gestion directement à l'agent IA. La Gateway lui donne essentiellement la capacité de gérer sa propre toolchain. Les deux outils critiques fournis par la Gateway pour ce processus sont mcp-find et mcp-add. L'agent interagit avec eux exactement comme avec n'importe quel function call standard. On peut illustrer cette logique avec un scénario concret. Supposons que tu demandes à ton agent d'analyser les métriques utilisateur stockées dans une base de données SQL. L'agent évalue la requête, vérifie son toolkit actuel et constate qu'aucun outil d'interrogation de base de données n'est chargé. Au lieu de lever une erreur, l'agent invoque l'outil mcp-find en lui passant une string de recherche pertinente, comme postgres. La Gateway intercepte cet appel et interroge le catalogue Docker MCP configuré pour trouver les serveurs disponibles correspondant à cette string. Elle renvoie ensuite à l'agent les métadonnées et les descriptions des serveurs correspondants. L'agent lit la description, confirme que le serveur Postgres résoudra le problème et passe à l'étape suivante. L'agent invoque ensuite l'outil mcp-add en lui transmettant l'identifiant du serveur Postgres qu'il vient de trouver. C'est là que ça devient intéressant. La Gateway intercepte la requête mcp-add, pull l'image nécessaire, démarre le serveur MCP dans un conteneur Docker et bind dynamiquement les nouveaux outils à la connexion active. L'agent a soudainement accès aux outils de base de données, se connecte à ta base de données, exécute la requête que tu avais demandée initialement et renvoie le résultat. L'ensemble du processus se déroule en background, gardant ta conversation totalement ininterrompue. Un troisième outil est fourni dans cette suite de gestion pour l'exécution de code expérimental, mais il gère un ensemble de problèmes complètement différent, donc nous gardons notre attention strictement sur la discovery aujourd'hui. Voici le point clé concernant ce processus. Lorsque l'agent utilise mcp-add pour charger un nouveau serveur, cet ajout est strictement scopé à la session en cours. La Gateway ne réécrit pas tes fichiers de configuration globaux et les outils nouvellement ajoutés ne persistent pas après un redémarrage. Lorsque tu fermes la session, le tool binding temporaire est détruit. Cela garantit que ton environnement de base reste propre et sécurisé, tout en offrant à l'agent une flexibilité maximale pour résoudre dynamiquement des problèmes complexes à plusieurs étapes. En exposant la recherche et l'installation dans le catalogue comme des function calls standards, Dynamic MCP élimine le fardeau de la configuration initiale et permet à l'agent de construire son propre environnement à la demande. C'est tout pour cet épisode. Merci pour ton écoute, et keep building !
15

Docker Sandboxes pour l'IA

3m 15s

Comprenez l'architecture des Docker Sandboxes. Découvrez pourquoi les agents de codage IA autonomes nécessitent des microVMs isolées avec des démons Docker dédiés au lieu des namespaces de conteneurs standards.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Docker Masterclass, épisode 15 sur 18. Un agent de coding IA autonome est exactement le genre de process que tu ne veux pas faire tourner avec un accès root sur ton laptop. Tu lui demandes de fixer un bug, et d'un coup il télécharge des packages arbitraires, modifie des fichiers système ou essaie de rebuild ton infrastructure locale. Il te faut un endroit où l'agent peut agir comme un admin sans vraiment l'être. C'est exactement ce que les Docker Sandboxes pour l'IA sont censées résoudre. Traditionnellement, Docker isole les process en utilisant les namespaces Linux et les control groups. Ces containers partagent le kernel de l'OS hôte. Pour un web service prévisible, ce modèle marche parfaitement. Mais un agent IA est par nature imprévisible. Il génère du code non vérifié, l'exécute, et a souvent besoin d'installer de nouveaux packages système à la volée pour tester ses propres solutions. Partager le kernel hôte avec un agent imprévisible, c'est un risque de sécurité trop grand. Pour régler ça, les Docker Sandboxes abandonnent les namespaces de containers standards au profit de microVMs isolées. Quand tu lances une sandbox pour un agent, ça boote une machine virtuelle dédiée et légère. L'agent a son propre kernel distinct. Il ne peut pas voir tes process hôtes. Il ne peut pas accéder à ta network stack hôte par défaut. Surtout, ça élimine complètement le risque des vulnérabilités classiques de container escape. L'agent est strictement confiné dans une box virtualisée au niveau hardware. C'est super important quand tu penses à ce que font vraiment les agents IA. Imagine que ton agent a pour tâche d'écrire une web app complexe, de créer un Dockerfile pour elle, et de tester le build. Pour faire ça, l'agent doit lancer des commandes Docker. Si tu mappais simplement la Docker socket de ton système hôte dans un container standard, l'agent pourrait théoriquement lancer des containers privilégiés directement sur ta machine hôte. Les Docker Sandboxes empêchent ça en faisant tourner un Docker daemon complètement isolé à l'intérieur même de la microVM. L'agent peut build des images, pull des dépendances externes, et faire tourner des nested containers toute la journée. Comme il parle au daemon isolé dans la microVM, l'environnement Docker de ton système hôte reste complètement ignorant et non pollué. Quand la task se termine et que la sandbox est détruite, le daemon interne et toutes ses images téléchargées disparaissent immédiatement. C'est là que ça devient intéressant. Si la microVM est complètement isolée, comment tu fais pour récupérer le code final ? L'architecture résout ça en utilisant le workspace mounting. C'est un mécanisme de filesystem passthrough sécurisé. Quand tu initialises la sandbox, tu définis un répertoire spécifique sur ton hôte pour servir de workspace. Ce seul répertoire est monté de façon sécurisée dans la microVM. Pendant que l'agent écrit du code, lance des tests ou génère des assets, il les sauvegarde dans ce répertoire workspace. Le passthrough synchronise ces fichiers spécifiques en retour sur ton filesystem hôte en temps réel. L'agent délivre l'output demandé sans jamais avoir accès au reste de ton disque dur. Il peut tout casser librement à l'intérieur de la microVM, mais tes fichiers locaux restent intacts. L'idée clé, c'est que l'isolation dans ce contexte ne sert plus juste à protéger l'hôte contre des softwares externes malveillants. Il s'agit de permettre en toute sécurité les opérations système imprévisibles et hautement privilégiées qu'un agent autonome doit effectuer pour être vraiment utile. Si tu aimes ces épisodes et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour cet épisode. À la prochaine !
16

Construire des équipes d'agents IA

3m 28s

Arrêtez de vous fier à un seul modèle d'IA pour les tâches complexes. Cet épisode présente le framework Docker Agent, en montrant comment composer des équipes spécialisées d'agents définies en YAML.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Docker Masterclass, épisode 16 sur 18. Tu confies une énorme erreur applicative à un seul modèle d'IA. Il essaie de garder toute l'architecture, les logs et la syntaxe cible en tête en même temps. À mi-chemin, il s'embrouille et hallucine un fix pour un fichier qui n'a rien à voir. Un modèle générique qui essaie de tout faire, ça mène à un context overload. Pour résoudre des problèmes complexes de manière fiable, tu as besoin de construire des équipes d'agents IA. Le framework Docker Agent te permet de définir des équipes spécialisées d'agents IA avec un simple fichier de configuration YAML. Au lieu d'écrire un seul system prompt monolithique, tu divises le workflow en rôles distincts. Tu structures ça sous forme de hiérarchie. Il y a un root agent qui orchestre le workflow, et plusieurs sous-agents qui exécutent des tâches spécifiques. Ça isole le contexte. Chaque sous-agent reçoit uniquement les informations dont il a besoin pour son job spécifique. Prends l'exemple d'un workflow de debugging. Tu as besoin d'une équipe avec deux rôles distincts. D'abord, un investigateur de bugs qui analyse les stack traces. Ensuite, un fixer qui réécrit vraiment le code cassé. Tu définis toute la composition de cette équipe dans un fichier appelé docker tiret agent point yml. Tu commences par configurer le root agent tout en haut du fichier. Tu lui donnes un nom, tu sélectionnes un modèle de langage sous-jacent, et tu fournis des instructions système. Le root agent agit comme un manager. Sa responsabilité principale n'est pas de résoudre le problème directement, mais de déléguer le travail. Tu donnes l'instruction au root agent de coordonner l'investigateur et le fixer en fonction des inputs qu'il reçoit. Ensuite, tu définis les sous-agents dans le même fichier YAML. Tu déclares l'agent investigateur de bugs. Tu lui assignes un modèle qui excelle dans le raisonnement et la lecture de logs. Tu lui donnes des instructions strictes pour lire uniquement les stack traces, identifier la fonction qui plante, et générer en output une brève explication de pourquoi ça a planté. Ensuite, tu déclares l'agent code fixer. Tu peux lui assigner un modèle spécifiquement optimisé pour la génération de code. Ses instructions lui disent strictement de prendre une fonction qui plante et de générer en output une version corrigée. Pas d'analyse de logs, juste du code en input et du code en output. Quand tu fais tourner cette équipe, l'utilisateur interagit uniquement avec le root agent. Tu passes au root agent un énorme dump de logs applicatifs. Le root agent évalue la requête et lit les descriptions de ses sous-agents disponibles. Il détermine que l'investigateur de bugs est le bon agent pour la première étape. Le root agent fait descendre le dump de logs à l'investigateur. L'investigateur traite le bruit, trouve une null pointer exception dans une fonction spécifique, et retourne juste ce détail précis. Le root agent prend cette information isolée et la passe à l'agent code fixer. Le code fixer écrit le patch et le renvoie au root manager, qui te retourne ensuite le résultat final et propre. Voici le point clé. Le code fixer ne voit jamais l'énorme stack trace. Il voit uniquement la fonction exacte qu'il doit corriger. Tu protèges la context window du modèle de code en filtrant le bruit en amont. En assignant des instructions strictes et spécifiques aux sous-agents individuels dans le fichier YAML, tu empêches les modèles de s'éloigner de leur tâche. Le root agent gère la séquence, et les sous-agents gèrent l'exécution. Structurer les agents de manière hiérarchique te force à traiter l'IA comme une architecture microservices, en assignant des limites strictes à ce dont un modèle individuel a le droit de se soucier. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
17

Toolsets et workflows d'agents

3m 45s

Rendez vos agents IA réellement utiles en leur donnant les bonnes contraintes. Apprenez à configurer des toolsets de système de fichiers et à imposer des workflows de développement structurés dans Docker Agent.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 17 sur 18. Un agent IA avec le language model le plus avancé est pratiquement inutile pour le développement s'il ne peut pas lire ton code source ou exécuter ta test suite. Sans capacités externes, il ne fait que deviner la syntaxe. Les toolsets et les workflows pour agents résolvent ce problème en comblant le fossé entre un simple générateur de texte et un software engineer opérationnel. Par défaut, un agent Docker tourne dans un container isolé. Il n'a aucune idée des fichiers qui existent dans le directory de ton projet. Pour changer ça, tu configures l'array toolsets dans le fichier YAML de ton agent. Les toolsets sont des capacités pré-packagées qui donnent à l'agent un accès direct à son environnement host. Pour un agent de développement, tu injectes généralement deux toolsets principaux : l'accès au filesystem et l'accès au shell. Le toolset filesystem permet à l'agent de lire ton directory tree, d'ouvrir les fichiers sources et d'écrire du code sur le disque. Le toolset shell permet à l'agent de lancer des commandes dans le terminal. Sans l'array toolsets, ton agent est coincé dans une boîte. Avec, ton agent a des mains et des yeux. Cependant, donner des mains et des yeux à un agent est la recette du chaos s'il manque de discipline. Un agent non structuré pourrait modifier un fichier, supposer que ça a marché, et signaler un succès sans jamais vérifier les erreurs de syntaxe. Tu contrôles ce comportement en utilisant le bloc instructions dans le fichier YAML. Ce bloc n'est pas fait pour des suggestions vagues. C'est là que tu définis un workflow opérationnel strict. La façon la plus fiable de structurer ces instructions, c'est de diviser les tâches de l'agent en quatre phases obligatoires : Analyze, Examine, Modify, et Validate. Tu les écris directement dans le bloc instructions, en disant à l'agent qu'il doit terminer une phase avant de passer à la suivante. D'abord, Analyze. L'agent lit le prompt de l'utilisateur pour comprendre la feature demandée ou le bug fix. Ensuite, Examine. Là, tu dis à l'agent d'utiliser son toolset filesystem pour fouiller ta codebase, trouver les fichiers pertinents, et lire leur contenu pour comprendre la logique actuelle. Troisièmement, Modify. L'agent écrit le code mis à jour sur le disque. C'est la partie qui compte. La quatrième phase, c'est Validate. C'est là que tu forces l'agent à prouver son travail en utilisant le toolset shell. Prends l'exemple d'un agent expert en développement Go. Dans la section Validate de tes instructions, tu exiges explicitement que l'agent lance la commande go test dot slash dot dot dot, suivie de golangci dash lint run. Comme l'agent a un accès shell, il exécute exactement ces commandes. Si le compiler Go lève une erreur de syntaxe, ou si un test échoue, le toolset renvoie cet output du terminal directement à l'agent. Comme tes instructions précisent que la tâche n'est pas terminée tant que la validation ne passe pas, l'agent est forcé de lire l'erreur, de retourner à la phase Modify, de corriger le code, et de relancer les tests. Il va répéter ce cycle jusqu'à ce que le linter soit content et que les tests passent. Donner accès au filesystem et au shell rend ton agent capable d'écrire du software. Mais structurer ses instructions pour exiger l'exécution explicite des tests rend ton agent fiable. Tu lies ses tools à une boucle de validation stricte pour ne jamais avoir à revoir du code cassé. C'est tout pour cette fois. Merci de m'avoir écouté, et continue de développer !
18

Les modèles d'IA dans Compose

3m 13s

Traitez vos LLMs locaux comme n'importe quelle autre dépendance d'application. Apprenez à déclarer, configurer et lier des modèles d'IA directement dans votre fichier YAML Docker Compose.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Masterclass Docker, épisode 18 sur 18. Ton application dépend d'un Large Language Model local. Tu démarres probablement un moteur d'inférence externe, tu configures le réseau manuellement et tu injectes les URL des endpoints à la main. Ça marche, mais ça casse la reproductibilité isolée de ton environnement. Ton modèle d'IA est juste une dépendance comme une autre, et il a sa place dans ton fichier de configuration, juste à côté de ta base de données. C'est exactement ce que fait l'élément models top-level dans Docker Compose. À partir de la version 2.38 de Compose, les models sont un concept natif. Avant, faire tourner un modèle local, ça voulait dire écrire des définitions de service complexes pour un moteur d'inférence, exposer manuellement les ports, et configurer des bridges réseau pour que le conteneur de ton application puisse lui parler. Le nouveau bloc models élimine cette friction en traitant le modèle d'IA comme un élément d'infrastructure distinct. Tu ajoutes un bloc models tout en haut de ton fichier, avec la même indentation que services et volumes. À l'intérieur, tu donnes un nom à ton modèle. Utilisons ai/smollm2 pour une simple application de chat. Sous ce nom, tu déclares l'identifiant exact du modèle à pull. C'est aussi là que tu définis les contraintes matérielles et les paramètres du moteur. Tu peux définir la taille du contexte pour restreindre l'utilisation de la mémoire. Si le moteur sous-jacent a besoin de paramètres de lancement spécifiques, tu les définis en utilisant des flags au runtime. La configuration du modèle est isolée et claire. Ensuite, tu bindes ton application au modèle. Dans ton bloc services, tu repères le service de ton app de chat et tu ajoutes un array models. En utilisant la syntaxe courte, tu listes simplement ai/smollm2. Tu n'as pas besoin de configurer les dépendances manuellement ou de mettre en place des alias réseau personnalisés. Voici le point clé. Quand tu utilises cette syntaxe de binding courte, Compose prend le relais sur l'orchestration. Il provisionne le bon moteur d'inférence en arrière-plan pour servir le modèle que tu as spécifié. Plus important encore, il auto-génère les variables d'environnement standards et les injecte directement dans le conteneur de ton application de chat. Ton code se réveille avec des variables comme OPENAI_BASE_URL déjà remplies, qui pointent parfaitement vers l'endpoint interne du modèle. Tu exécutes une seule commande docker compose up. Compose pull le modèle smollm2, configure le moteur, démarre ton service de chat et câble la connexion. Pas de clés API manuelles, pas besoin de deviner les adresses IP internes. Tout est routé correctement out of the box. Je t'encourage à explorer la documentation officielle et à essayer d'écrire un de ces fichiers toi-même. Comme ça vient clôturer notre série de masterclass, n'hésite pas à visiter devstories dot eu pour suggérer des sujets pour ce qu'on couvrira ensuite. En élevant les modèles d'IA au rang d'éléments natifs dans ta configuration, ton infrastructure devient entièrement déclarative, ce qui garantit que la version exacte du modèle que ton code attend est toujours celle qui démarre. C'est tout pour aujourd'hui. Merci d'avoir écouté, va construire un truc cool.