<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on kenji.blog</title><link>http://kenji.blog/fr/tags/docker/</link><description>Recent content in Docker on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 01:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>Étapes pour construire un environnement de développement local reproductible avec Docker</title><link>http://kenji.blog/fr/p/docker-reproducible-local-dev-environment/</link><pubDate>Sun, 13 Sep 2026 01:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/docker-reproducible-local-dev-environment/</guid><description>&lt;img src="http://kenji.blog/p/docker-reproducible-local-dev-environment/img/eyecatch.jpg" alt="Featured image of post Étapes pour construire un environnement de développement local reproductible avec Docker" />&lt;h2 id="1-introduction--sortir-du--ça-marche-sur-ma-machine-">1. Introduction : Sortir du « Ça marche sur ma machine »
&lt;/h2>&lt;p>Dans le développement logiciel, le problème du « Ça marche sur ma machine » (It works on my machine), dû aux différences d&amp;rsquo;environnements entre les développeurs, est depuis longtemps un facteur de perte de temps dans de nombreux projets. En raison des différences de systèmes d&amp;rsquo;exploitation, de versions de langages installées, des dépendances de bibliothèques, ou des conflits d&amp;rsquo;outils installés globalement, l&amp;rsquo;environnement local est toujours exposé à une « incertitude d&amp;rsquo;état ».&lt;/p>
&lt;p>Ce qui résout fondamentalement ces défis, c&amp;rsquo;est la technologie des conteneurs, notamment &lt;strong>Docker&lt;/strong>, et le paradigme d&amp;rsquo;&lt;strong>Infrastructure as Code (IaC)&lt;/strong>. Conteneuriser l&amp;rsquo;environnement de développement local permet une isolation au niveau du système d&amp;rsquo;exploitation et de versionner l&amp;rsquo;environnement lui-même avec la base de code.&lt;/p>
&lt;p>Cet article explique en détail, avec des perspectives mathématiques, la méthode pour construire &lt;strong>« un environnement de développement local reproductible qui reste exactement le même peu importe qui, quand, et sur quelle machine il est lancé »&lt;/strong>, en tirant parti de Docker, Docker Compose, et VSCode DevContainers.&lt;/p>
&lt;hr>
&lt;h2 id="2-affinité-entre-linfrastructure-as-code-iac-et-la-technologie-des-conteneurs">2. Affinité entre l&amp;rsquo;Infrastructure as Code (IaC) et la technologie des conteneurs
&lt;/h2>&lt;h3 id="principes-de-liac-et-son-application-à-lenvironnement-local">Principes de l&amp;rsquo;IaC et son application à l&amp;rsquo;environnement local
&lt;/h3>&lt;p>L&amp;rsquo;Infrastructure as Code (IaC) est une approche qui gère la configuration et le provisionnement de l&amp;rsquo;infrastructure via des fichiers de définition lisibles par machine, plutôt que par un processus manuel. Les principes fondamentaux de l&amp;rsquo;IaC incluent :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Approche déclarative (Declarative Approach)&lt;/strong> : On définit « quel devrait être l&amp;rsquo;état final » plutôt que « comment changer l&amp;rsquo;état ».&lt;/li>
&lt;li>&lt;strong>Idempotence (Idempotency)&lt;/strong> : Quel que soit le nombre d&amp;rsquo;exécutions du script, le même résultat (état) est toujours garanti.&lt;/li>
&lt;li>&lt;strong>Contrôle de version (Version Control)&lt;/strong> : L&amp;rsquo;état de l&amp;rsquo;infrastructure est stocké sous forme de code dans des systèmes comme Git, ce qui permet le suivi de l&amp;rsquo;historique et la revue par les pairs.&lt;/li>
&lt;/ol>
&lt;p>Pratiquer l&amp;rsquo;IaC dans un environnement de développement local signifie coder « l&amp;rsquo;état idéal » de l&amp;rsquo;environnement de développement à l&amp;rsquo;aide de &lt;code>Dockerfile&lt;/code>, &lt;code>docker-compose.yml&lt;/code>, et &lt;code>devcontainer.json&lt;/code>. Cela permet aux nouveaux membres de l&amp;rsquo;équipe de commencer immédiatement le développement en clonant simplement le dépôt et en exécutant une seule commande, offrant ainsi une excellente expérience d&amp;rsquo;intégration (onboarding).&lt;/p>
&lt;h3 id="fonctionnalités-du-noyau-derrière-la-technologie-des-conteneurs">Fonctionnalités du noyau derrière la technologie des conteneurs
&lt;/h3>&lt;p>Contrairement à la virtualisation par hyperviseur comme les machines virtuelles (VM), la technologie des conteneurs est une technologie de virtualisation légère qui isole les processus tout en partageant le noyau du système d&amp;rsquo;exploitation hôte. Pour y parvenir, les fonctionnalités suivantes du noyau Linux sont principalement utilisées :&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Namespaces&lt;/strong> : Fournissent une vue isolée des ressources système (PID, réseau, points de montage, utilisateurs, etc.) pour chaque processus.&lt;/li>
&lt;li>&lt;strong>Cgroups (Control Groups)&lt;/strong> : Limitent et allouent les ressources physiques (CPU, mémoire, E/S disque, etc.) qu&amp;rsquo;un processus peut utiliser.&lt;/li>
&lt;li>&lt;strong>UnionFS (Union File System)&lt;/strong> : Technologie permettant de superposer de manière transparente plusieurs arborescences de répertoires (couches) et de les présenter comme un système de fichiers unique. Les couches d&amp;rsquo;images Docker reposent sur cette technologie.&lt;/li>
&lt;/ul>
&lt;p>Considérons un modèle mathématique de limitation de ressources. Soit $M_{\text{total}}$ la capacité de mémoire totale de la machine hôte et $m_i$ la limite de mémoire pour $n$ conteneurs s&amp;rsquo;exécutant sur l&amp;rsquo;hôte. En tenant compte de la mémoire de base $M_{\text{os}}$ consommée par l&amp;rsquo;OS hôte et d&amp;rsquo;autres processus, la condition nécessaire au fonctionnement stable du système peut être exprimée par l&amp;rsquo;inégalité suivante :&lt;/p>
$$ \sum_{i=1}^{n} m_i \le M_{\text{total}} - M_{\text{os}} $$&lt;p>En définissant strictement $m_i$ pour chaque conteneur à l&amp;rsquo;aide de Cgroups, même si un conteneur spécifique présente une fuite de mémoire, l&amp;rsquo;OOM (Out Of Memory) Killer empêchera les autres conteneurs et l&amp;rsquo;ensemble du système hôte de tomber en panne.&lt;/p>
&lt;hr>
&lt;h2 id="3-conception-efficace-de-dockerfile--maîtriser-les-builds-multi-étapes">3. Conception efficace de Dockerfile : Maîtriser les builds multi-étapes
&lt;/h2>&lt;p>La première étape vers un environnement reproductible est la conception du &lt;code>Dockerfile&lt;/code>, qui définit l&amp;rsquo;environnement d&amp;rsquo;exécution de l&amp;rsquo;application. Ici, en utilisant Python (FastAPI) comme exemple, nous expliquons les meilleures pratiques pour des Dockerfiles sécurisés et légers utilisant des &lt;strong>builds multi-étapes&lt;/strong> (multi-stage builds).&lt;/p>
&lt;p>Le build multi-étapes est une technique qui utilise plusieurs instructions &lt;code>FROM&lt;/code> dans un seul &lt;code>Dockerfile&lt;/code> pour séparer l&amp;rsquo;environnement de construction (un environnement lourd avec compilateurs et outils de développement) de l&amp;rsquo;environnement d&amp;rsquo;exécution (un environnement léger avec seulement les artefacts nécessaires).&lt;/p>
&lt;h3 id="dockerfile-pratique-pour-python-fastapi">Dockerfile pratique pour Python FastAPI
&lt;/h3>&lt;p>Le code suivant est un exemple de &lt;code>Dockerfile&lt;/code> avancé combinant la gestion des dépendances avec Poetry et les builds multi-étapes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># ---------------------------------------------------------&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Stage 1: Builder (Environnement de construction)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ---------------------------------------------------------&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="s"> python:3.11-slim AS builder&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Configuration des variables d&amp;#39;environnement nécessaires&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PYTHONUNBUFFERED&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">PYTHONDONTWRITEBYTECODE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">POETRY_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span>.6.1 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">POETRY_HOME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/opt/poetry&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">POETRY_VIRTUALENVS_IN_PROJECT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">true&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">POETRY_NO_INTERACTION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Installation des paquets de dépendances&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y --no-install-recommends &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> curl build-essential &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> curl -sSL https://install.python-poetry.org &lt;span class="p">|&lt;/span> python3 - &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> apt-get clean &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> rm -rf /var/lib/apt/lists/*&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PATH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$POETRY_HOME&lt;/span>&lt;span class="s2">/bin:&lt;/span>&lt;span class="nv">$PATH&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> /app&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Copie des fichiers de dépendances et installation&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> pyproject.toml poetry.lock ./&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> poetry install --no-root --only main&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ---------------------------------------------------------&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Stage 2: Runtime (Environnement d&amp;#39;exécution)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ---------------------------------------------------------&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="s"> python:3.11-slim AS runtime&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PYTHONUNBUFFERED&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">PYTHONDONTWRITEBYTECODE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">PATH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/app/.venv/bin:&lt;/span>&lt;span class="nv">$PATH&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Création d&amp;#39;un utilisateur non privilégié minimal&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> groupadd -r appuser &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> useradd -r -g appuser appuser&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> /app&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Copier uniquement l&amp;#39;environnement virtuel (dépendances) depuis le constructeur&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> --from&lt;span class="o">=&lt;/span>builder --chown&lt;span class="o">=&lt;/span>appuser:appuser /app/.venv /app/.venv&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Copie du code de l&amp;#39;application&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> --chown&lt;span class="o">=&lt;/span>appuser:appuser ./src /app/src&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Passer à l&amp;#39;utilisateur non privilégié&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">USER&lt;/span>&lt;span class="s"> appuser&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Commande par défaut au lancement du conteneur&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENTRYPOINT&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;uvicorn&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;src.main:app&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;--host&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;0.0.0.0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;--port&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;8000&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="évaluation-mathématique-de-la-taille-de-limage-grâce-au-build-multi-étapes">Évaluation mathématique de la taille de l&amp;rsquo;image grâce au build multi-étapes
&lt;/h3>&lt;p>Soit $S_{\text{single}}$ la taille de l&amp;rsquo;image avec un build à une étape, et $S_{\text{multi}}$ la taille avec un build multi-étapes. Le taux de réduction de taille $R$ est calculé comme suit :&lt;/p>
$$ R = \left( 1 - \frac{S_{\text{multi}}}{S_{\text{single}}} \right) \times 100 \ (\%) $$&lt;p>Par exemple, supposons que $S_{\text{single}}$ comprenne l&amp;rsquo;image de base de l&amp;rsquo;OS (environ 110 Mo), les paquets de développement (gcc etc., environ 150 Mo), Poetry lui-même (environ 40 Mo), les bibliothèques de dépendances du projet (environ 80 Mo) et le code source (environ 5 Mo), pour un total de 385 Mo.
D&amp;rsquo;autre part, $S_{\text{multi}}$ ne copie que les bibliothèques (80 Mo) et le code source (5 Mo) dans l&amp;rsquo;image de base (110 Mo), ce qui donne un total de 195 Mo.&lt;/p>
$$ R = \left( 1 - \frac{195}{385} \right) \times 100 \approx 49.35\% $$&lt;p>Ainsi, en introduisant le build multi-étapes, la taille de l&amp;rsquo;image peut être réduite d&amp;rsquo;environ la moitié. La réduction de la taille de l&amp;rsquo;image est directement liée à des temps de téléchargement (pull) plus courts depuis le registre, des économies d&amp;rsquo;espace disque, et une sécurité améliorée grâce à la réduction de la surface d&amp;rsquo;attaque (Attack Surface).&lt;/p>
&lt;hr>
&lt;h2 id="4-orchestration-de-plusieurs-conteneurs-avec-docker-compose">4. Orchestration de plusieurs conteneurs avec Docker Compose
&lt;/h2>&lt;p>Dans le développement d&amp;rsquo;applications Web modernes, il est courant d&amp;rsquo;avoir une architecture de microservices où plusieurs composants tels qu&amp;rsquo;un serveur Web, une base de données, et un serveur de cache interagissent. Pour gérer cela de manière centralisée dans un environnement local, nous utilisons &lt;code>docker-compose.yml&lt;/code>.&lt;/p>
&lt;p>Cette fois, nous allons construire localement un système à 3 couches : « Web (FastAPI) », « Database (PostgreSQL) », et « Cache (Redis) ».&lt;/p>
&lt;h3 id="diagramme-darchitecture-mermaid">Diagramme d&amp;rsquo;architecture (Mermaid)
&lt;/h3>&lt;p>Le diagramme suivant illustre la relation entre les conteneurs, le réseau, et les volumes sur la machine locale.&lt;/p>
&lt;pre class="mermaid">
graph TD
User[&amp;#34;Machine Hôte (Navigateur/curl)&amp;#34;] --&amp;gt;|Localhost:8000| Web[&amp;#34;Conteneur Web FastAPI&amp;#34;]
subgraph &amp;#34;Réseau Bridge Docker (app-network)&amp;#34;
Web --&amp;gt;|Port 5432| DB[&amp;#34;Conteneur PostgreSQL&amp;#34;]
Web --&amp;gt;|Port 6379| Redis[&amp;#34;Conteneur Redis&amp;#34;]
end
DB --&amp;gt; Volume1[&amp;#34;Volume Nommé (postgres_data)&amp;#34;]
Redis --&amp;gt; Volume2[&amp;#34;Volume Nommé (redis_data)&amp;#34;]
HostDir[&amp;#34;Code Source Hôte (./src)&amp;#34;] -.-&amp;gt;|Bind Mount| Web
&lt;/pre>
&lt;h3 id="implémentation-de-docker-composeyml-et-explications-détaillées">Implémentation de docker-compose.yml et explications détaillées
&lt;/h3>&lt;p>Voici un exemple de &lt;code>docker-compose.yml&lt;/code> robuste adapté à un environnement pratique.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.8&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">web&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">build&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">context&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">target&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">runtime&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">dev_web&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;8000:8000&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./src:/app/src:ro &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Monter le code de l&amp;#39;hôte en lecture seule (pour le rechargement à chaud)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">REDIS_URL=redis://redis:6379/0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">env_file&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">.env&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">depends_on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">db&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">condition&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">service_healthy&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">redis&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">condition&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">service_started&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">app-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;uvicorn&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;src.main:app&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;--host&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;0.0.0.0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;--port&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;8000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;--reload&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">db&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">postgres:15-alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">dev_db&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;5432:5432&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">POSTGRES_USER&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">postgres&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">POSTGRES_PASSWORD&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${POSTGRES_PASSWORD}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">POSTGRES_DB&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${POSTGRES_DB}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">postgres_data:/var/lib/postgresql/data&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">app-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">healthcheck&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">test&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;CMD-SHELL&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;pg_isready -U postgres -d ${POSTGRES_DB}&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">interval&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">5s&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">timeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">5s&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">retries&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">5&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">redis&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">redis:7-alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">dev_redis&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;6379:6379&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">redis_data:/data&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">app-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;redis-server&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;--appendonly&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;yes&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">postgres_data&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">redis_data&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app-network&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bridge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="volumes-et-persistance-des-données">Volumes et persistance des données
&lt;/h3>&lt;p>En principe, les conteneurs sont « stateless » (sans état) et « éphémères » (à courte durée de vie). Lorsqu&amp;rsquo;un conteneur est détruit, ses données internes sont également perdues. Pour conserver les données de base de données ou le cache, un espace système de fichiers de la machine hôte doit être monté dans le conteneur.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Bind Mount (Montage lié)&lt;/strong> : Dans le service &lt;code>web&lt;/code> ci-dessus, &lt;code>./src:/app/src:ro&lt;/code> y correspond. Il mappe directement un répertoire spécifique de l&amp;rsquo;hôte à l&amp;rsquo;intérieur du conteneur. Il est utilisé pour refléter immédiatement les modifications de code locales dans le conteneur (rechargement à chaud). Pour des raisons de sécurité, la meilleure pratique est d&amp;rsquo;ajouter l&amp;rsquo;option &lt;code>:ro&lt;/code> (Read-Only) afin que le conteneur ne puisse pas modifier le code source de l&amp;rsquo;hôte.&lt;/li>
&lt;li>&lt;strong>Named Volume (Volume nommé)&lt;/strong> : C&amp;rsquo;est le cas de &lt;code>postgres_data&lt;/code> ou &lt;code>redis_data&lt;/code>. C&amp;rsquo;est une zone gérée en interne par Docker (comme &lt;code>/var/lib/docker/volumes/&lt;/code>), qui a de meilleures performances d&amp;rsquo;E/S qu&amp;rsquo;un bind mount et qui absorbe les différences de systèmes de fichiers entre les OS. Il faut toujours l&amp;rsquo;utiliser pour la persistance de base de données.&lt;/li>
&lt;/ul>
&lt;h3 id="réseau-networking-et-découverte-de-services">Réseau (Networking) et découverte de services
&lt;/h3>&lt;p>Docker Compose crée par défaut un réseau pont (bridge) distinct pour chaque projet. Il s&amp;rsquo;agit du &lt;code>app-network&lt;/code> ci-dessus.
Les conteneurs appartenant au même réseau peuvent se résoudre (résolution DNS) via leur « nom de service » (par exemple : &lt;code>db&lt;/code>, &lt;code>redis&lt;/code>) plutôt que par leur adresse IP.
Par exemple, le conteneur Web peut accéder à la base de données via l&amp;rsquo;URL &lt;code>postgresql://postgres:password@db:5432/mydb&lt;/code>. Cela permet de changer de manière transparente de cible de connexion via des variables d&amp;rsquo;environnement entre les environnements locaux, de pré-production, et de production sans modifier le code de l&amp;rsquo;infrastructure.&lt;/p>
&lt;h3 id="bilan-de-santé-healthcheck-et-ordre-de-démarrage">Bilan de santé (Healthcheck) et ordre de démarrage
&lt;/h3>&lt;p>La directive &lt;code>depends_on&lt;/code> contrôle l&amp;rsquo;ordre de démarrage des conteneurs, mais si l&amp;rsquo;on spécifie simplement &lt;code>depends_on&lt;/code>, le conteneur Web démarrera dès que le conteneur DB sera « lancé ». En réalité, le processus d&amp;rsquo;initialisation de la DB (démarrage du processus PostgreSQL, préparation des tables) prend quelques secondes, et une connexion depuis le conteneur Web pendant ce temps résultera en une erreur.
Pour éviter cela, nous définissons un &lt;code>healthcheck&lt;/code> et spécifions &lt;code>condition: service_healthy&lt;/code>, ce qui permet de s&amp;rsquo;assurer que la « DB est prête à accepter les requêtes de connexion » avant de démarrer le conteneur Web.&lt;/p>
&lt;hr>
&lt;h2 id="5-gestion-des-variables-denvironnement-et-sécurité-env">5. Gestion des variables d&amp;rsquo;environnement et sécurité (.env)
&lt;/h2>&lt;p>C&amp;rsquo;est un anti-pattern à éviter absolument que de coder en dur des informations sensibles telles que les mots de passe de bases de données ou les clés d&amp;rsquo;API dans &lt;code>docker-compose.yml&lt;/code>. À la place, utilisez un fichier de variables d&amp;rsquo;environnement &lt;code>.env&lt;/code> pour injecter ces valeurs.&lt;/p>
&lt;p>Créez un fichier &lt;code>.env&lt;/code> à la racine du projet.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Fichier .env (Assurez-vous de l&amp;#39;ajouter à .gitignore pour l&amp;#39;exclure de Git)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">POSTGRES_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">supersecretpassword&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">POSTGRES_DB&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">devdb&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">API_SECRET_KEY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">dev_secret_key_12345&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Docker Compose charge par défaut le fichier &lt;code>.env&lt;/code> dans le répertoire d&amp;rsquo;exécution et développe les espaces réservés &lt;code>${VAR_NAME}&lt;/code> dans les fichiers YAML. Cette méthode permet de gérer en toute sécurité différentes valeurs de configuration pour des environnements tels que le local, la pré-production, et la production, sans modifier le code de l&amp;rsquo;infrastructure.&lt;/p>
&lt;hr>
&lt;h2 id="6-lexpérience-de-développement-ultime-avec-vscode-devcontainers">6. L&amp;rsquo;expérience de développement ultime avec VSCode DevContainers
&lt;/h2>&lt;p>À ce stade, nous avons construit un environnement backend robuste à l&amp;rsquo;aide de Docker. Cependant, nous pouvons aller encore plus loin. En utilisant la fonctionnalité &lt;strong>VSCode DevContainers (Remote - Containers)&lt;/strong>, il est possible d&amp;rsquo;exécuter le backend de l&amp;rsquo;éditeur (VSCode) lui-même à l&amp;rsquo;intérieur du conteneur.&lt;/p>
&lt;p>Cela élimine le besoin d&amp;rsquo;installer Python ou Node.js sur la machine locale. Les linters (flake8/eslint), les formateurs (black/prettier) et même les extensions de l&amp;rsquo;IDE, tout peut être défini dans la base de code et partagé avec tous les membres de l&amp;rsquo;équipe.&lt;/p>
&lt;h3 id="configuration-de-devcontainerjson">Configuration de devcontainer.json
&lt;/h3>&lt;p>Créez un répertoire &lt;code>.devcontainer&lt;/code> à la racine du projet, et placez-y le fichier de configuration.&lt;/p>
&lt;p>&lt;code>.devcontainer/devcontainer.json&lt;/code> :&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Python FastAPI Dev Environment&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;dockerComposeFile&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;../docker-compose.yml&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;service&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;web&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;workspaceFolder&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/app&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;customizations&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;vscode&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;settings&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;python.defaultInterpreterPath&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/app/.venv/bin/python&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;python.formatting.provider&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;black&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;editor.formatOnSave&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;extensions&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;ms-python.python&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;ms-python.vscode-pylance&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;ms-python.black-formatter&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;tamasfe.even-better-toml&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;forwardPorts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">8000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5432&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">6379&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;remoteUser&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;appuser&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;postCreateCommand&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;poetry install&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En incluant ce fichier dans le dépôt, dès l&amp;rsquo;ouverture du projet dans VSCode, une invite « Reopen in Container » (Rouvrir dans le conteneur) apparaît. D&amp;rsquo;un simple clic, tous les conteneurs nécessaires démarrent, les extensions sont installées, et vous êtes immédiatement prêt à coder. C&amp;rsquo;est une expérience véritablement magique.&lt;/p>
&lt;hr>
&lt;h2 id="7-séquence-de-traitement-des-requêtes-et-modélisation-des-performances">7. Séquence de traitement des requêtes et modélisation des performances
&lt;/h2>&lt;p>Examinons le cycle de vie du traitement d&amp;rsquo;une requête d&amp;rsquo;application Web dans l&amp;rsquo;environnement de développement local à l&amp;rsquo;aide d&amp;rsquo;un diagramme de séquence, puis analysons le modèle mathématique de ses performances.&lt;/p>
&lt;h3 id="diagramme-de-séquence-flux-de-requête">Diagramme de séquence (Flux de requête)
&lt;/h3>&lt;pre class="mermaid">
sequenceDiagram
participant Client as &amp;#34;Navigateur / VSCode&amp;#34;
participant Web as &amp;#34;FastAPI (Web)&amp;#34;
participant Redis as &amp;#34;Cache Redis&amp;#34;
participant DB as &amp;#34;PostgreSQL&amp;#34;
Client-&amp;gt;&amp;gt;Web: &amp;#34;GET /api/users/123&amp;#34;
activate Web
Web-&amp;gt;&amp;gt;Redis: &amp;#34;Vérifier le cache pour user:123&amp;#34;
activate Redis
alt &amp;#34;Succès du cache (Données présentes)&amp;#34;
Redis--&amp;gt;&amp;gt;Web: &amp;#34;Retourner les données utilisateur en cache&amp;#34;
Web--&amp;gt;&amp;gt;Client: &amp;#34;200 OK (Réponse rapide)&amp;#34;
else &amp;#34;Échec du cache (Aucune donnée)&amp;#34;
Redis--&amp;gt;&amp;gt;Web: &amp;#34;Nul (Non trouvé)&amp;#34;
deactivate Redis
Web-&amp;gt;&amp;gt;DB: &amp;#34;SELECT * FROM users WHERE id = 123&amp;#34;
activate DB
DB--&amp;gt;&amp;gt;Web: &amp;#34;Retourner la ligne de la base de données&amp;#34;
deactivate DB
Web-&amp;gt;&amp;gt;Redis: &amp;#34;Définir les données user:123 (TTL: 60s)&amp;#34;
activate Redis
Redis--&amp;gt;&amp;gt;Web: &amp;#34;OK&amp;#34;
deactivate Redis
Web--&amp;gt;&amp;gt;Client: &amp;#34;200 OK (Réponse standard)&amp;#34;
end
deactivate Web
&lt;/pre>
&lt;h3 id="modèle-mathématique-de-la-latence-de-traitement">Modèle mathématique de la latence de traitement
&lt;/h3>&lt;p>Nous modélisons mathématiquement le temps de traitement moyen des requêtes $T_{\text{total}}$ dans le système ci-dessus.
La latence de chaque processus est définie comme suit :&lt;/p>
&lt;ul>
&lt;li>$T_{\text{net}}$ : Latence réseau entre le client et le conteneur Web&lt;/li>
&lt;li>$T_{\text{app}}$ : Temps de traitement pur côté application (sérialisation, etc.)&lt;/li>
&lt;li>$T_{\text{cache}}$ : Temps requis pour la lecture/écriture depuis Redis&lt;/li>
&lt;li>$T_{\text{db}}$ : Temps requis pour l&amp;rsquo;exécution des requêtes vers PostgreSQL&lt;/li>
&lt;li>$p_{\text{miss}}$ : Taux d&amp;rsquo;échec du cache ($0 \le p_{\text{miss}} \le 1$)&lt;/li>
&lt;/ul>
&lt;p>Le temps de réponse moyen est exprimé par l&amp;rsquo;équation d&amp;rsquo;espérance mathématique suivante :&lt;/p>
$$ T_{\text{total}} = T_{\text{net}} + T_{\text{app}} + T_{\text{cache}} + p_{\text{miss}} \times (T_{\text{db}} + T_{\text{cache\_write}}) $$&lt;p>Dans l&amp;rsquo;environnement de développement local (dans Docker), $T_{\text{net}}$ est proche de 0, mais ce qui requiert notre attention, ce sont &lt;strong>les performances d&amp;rsquo;E/S du bind mount&lt;/strong>. En particulier, lors de l&amp;rsquo;utilisation de Docker Desktop sous Windows/macOS, la surcharge de partage de fichiers entre l&amp;rsquo;OS hôte et la VM (conteneur) a tendance à gonfler $T_{\text{app}}$ (comme les temps de lecture du code). Pour résoudre ce goulot d&amp;rsquo;étranglement, il est fortement recommandé d&amp;rsquo;utiliser DevContainers pour placer l&amp;rsquo;intégralité du code source dans un volume nommé, ou d&amp;rsquo;adopter une architecture exécutant le moteur Docker de manière native dans l&amp;rsquo;environnement WSL2 (Windows Subsystem for Linux 2).&lt;/p>
&lt;hr>
&lt;h2 id="8-optimisation-des-performances-de-build-docker--stratégie-de-mise-en-cache-des-couches">8. Optimisation des performances de build Docker : Stratégie de mise en cache des couches
&lt;/h2>&lt;p>Lorsque vous rédigez un Dockerfile, comprendre le mécanisme de « cache de couche » (layer cache) peut considérablement modifier le temps de build.
Docker crée un delta du système de fichiers (une couche) pour chaque instruction du Dockerfile (&lt;code>FROM&lt;/code>, &lt;code>RUN&lt;/code>, &lt;code>COPY&lt;/code>, etc.) et la conserve comme cache. Lors d&amp;rsquo;une nouvelle construction, le cache des couches inchangées est réutilisé.&lt;/p>
&lt;p>Le principe clé est de &lt;strong>« décrire dans l&amp;rsquo;ordre de la fréquence de modification la plus faible »&lt;/strong>.&lt;/p>
&lt;p>Considérons la modélisation de l&amp;rsquo;impact des modifications du code source sur le temps de build. Soit $T_{\text{build}}$ le temps de build total, $T_{\text{layer}_i}$ le temps d&amp;rsquo;exécution de chaque étape, et $c_i \in \{0, 1\}$ la valeur booléenne indiquant si le cache a été utilisé (1 en cas de succès du cache).&lt;/p>
$$ T_{\text{build}} = T_{\text{init}} + \sum_{i=1}^{n} (1 - c_i) \times T_{\text{layer}_i} $$&lt;p>Une fois qu&amp;rsquo;un échec de cache survient à la couche $k$ ($c_k = 0$), le cache est invalidé pour toutes les couches suivantes $j > k$ ($c_j = 0$).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Mauvais exemple (Copie du code source en premier)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> ./src /app/src&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> pyproject.toml poetry.lock ./&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> poetry install&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dans ce cas, modifier une seule ligne de code invalidera le cache dès le premier &lt;code>COPY&lt;/code>, ce qui entraînera l&amp;rsquo;exécution longue de &lt;code>RUN poetry install&lt;/code> à chaque fois.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Bon exemple (Résolution des dépendances en premier)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> pyproject.toml poetry.lock ./&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> poetry install&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> ./src /app/src&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En écrivant ainsi, même si le code source change, le cache de la couche &lt;code>poetry install&lt;/code> ($c_i = 1$) est effectif, réduisant considérablement le temps de build, passant de plusieurs minutes à quelques secondes.&lt;/p>
&lt;hr>
&lt;h2 id="9-dépannage-et-conseils">9. Dépannage et conseils
&lt;/h2>&lt;p>Voici des problèmes fréquents rencontrés lors de l&amp;rsquo;utilisation d&amp;rsquo;un environnement local et leurs solutions.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Erreur de conflit de port&lt;/strong>
Si vous obtenez une erreur telle que &lt;code>Bind for 0.0.0.0:8000 failed: port is already allocated&lt;/code>, c&amp;rsquo;est qu&amp;rsquo;un autre processus sur la machine locale utilise ce port. Vous pouvez éviter cela en changeant le numéro de port côté hôte, comme &lt;code>ports: - &amp;quot;8080:8000&amp;quot;&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Épuisement de l&amp;rsquo;espace disque&lt;/strong>
L&amp;rsquo;utilisation de Docker sur une longue période peut accumuler des images et volumes inutilisés (Dangling Images / Volumes), occupant parfois des dizaines de Go d&amp;rsquo;espace disque. Il est recommandé de nettoyer périodiquement le système avec la commande suivante :&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker system prune -a --volumes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Problème de permissions de fichiers&lt;/strong>
Lors de l&amp;rsquo;utilisation de bind mounts sous Linux, le propriétaire des fichiers créés dans le conteneur peut devenir &lt;code>root&lt;/code>, les rendant non modifiables côté hôte. Vous pouvez résoudre cela en créant un utilisateur non privilégié dans le Dockerfile dont l&amp;rsquo;UID/GID (par ex. 1000:1000) correspond à celui de votre système d&amp;rsquo;exploitation hôte.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="10-conclusion--lamélioration-de-la-vitesse-de-développement-grâce-à-la-reproductibilité">10. Conclusion : L&amp;rsquo;amélioration de la vitesse de développement grâce à la reproductibilité
&lt;/h2>&lt;p>La combinaison de Docker, Docker Compose et VSCode DevContainers permet de créer un environnement de développement local robuste, de sorte que « peu importe qui lance l&amp;rsquo;environnement, l&amp;rsquo;état sera exactement le même ».&lt;/p>
&lt;p>Apporter le paradigme de l&amp;rsquo;IaC à l&amp;rsquo;environnement local ne se limite pas à raccourcir le temps de configuration initial. Il élimine les craintes liées aux modifications de la configuration de l&amp;rsquo;infrastructure, facilite l&amp;rsquo;expérimentation de nouvelles piles technologiques et permet une transition en douceur vers les pipelines CI/CD, améliorant considérablement la vitesse et la qualité globales du cycle de développement.&lt;/p>
&lt;p>N&amp;rsquo;hésitez pas à introduire les meilleures pratiques abordées dans cet article, telles que l&amp;rsquo;optimisation de la taille de l&amp;rsquo;image via le build multi-étapes, le contrôle des dépendances avec les bilans de santé, et l&amp;rsquo;écriture de Dockerfile tenant compte du cache des couches, afin d&amp;rsquo;offrir la meilleure expérience de développement (DX: Developer Experience) à vos propres projets.&lt;/p></description></item><item><title>Le guide ultime de configuration de l'environnement de développement pour WSL2 (Windows Subsystem for Linux)</title><link>http://kenji.blog/fr/p/wsl2-ultimate-development-setup-guide/</link><pubDate>Sat, 12 Sep 2026 23:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/wsl2-ultimate-development-setup-guide/</guid><description>&lt;img src="http://kenji.blog/p/wsl2-ultimate-development-setup-guide/img/eyecatch.jpg" alt="Featured image of post Le guide ultime de configuration de l'environnement de développement pour WSL2 (Windows Subsystem for Linux)" />&lt;p>WSL2 (Windows Subsystem for Linux 2), qui offre un environnement de développement Linux natif sur Windows, est devenu un outil indispensable dans le développement de logiciels moderne. Cependant, il y a un monde de différence en termes de performances et d&amp;rsquo;expérience de développement entre l&amp;rsquo;utiliser dans son état par défaut et le régler de manière appropriée en comprenant son architecture.&lt;/p>
&lt;p>Dans cet article, nous expliquerons de manière exhaustive, avec plus de 10 000 caractères, toutes les étapes pour construire l&amp;rsquo;« environnement de développement ultime » exigé par les ingénieurs professionnels, en commençant par l&amp;rsquo;explication de l&amp;rsquo;architecture fondamentale de WSL2, les paramètres pour maximiser les performances, la construction d&amp;rsquo;un environnement de terminal confortable, l&amp;rsquo;intégration transparente avec Docker et VS Code, et enfin les paramètres réseau avancés.&lt;/p>
&lt;hr>
&lt;h2 id="1-architecture-de-wsl2-et-évolution-par-rapport-à-wsl1">1. Architecture de WSL2 et évolution par rapport à WSL1
&lt;/h2>&lt;p>Afin de libérer tout le potentiel de WSL2, il est d&amp;rsquo;abord important de comprendre sa structure interne. L&amp;rsquo;approche pour exécuter des binaires Linux sur Windows est fondamentalement différente entre le premier WSL (WSL1) et WSL2.&lt;/p>
&lt;h3 id="wsl1--couche-de-traduction-des-appels-système">WSL1 : Couche de traduction des appels système
&lt;/h3>&lt;p>WSL1 a adopté un mécanisme qui traduisait les appels système Linux en API Windows NT en temps réel. Cela avait l&amp;rsquo;avantage d&amp;rsquo;une surcharge de ressources très faible, car aucune machine virtuelle (VM) n&amp;rsquo;était utilisée. Cependant, il était difficile d&amp;rsquo;émuler complètement les appels système complexes, tels que les opérations d&amp;rsquo;E/S du système de fichiers, ce qui entraînait des baisses de performances désespérantes, notamment dans les processus traitant un grand nombre de petits fichiers, comme &lt;code>npm install&lt;/code> de Node.js ou les opérations sur les dépôts Git.&lt;/p>
&lt;h3 id="wsl2--vm-utilitaire-légère-et-noyau-linux-complet">WSL2 : VM utilitaire légère et noyau Linux complet
&lt;/h3>&lt;p>Dans WSL2, l&amp;rsquo;architecture a été remaniée pour qu&amp;rsquo;un véritable noyau Linux, construit par Microsoft, s&amp;rsquo;exécute directement sur une &lt;strong>« VM utilitaire légère » qui utilise un sous-ensemble de l&amp;rsquo;architecture Hyper-V&lt;/strong>. Cela garantit une compatibilité à 100 % des appels système, et en utilisant un disque virtuel (VHDX) avec un système de fichiers natif Linux ext4, les performances d&amp;rsquo;E/S des fichiers ont été considérablement améliorées par rapport à WSL1.&lt;/p>
&lt;p>Le diagramme Mermaid suivant illustre la différence structurelle entre WSL1 et WSL2.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
subgraph &amp;#34;Environnement du système d&amp;#39;exploitation Windows&amp;#34;
A[&amp;#34;Noyau Windows NT&amp;#34;]
A --&amp;gt; F[&amp;#34;Système de fichiers NTFS (Lecteur C:)&amp;#34;]
end
subgraph &amp;#34;Architecture WSL2&amp;#34;
B[&amp;#34;Hyperviseur Hyper-V&amp;#34;]
B --&amp;gt; C[&amp;#34;VM utilitaire légère&amp;#34;]
C --&amp;gt; D[&amp;#34;Noyau Linux (Microsoft)&amp;#34;]
D --&amp;gt; E[&amp;#34;Espace utilisateur Ubuntu (glibc, bash, etc.)&amp;#34;]
D --&amp;gt; G[&amp;#34;Disque virtuel ext4 (.vhdx)&amp;#34;]
end
A -.-&amp;gt;|&amp;#34;Partage de fichiers réseau par le protocole Plan 9 (9P)&amp;#34;| D
style B fill:#f9f,stroke:#333,stroke-width:2px
style D fill:#bbf,stroke:#333,stroke-width:2px
&lt;/pre>
&lt;p>La leçon importante à tirer de cette structure est que &lt;strong>« l&amp;rsquo;accès aux fichiers côté Linux (dans le VHDX) est extrêmement rapide, mais l&amp;rsquo;accès aux fichiers côté Windows (&lt;code>/mnt/c/&lt;/code>) est très lent car il passe par le protocole 9P »&lt;/strong>. Le code source de vos projets doit toujours être placé dans le répertoire personnel côté WSL (&lt;code>~&lt;/code>).&lt;/p>
&lt;hr>
&lt;h2 id="2-analyse-mathématique-des-performances--pourquoi-wsl2-est-il-rapide-">2. Analyse mathématique des performances : Pourquoi WSL2 est-il rapide ?
&lt;/h2>&lt;p>Évaluons quantitativement l&amp;rsquo;amélioration des performances de WSL2 à l&amp;rsquo;aide d&amp;rsquo;un modèle mathématique. L&amp;rsquo;une des opérations les plus chronophages dans le développement de logiciels est le traitement impliquant des E/S pour un grand nombre de fichiers (ex. : installation de bibliothèques ou compilation).&lt;/p>
&lt;p>Le temps d&amp;rsquo;exécution global $T_{total}$ d&amp;rsquo;un traitement est exprimé par la somme du temps de calcul par le processeur $T_{compute}$ et du temps consacré aux E/S disque $T_{io}$.&lt;/p>
$$ T_{total} = T_{compute} + T_{io} $$&lt;p>Dans le cas de WSL1, une surcharge se produit lors de la conversion des opérations côté Linux en opérations NTFS, le temps d&amp;rsquo;E/S est donc modélisé comme suit. Ici, $n$ est le nombre d&amp;rsquo;opérations sur les fichiers, $t_{ntfs\_syscall}$ est le temps d&amp;rsquo;exécution de l&amp;rsquo;appel système côté Windows, et $t_{trans}$ est la surcharge de la couche de traduction.&lt;/p>
$$ T_{wsl1\_io} = \sum_{i=1}^{n} (t_{ntfs\_syscall_i} + t_{trans_i}) $$&lt;p>D&amp;rsquo;autre part, dans le cas de WSL2, le noyau émet directement des E/S vers le système de fichiers ext4, de sorte que la surcharge n&amp;rsquo;est qu&amp;rsquo;un très léger retard $t_{virt}$ dû à la virtualisation.&lt;/p>
$$ T_{wsl2\_io} = \sum_{i=1}^{n} (t_{ext4_i} + t_{virt_i}) $$&lt;p>Dans un système de fichiers classique, comme $t_{ext4} \ll t_{ntfs\_syscall} + t_{trans}$, lorsque $n$ est très grand (des dizaines à des centaines de milliers d&amp;rsquo;opérations sur les fichiers), la différence de temps d&amp;rsquo;E/S entre WSL1 et WSL2 augmente de manière exponentielle.&lt;/p>
&lt;p>De plus, si le taux de surcharge des calculs du processeur dans un environnement virtualisé est $\rho$, avec la dernière virtualisation assistée par matériel (Intel VT-x / AMD-V), il se situe autour de $\rho \approx 0.01 \sim 0.03$ (1 à 3 %). Par conséquent, même dans des tâches purement de calcul, des performances comparables à un environnement Linux natif de $97\% \sim 99\%$ sont atteintes.&lt;/p>
&lt;hr>
&lt;h2 id="3-installation-et-construction-des-bases">3. Installation et construction des bases
&lt;/h2>&lt;p>Sur Windows 10/11, l&amp;rsquo;installation de WSL2 est devenue très simple. Il suffit d&amp;rsquo;ouvrir PowerShell avec les privilèges d&amp;rsquo;administrateur et d&amp;rsquo;exécuter la commande suivante.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># WSL2 et Ubuntu sont installés par défaut&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-install&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Pour spécifier une distribution particulière&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Peut être vérifié avec wsl --list --online&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-install&lt;/span> &lt;span class="n">-d&lt;/span> &lt;span class="n">Ubuntu&lt;/span>&lt;span class="p">-&lt;/span>&lt;span class="mf">24.04&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Après l&amp;rsquo;installation et un redémarrage, il vous sera demandé de configurer un nom d&amp;rsquo;utilisateur et un mot de passe UNIX lors du premier lancement. Cet utilisateur est indépendant de l&amp;rsquo;utilisateur Windows et n&amp;rsquo;est valide qu&amp;rsquo;au sein de WSL.&lt;/p>
&lt;p>Si vous utilisez déjà WSL1, vous pouvez le convertir en WSL2 avec les commandes suivantes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Convertir une distribution existante en WSL2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-set-version&lt;/span> &lt;span class="n">Ubuntu&lt;/span> &lt;span class="mf">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Définir WSL2 comme version par défaut pour les distributions ajoutées à l&amp;#39;avenir&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-set-default-version&lt;/span> &lt;span class="mf">2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="4-les-secrets-du-contrôle-des-ressources--wslconfig-et-wslconf">4. Les secrets du contrôle des ressources : .wslconfig et wsl.conf
&lt;/h2>&lt;p>L&amp;rsquo;un des plus grands pièges de WSL2 est la « consommation illimitée de mémoire (gonflement du processus Vmmem) ». Comme WSL2 utilise le cache de page du noyau Linux, chaque opération d&amp;rsquo;E/S consomme de la mémoire de l&amp;rsquo;hôte (Windows) de manière infinie. Pour éviter cela, il est impératif de limiter les ressources via des fichiers de configuration.&lt;/p>
&lt;p>Les fichiers de configuration de WSL2 sont divisés en deux : &lt;strong>&lt;code>.wslconfig&lt;/code> qui affecte l&amp;rsquo;ensemble de Windows&lt;/strong> et &lt;strong>&lt;code>wsl.conf&lt;/code> qui affecte l&amp;rsquo;intérieur de chaque distribution&lt;/strong>.&lt;/p>
&lt;h3 id="41-wslconfig-côté-windows">4.1. .wslconfig (Côté Windows)
&lt;/h3>&lt;p>Créez un fichier dans le répertoire de profil utilisateur de Windows (&lt;code>C:\Users\&amp;lt;Nom_d_utilisateur&amp;gt;\.wslconfig&lt;/code>) pour contrôler l&amp;rsquo;allocation des ressources à la VM.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># C:\Users\&amp;lt;Nom_d_utilisateur&amp;gt;\.wslconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[wsl2]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Quantité maximale de mémoire allouée à la VM. Il est recommandé d&amp;#39;utiliser environ 50 % à 75 % de la mémoire totale de l&amp;#39;hôte&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">memory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">16GB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Nombre de cœurs de processeur à utiliser (tous les cœurs sont utilisés si omis)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">processors&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">8&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Taille du fichier d&amp;#39;échange (swap)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">swap&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">8GB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Emplacement du fichier d&amp;#39;échange (si vous souhaitez économiser de l&amp;#39;espace sur le lecteur C)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># swapfile=D:\\wsl\\swap.vhdx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Activer le transfert localhost (pour accéder à WSL depuis Windows via localhost)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">localhostForwarding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Libérer automatiquement la mémoire (Windows 11 uniquement)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Libère dynamiquement le cache de page et empêche le gonflement de Vmmem&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">autoMemoryReclaim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">dropcache&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[experimental]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Fonctionnalités réseau avancées disponibles dans Windows 11 22H2 et versions ultérieures&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Cela permet la prise en charge d&amp;#39;IPv6 et le partage de la même adresse IP entre WSL et Windows&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">networkingMode&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">mirrored&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">dnsTunneling&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">firewall&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">autoProxy&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="42-wslconf-côté-linux">4.2. wsl.conf (Côté Linux)
&lt;/h3>&lt;p>Modifiez &lt;code>/etc/wsl.conf&lt;/code> à l&amp;rsquo;intérieur de WSL pour contrôler le comportement spécifique de la distribution.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># /etc/wsl.conf (Modifié à l&amp;#39;intérieur de WSL)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[network]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Désactiver la génération automatique de /etc/resolv.conf au démarrage de WSL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Utile si vous souhaitez configurer un DNS personnalisé (ex. : 8.8.8.8)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">generateResolvConf&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">false&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Définir un nom d&amp;#39;hôte personnalisé&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">hostname&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">WSL-DevNode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[automount]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Paramètres lors du montage de lecteurs Windows&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">enabled&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">options&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;metadata,uid=1000,gid=1000,umask=022&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Changer le point de montage du lecteur C de /mnt/c à /c (pour raccourcir le chemin)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">root&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">/&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[boot]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Activer systemd (WSL 0.67.6 et versions ultérieures)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Cela permet à snap et à divers démons (tels que Docker) de fonctionner nativement&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">systemd&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[user]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Utilisateur connecté par défaut&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">default&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">kenji&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Pour appliquer ces paramètres, vous devez exécuter &lt;code>wsl --shutdown&lt;/code> dans PowerShell pour arrêter complètement la VM WSL avant de redémarrer.&lt;/p>
&lt;hr>
&lt;h2 id="5-lenvironnement-de-terminal-ultime--zsh--powerlevel10k">5. L&amp;rsquo;environnement de terminal ultime : Zsh + Powerlevel10k
&lt;/h2>&lt;p>Rester avec le bash par défaut n&amp;rsquo;augmentera pas votre productivité. En combinant Zsh, qui se vante de puissantes capacités de complétion et de visibilité, avec le thème ultra-rapide « Powerlevel10k », nous allons construire l&amp;rsquo;invite de commande (prompt) la plus puissante.&lt;/p>
&lt;h3 id="51-installation-et-configuration-de-windows-terminal">5.1. Installation et configuration de Windows Terminal
&lt;/h3>&lt;p>Installez « Windows Terminal » à partir du Microsoft Store. Ouvrez la configuration JSON (&lt;code>settings.json&lt;/code>), définissez le profil par défaut sur WSL (Ubuntu) et changez la police pour une Nerd Font orientée développement (par ex., &lt;code>HackGen Console NF&lt;/code> ou &lt;code>MesloLGS NF&lt;/code>).&lt;/p>
&lt;h3 id="52-installation-de-zsh-et-oh-my-zsh">5.2. Installation de Zsh et Oh My Zsh
&lt;/h3>&lt;p>Exécutez les commandes suivantes dans le terminal WSL.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Mise à jour des paquets et installation de Zsh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> sudo apt upgrade -y
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt install -y zsh git curl
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Exécuter le script d&amp;#39;installation de Oh My Zsh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sh -c &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-introduction-de-powerlevel10k-et-des-plugins">5.3. Introduction de Powerlevel10k et des plugins
&lt;/h3>&lt;p>Nous allons introduire des plugins pour améliorer encore Zsh (coloration syntaxique et auto-complétion) ainsi que le thème Powerlevel10k.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Powerlevel10k&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git clone --depth&lt;span class="err">=&lt;/span>&lt;span class="m">1&lt;/span> https://github.com/romkatv/powerlevel10k.git &lt;span class="si">${&lt;/span>&lt;span class="nv">ZSH_CUSTOM&lt;/span>&lt;span class="k">:-&lt;/span>&lt;span class="nv">$HOME&lt;/span>&lt;span class="p">/.oh-my-zsh/custom&lt;/span>&lt;span class="si">}&lt;/span>/themes/powerlevel10k
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># zsh-autosuggestions&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git clone https://github.com/zsh-users/zsh-autosuggestions &lt;span class="si">${&lt;/span>&lt;span class="nv">ZSH_CUSTOM&lt;/span>&lt;span class="k">:-&lt;/span>&lt;span class="p">~/.oh-my-zsh/custom&lt;/span>&lt;span class="si">}&lt;/span>/plugins/zsh-autosuggestions
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># zsh-syntax-highlighting&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git clone https://github.com/zsh-users/zsh-syntax-highlighting.git &lt;span class="si">${&lt;/span>&lt;span class="nv">ZSH_CUSTOM&lt;/span>&lt;span class="k">:-&lt;/span>&lt;span class="p">~/.oh-my-zsh/custom&lt;/span>&lt;span class="si">}&lt;/span>/plugins/zsh-syntax-highlighting
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Modifiez &lt;code>~/.zshrc&lt;/code> pour activer le thème et les plugins.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Changements dans ~/.zshrc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">ZSH_THEME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;powerlevel10k/powerlevel10k&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ajouter au tableau des plugins&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">plugins&lt;/span>&lt;span class="o">=(&lt;/span>git zsh-autosuggestions zsh-syntax-highlighting&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Enregistrez et exécutez &lt;code>source ~/.zshrc&lt;/code>, l&amp;rsquo;assistant de configuration de Powerlevel10k (&lt;code>p10k configure&lt;/code>) se lancera. Suivez les instructions à l&amp;rsquo;écran pour personnaliser l&amp;rsquo;invite selon vos préférences (style de l&amp;rsquo;invite, présence d&amp;rsquo;icônes, informations à afficher, etc.). Le nom de la branche Git et son statut, la version de Node.js, le temps d&amp;rsquo;exécution des commandes, etc. seront affichés en temps réel, ce qui améliorera considérablement l&amp;rsquo;efficacité du développement.&lt;/p>
&lt;hr>
&lt;h2 id="6-intégration-transparente-de-vs-code-remote---wsl">6. Intégration transparente de VS Code Remote - WSL
&lt;/h2>&lt;p>Pour le développement dans WSL2, l&amp;rsquo;extension « Remote - WSL » est le mécanisme qui permet d&amp;rsquo;accéder de manière transparente aux fichiers dans WSL depuis l&amp;rsquo;IDE (Visual Studio Code) installé côté Windows.&lt;/p>
&lt;h3 id="explication-de-larchitecture">Explication de l&amp;rsquo;architecture
&lt;/h3>&lt;p>Le diagramme de séquence suivant montre comment VS Code communique avec WSL2.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
autonumber
participant U as &amp;#34;Développeur&amp;#34;
participant V as &amp;#34;Interface utilisateur de VS Code (Windows)&amp;#34;
participant S as &amp;#34;Serveur VS Code (WSL2)&amp;#34;
participant F as &amp;#34;Système de fichiers ext4 (WSL2)&amp;#34;
U-&amp;gt;&amp;gt;V: &amp;#34;Tapez `code .` dans le terminal WSL&amp;#34;
V-&amp;gt;&amp;gt;S: &amp;#34;Établir une connexion RPC via Vsock&amp;#34;
Note over V,S: Communication via les sockets Hyper-V sans utiliser TCP/IP
S-&amp;gt;&amp;gt;F: &amp;#34;Lire les fichiers sources / Exécuter le Linter&amp;#34;
F--&amp;gt;&amp;gt;S: &amp;#34;Retourner les données et l&amp;#39;analyse&amp;#34;
S--&amp;gt;&amp;gt;V: &amp;#34;Diffuser les résultats du serveur de langage vers l&amp;#39;UI&amp;#34;
V--&amp;gt;&amp;gt;U: &amp;#34;Afficher la coloration syntaxique et les erreurs&amp;#34;
&lt;/pre>
&lt;p>Le VS Code côté Windows fonctionne comme un simple « client léger (UI) », et tous les traitements lourds tels que le Language Server, le débogueur et l&amp;rsquo;exécution du terminal sont gérés par le « VS Code Server » côté WSL. Cela vous permet de garder votre environnement propre uniquement du côté WSL, sans avoir à installer Node.js ou Python du côté Windows.&lt;/p>
&lt;h3 id="paramètres-essentiels-de-vs-code">Paramètres essentiels de VS Code
&lt;/h3>&lt;p>Installez &lt;strong>&amp;ldquo;WSL&amp;rdquo; (ms-vscode-remote.remote-wsl)&lt;/strong> depuis les « Extensions » de VS Code. Ensuite, allez simplement dans le répertoire de votre projet dans le terminal WSL et exécutez &lt;code>code .&lt;/code>, VS Code se lancera côté Windows avec ce répertoire ouvert.&lt;/p>
&lt;p>&lt;strong>Point important (problème des codes de fin de ligne) :&lt;/strong>
Les codes de fin de ligne diffèrent entre Windows et Linux (Windows utilise &lt;code>CRLF&lt;/code>, Linux utilise &lt;code>LF&lt;/code>). Lors d&amp;rsquo;un développement sur WSL, assurez-vous d&amp;rsquo;unifier le paramètre &lt;code>core.autocrlf&lt;/code> de Git et les paramètres de fichier par défaut de VS Code à &lt;code>LF&lt;/code>. Si vous négligez cela, vous rencontrerez des erreurs mystérieuses lors de l&amp;rsquo;exécution de scripts shell ou de conteneurs Docker.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Configuration du code de fin de ligne de Git côté WSL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git config --global core.autocrlf input
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ajoutez également ce qui suit dans le fichier &lt;code>settings.json&lt;/code> de VS Code (Paramètres distants).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;files.eol&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\n&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;terminal.integrated.defaultProfile.linux&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zsh&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="7-optimisation-de-docker-desktop-et-de-lintégration-wsl2">7. Optimisation de Docker Desktop et de l&amp;rsquo;intégration WSL2
&lt;/h2>&lt;p>Pour utiliser Docker dans un environnement WSL2, il existe principalement deux approches.&lt;/p>
&lt;ol>
&lt;li>Installer &lt;strong>Docker Desktop pour Windows&lt;/strong> et activer la fonctionnalité d&amp;rsquo;intégration WSL2&lt;/li>
&lt;li>Installer &lt;strong>nativement le moteur Docker&lt;/strong> directement à l&amp;rsquo;intérieur de WSL2 (ex. : Ubuntu)&lt;/li>
&lt;/ol>
&lt;h3 id="approche-1--docker-desktop-recommandé">Approche 1 : Docker Desktop (Recommandé)
&lt;/h3>&lt;p>Dans la plupart des cas, cela est recommandé car la gestion via l&amp;rsquo;interface graphique et l&amp;rsquo;accès transparent aux conteneurs entre Windows/WSL sont faciles. Vérifiez les points suivants depuis les paramètres de Docker Desktop (Settings).&lt;/p>
&lt;ul>
&lt;li>Cochez &lt;code>General&lt;/code> -&amp;gt; &lt;code>Use the WSL 2 based engine&lt;/code>.&lt;/li>
&lt;li>Cochez &lt;code>Resources&lt;/code> -&amp;gt; &lt;code>WSL Integration&lt;/code> -&amp;gt; &lt;code>Enable integration with my default WSL distro&lt;/code> et activez la distribution à utiliser (Ubuntu) avec le bouton à bascule.&lt;/li>
&lt;/ul>
&lt;p>Cela vous permet d&amp;rsquo;exécuter la commande &lt;code>docker&lt;/code> directement depuis le terminal WSL2, et la communication avec le démon Docker s&amp;rsquo;effectue via des machines virtuelles légères dédiées (&lt;code>docker-desktop&lt;/code> et &lt;code>docker-desktop-data&lt;/code>) gérées par Docker Desktop.&lt;/p>
&lt;h3 id="approche-2--installation-directe-du-moteur-docker-natif">Approche 2 : Installation directe du moteur Docker natif
&lt;/h3>&lt;p>Si vous avez des contraintes de réseau d&amp;rsquo;entreprise (comme éviter la monétisation de Docker Desktop) ou si vous souhaitez réduire au maximum la surcharge de performances, installez Docker en tant que pur serveur Ubuntu après avoir activé &lt;code>systemd&lt;/code> dans &lt;code>/etc/wsl.conf&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Extrait des instructions officielles d&amp;#39;installation de Docker sur WSL2 Ubuntu avec systemd activé&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get install ca-certificates curl gnupg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo install -m &lt;span class="m">0755&lt;/span> -d /etc/apt/keyrings
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -fsSL https://download.docker.com/linux/ubuntu/gpg &lt;span class="p">|&lt;/span> sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo chmod a+r /etc/apt/keyrings/docker.gpg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ajout du dépôt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="s2">&amp;#34;deb [arch=&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>dpkg --print-architecture&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34; signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>. /etc/os-release &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$VERSION_CODENAME&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34; stable&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ajouter l&amp;#39;utilisateur actuel au groupe docker (pour exécuter sans sudo)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo usermod -aG docker &lt;span class="nv">$USER&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Après le redémarrage, &lt;code>systemctl start docker&lt;/code> fonctionnera exactement comme dans un environnement Linux natif et offrira des performances élevées.&lt;/p>
&lt;hr>
&lt;h2 id="8-intégration-des-clés-ssh--authentification-transparente-entre-windows-et-wsl">8. Intégration des clés SSH : Authentification transparente entre Windows et WSL
&lt;/h2>&lt;p>Lors de la réalisation de clones SSH Git ou de la connexion SSH à des serveurs distants, gérer des clés SSH séparées côté Windows et côté WSL est très fastidieux. Pour allier sécurité et commodité, nous allons configurer un pont pour transférer l&amp;rsquo;agent SSH en cours d&amp;rsquo;exécution côté Windows (ou un gestionnaire de mots de passe comme 1Password) vers le côté WSL.&lt;/p>
&lt;p>Ici, nous expliquerons l&amp;rsquo;approche la plus sécurisée et moderne consistant à utiliser la &lt;strong>fonctionnalité d&amp;rsquo;agent SSH de 1Password&lt;/strong> ou &lt;strong>l&amp;rsquo;OpenSSH Authentication Agent de Windows&lt;/strong>, et à la transférer vers un socket de domaine UNIX de WSL2 en utilisant &lt;code>npiperelay&lt;/code> et &lt;code>socat&lt;/code>.&lt;/p>
&lt;h3 id="transfert-de-socket-ssh-agent">Transfert de socket ssh-agent
&lt;/h3>&lt;p>Habituellement, l&amp;rsquo;agent SSH, qui est fourni en tant que Named Pipe (tube nommé) sous Windows, doit être converti en un fichier socket côté WSL. Il est facile d&amp;rsquo;utiliser des fonctionnalités fournies par &lt;code>wsl-ssh-agent&lt;/code> ou 1Password.&lt;/p>
&lt;p>Depuis l&amp;rsquo;écran des paramètres de 1Password, activez « Developer » -&amp;gt; « Use the SSH agent » (Utiliser l&amp;rsquo;agent SSH).
Ensuite, ajoutez la configuration suivante dans le fichier &lt;code>~/.zshrc&lt;/code> ou &lt;code>~/.bashrc&lt;/code> côté WSL pour lier automatiquement le socket lors de la connexion.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ajout dans ~/.zshrc (exemple lors de l&amp;#39;utilisation de 1Password SSH Agent)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">SSH_AUTH_SOCK&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nv">$HOME&lt;/span>/.ssh/agent.sock
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Transférer avec socat et npiperelay si le socket n&amp;#39;existe pas ou si le processus n&amp;#39;est pas lié au démarrage de WSL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">ALREADY_RUNNING&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">$(&lt;/span>ps -aux &lt;span class="p">|&lt;/span> grep &lt;span class="s2">&amp;#34;[n]piperelay.exe -ei -s //./pipe/openssh-ssh-agent&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> wc -l&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="nv">$ALREADY_RUNNING&lt;/span> -eq &lt;span class="m">0&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -S &lt;span class="nv">$SSH_AUTH_SOCK&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm &lt;span class="nv">$SSH_AUTH_SOCK&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Démarrer socat en arrière-plan et connecter le Named Pipe côté Windows au socket UNIX côté WSL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>setsid socat UNIX-LISTEN:&lt;span class="nv">$SSH_AUTH_SOCK&lt;/span>,fork EXEC:&lt;span class="s2">&amp;#34;npiperelay.exe -ei -s //./pipe/openssh-ssh-agent&amp;#34;&lt;/span>,nofork &lt;span class="p">&amp;amp;&lt;/span>&lt;span class="o">)&lt;/span> &amp;gt;/dev/null 2&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>L&amp;rsquo;installation de &lt;code>npiperelay.exe&lt;/code> et l&amp;rsquo;ajout à la variable d&amp;rsquo;environnement PATH côté Windows sont nécessaires au préalable.&lt;/li>
&lt;/ul>
&lt;p>Une fois cette configuration terminée, lors de l&amp;rsquo;exécution de &lt;code>ssh-add -l&lt;/code> depuis le terminal WSL, la liste des clés publiques des clés SSH enregistrées dans 1Password ou côté Windows s&amp;rsquo;affichera. Cela vous permet de passer l&amp;rsquo;authentification en toute sécurité sans avoir à copier les fichiers de clé privée dans WSL.&lt;/p>
&lt;hr>
&lt;h2 id="9-maintenance--optimisation-compression-dun-vhdx-gonflé">9. Maintenance : Optimisation (compression) d&amp;rsquo;un VHDX gonflé
&lt;/h2>&lt;p>L&amp;rsquo;un des plus grands inconvénients de WSL2 est sa spécification selon laquelle « la taille du fichier du disque virtuel côté Windows (.vhdx) ne rétrécit pas automatiquement, même si vous supprimez des images Docker ou des fichiers ». Si vous continuez à développer pendant une longue période, le fichier ext4.vhdx va gonfler jusqu&amp;rsquo;à des dizaines ou des centaines de gigaoctets.&lt;/p>
&lt;p>Pour libérer de l&amp;rsquo;espace disque, vous devez optimiser (Compacter) régulièrement le VHDX depuis le côté Windows.&lt;/p>
&lt;ol>
&lt;li>Tout d&amp;rsquo;abord, arrêtez complètement WSL.
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-shutdown&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>Ouvrez PowerShell avec des privilèges d&amp;rsquo;administrateur et exécutez la commande &lt;code>diskpart&lt;/code> suivante, ou la commande &lt;code>Optimize-VHD&lt;/code> du module Hyper-V (cette dernière n&amp;rsquo;est disponible que si Hyper-V est activé).&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Si le module Hyper-V est disponible&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Optimize-VHD&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$env:LOCALAPPDATA&lt;/span>&lt;span class="s2">\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx&amp;#34;&lt;/span> &lt;span class="n">-Mode&lt;/span> &lt;span class="n">Full&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Si vous utilisez diskpart&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">diskpart&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Entrez interactivement dans l&amp;#39;invite suivante&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DISKPART&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="nb">select &lt;/span>&lt;span class="n">vdisk&lt;/span> &lt;span class="n">file&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="s2">&amp;#34;C:\Users\&amp;lt;Nom_d_utilisateur&amp;gt;\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DISKPART&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">attach&lt;/span> &lt;span class="n">vdisk&lt;/span> &lt;span class="n">readonly&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DISKPART&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">compact&lt;/span> &lt;span class="n">vdisk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DISKPART&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">detach&lt;/span> &lt;span class="n">vdisk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DISKPART&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">exit&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En effectuant cette opération régulièrement, vous pouvez récupérer la capacité du lecteur C inutilement consommée.&lt;/p>
&lt;hr>
&lt;h2 id="10-conclusion">10. Conclusion
&lt;/h2>&lt;p>WSL2 a complètement dépassé le cadre d&amp;rsquo;être un simple « Linux bonus fonctionnant sur Windows » et a évolué vers une puissante plateforme de développement qui n&amp;rsquo;est pas inférieure, et peut-être même supérieure, à macOS et aux machines Linux natives.&lt;/p>
&lt;p>En appliquant tous les paramètres expliqués cette fois-ci (optimisation des ressources avec &lt;code>.wslconfig&lt;/code>, amélioration du terminal avec Zsh + Powerlevel10k, accès transparent avec VS Code Remote, intégration SSH et maintenance VHDX), un « environnement de développement ultime » rapide, sécurisé et sans stress est achevé.&lt;/p>
&lt;p>La configuration de l&amp;rsquo;environnement demande un peu d&amp;rsquo;effort, mais une fois les paramètres fixés, il ne fait aucun doute que votre future productivité en ingénierie s&amp;rsquo;améliorera considérablement. N&amp;rsquo;hésitez pas à explorer des personnalisations supplémentaires sur la base de ce guide, en fonction de vos propres projets et préférences.&lt;/p></description></item></channel></rss>