<?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/de/tags/docker/</link><description>Recent content in Docker on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>de</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 01:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/de/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>Aufbau einer reproduzierbaren lokalen Entwicklungsumgebung mit Docker</title><link>http://kenji.blog/de/p/docker-reproducible-local-dev-environment/</link><pubDate>Sun, 13 Sep 2026 01:00:00 +0900</pubDate><guid>http://kenji.blog/de/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 Aufbau einer reproduzierbaren lokalen Entwicklungsumgebung mit Docker" />&lt;h2 id="1-einführung-weg-von-auf-meiner-maschine-funktioniert-es">1. Einführung: Weg von &amp;ldquo;Auf meiner Maschine funktioniert es&amp;rdquo;
&lt;/h2>&lt;p>In der Softwareentwicklung ist das Problem &amp;ldquo;Auf meiner Maschine funktioniert es&amp;rdquo; (It works on my machine), das auf unterschiedliche Umgebungen zwischen Entwicklern zurückzuführen ist, seit langem ein Faktor, der in vielen Projekten Zeit verschwendet. Aufgrund von Unterschieden im Betriebssystem, Versionen installierter Sprachen, Bibliotheksabhängigkeiten und Konflikten zwischen global installierten Tools ist die lokale Umgebung ständig einer &amp;ldquo;Zustandsunsicherheit&amp;rdquo; ausgesetzt.&lt;/p>
&lt;p>Was diese Probleme von Grund auf löst, sind Container-Technologien wie &lt;strong>Docker&lt;/strong> und das Paradigma von &lt;strong>Infrastructure as Code (IaC)&lt;/strong>. Durch die Containerisierung der lokalen Entwicklungsumgebung wird eine Isolierung auf Betriebssystemebene erreicht, was es ermöglicht, die Umgebung selbst zusammen mit der Codebasis zu versionieren.&lt;/p>
&lt;p>In diesem Artikel erklären wir ausführlich die Schritte zum Aufbau einer &lt;strong>&amp;ldquo;reproduzierbaren lokalen Entwicklungsumgebung, die immer in exakt demselben Zustand startet, unabhängig davon, wer sie wann und auf welcher Maschine startet&amp;rdquo;&lt;/strong>, unter Verwendung von Docker, Docker Compose und VSCode DevContainers. Wir beleuchten auch die tiefgreifenden technischen Mechanismen dahinter, einschließlich einer mathematischen Perspektive.&lt;/p>
&lt;hr>
&lt;h2 id="2-die-affinität-zwischen-infrastructure-as-code-iac-und-container-technologie">2. Die Affinität zwischen Infrastructure as Code (IaC) und Container-Technologie
&lt;/h2>&lt;h3 id="prinzipien-von-iac-und-deren-anwendung-auf-lokale-umgebungen">Prinzipien von IaC und deren Anwendung auf lokale Umgebungen
&lt;/h3>&lt;p>Infrastructure as Code (IaC) ist ein Ansatz zur Verwaltung der Konfiguration und Bereitstellung von Infrastruktur durch maschinenlesbare Definitionsdateien anstelle von manuellen Prozessen. Zu den Kernprinzipien von IaC gehören folgende Elemente:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Deklarativer Ansatz (Declarative Approach)&lt;/strong>: Definiert &amp;ldquo;wie der Endzustand sein soll&amp;rdquo;, anstatt &amp;ldquo;wie der Zustand geändert werden soll&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>Idempotenz (Idempotency)&lt;/strong>: Egal wie oft das Skript ausgeführt wird, es wird immer dasselbe Ergebnis (Zustand) garantiert.&lt;/li>
&lt;li>&lt;strong>Versionskontrolle (Version Control)&lt;/strong>: Der Zustand der Infrastruktur wird als Code in einem VCS wie Git gespeichert, was die Verfolgung des Änderungsverlaufs und Peer-Reviews ermöglicht.&lt;/li>
&lt;/ol>
&lt;p>Die Umsetzung von IaC in einer lokalen Entwicklungsumgebung bedeutet, den &amp;ldquo;idealen Zustand&amp;rdquo; der Entwicklungsumgebung mit &lt;code>Dockerfile&lt;/code>, &lt;code>docker-compose.yml&lt;/code> und &lt;code>devcontainer.json&lt;/code> in Code zu fassen. Dadurch wird ein Onboarding-Erlebnis geschaffen, bei dem neue Teammitglieder einfach das Repository klonen und einen einzigen Befehl ausführen können, um sofort mit der Entwicklung zu beginnen.&lt;/p>
&lt;h3 id="kernel-funktionen-die-die-container-technologie-unterstützen">Kernel-Funktionen, die die Container-Technologie unterstützen
&lt;/h3>&lt;p>Im Gegensatz zur Hypervisor-basierten Virtualisierung wie bei virtuellen Maschinen (VMs) ist die Container-Technologie eine leichtgewichtige Virtualisierungstechnik, die Prozesse isoliert, während sie den Kernel des Host-Betriebssystems teilt. Um dies zu erreichen, werden hauptsächlich die folgenden Funktionen des Linux-Kernels verwendet:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Namespaces&lt;/strong>: Bieten eine isolierte Sicht auf Systemressourcen (PID, Netzwerk, Mount-Punkte, Benutzer usw.) für jeden Prozess.&lt;/li>
&lt;li>&lt;strong>Cgroups (Control Groups)&lt;/strong>: Begrenzen und weisen physische Ressourcen (CPU, Speicher, Festplatten-I/O usw.) zu, die von Prozessen verwendet werden können.&lt;/li>
&lt;li>&lt;strong>UnionFS (Union File System)&lt;/strong>: Eine Technologie, die mehrere Verzeichnisbäume (Ebenen) transparent überlagert, sodass sie als ein einziges Dateisystem erscheinen. Die Image-Ebenen von Docker basieren auf dieser Technologie.&lt;/li>
&lt;/ul>
&lt;p>Betrachten wir ein mathematisches Modell der Ressourcenbegrenzung. Sei $M_{\text{total}}$ die Gesamtspeicherkapazität der Host-Maschine und $m_i$ die Speicherbegrenzung von $n$ Containern, die auf dem Host laufen. Unter Berücksichtigung des Basisspeichers $M_{\text{os}}$, der vom Host-Betriebssystem und anderen Prozessen verbraucht wird, kann die notwendige Bedingung für den stabilen Betrieb des Systems durch folgende Ungleichung ausgedrückt werden:&lt;/p>
$$ \sum_{i=1}^{n} m_i \le M_{\text{total}} - M_{\text{os}} $$&lt;p>Indem $m_i$ für jeden Container mithilfe von Cgroups strikt definiert wird, kann verhindert werden, dass der OOM (Out Of Memory) Killer andere Container oder das gesamte Host-System zum Absturz bringt, selbst wenn ein bestimmter Container ein Speicherleck verursacht.&lt;/p>
&lt;hr>
&lt;h2 id="3-effizientes-dockerfile-design-multi-stage-builds-meistern">3. Effizientes Dockerfile-Design: Multi-Stage-Builds meistern
&lt;/h2>&lt;p>Der erste Schritt zu einer reproduzierbaren Umgebung ist das Design des &lt;code>Dockerfile&lt;/code>, das die Ausführungsumgebung der Anwendung definiert. Hier erklären wir am Beispiel von Python (FastAPI) die Best Practices für ein sicheres und leichtgewichtiges Dockerfile unter Verwendung von &lt;strong>Multi-Stage-Builds&lt;/strong>.&lt;/p>
&lt;p>Ein Multi-Stage-Build ist eine Technik, die mehrere &lt;code>FROM&lt;/code>-Anweisungen in einem einzigen &lt;code>Dockerfile&lt;/code> verwendet, um die Build-Umgebung (eine schwere Umgebung, die Compiler und Entwicklungstools enthält) von der Laufzeitumgebung (einer leichtgewichtigen Umgebung, die nur die notwendigen Artefakte enthält) zu trennen.&lt;/p>
&lt;h3 id="praktisches-dockerfile-für-python-fastapi">Praktisches Dockerfile für Python FastAPI
&lt;/h3>&lt;p>Der folgende Code ist ein Beispiel für ein fortgeschrittenes &lt;code>Dockerfile&lt;/code>, das Abhängigkeitsmanagement mit Poetry und Multi-Stage-Builds kombiniert.&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 (Build-Umgebung)&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"># Festlegen erforderlicher Umgebungsvariablen&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 von Abhängigkeiten&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"># Kopieren und Installieren der Abhängigkeitsdateien&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 (Laufzeitumgebung)&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"># Erstellen eines minimalen, nicht privilegierten Benutzers&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"># Kopieren nur der virtuellen Umgebung (Abhängigkeiten) vom 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 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"># Kopieren des Anwendungscodes&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"># Wechseln zum nicht privilegierten Benutzer&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"># Standardbefehl beim Starten des Containers&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="mathematische-bewertung-der-image-größe-durch-multi-stage-builds">Mathematische Bewertung der Image-Größe durch Multi-Stage-Builds
&lt;/h3>&lt;p>Sei $S_{\text{single}}$ die Image-Größe bei einem Single-Stage-Build und $S_{\text{multi}}$ die Image-Größe bei Anwendung eines Multi-Stage-Builds. Die Reduktionsrate der Größe $R$ wird wie folgt berechnet:&lt;/p>
$$ R = \left( 1 - \frac{S_{\text{multi}}}{S_{\text{single}}} \right) \times 100 \ (\%) $$&lt;p>Angenommen, $S_{\text{single}}$ enthält das Basis-Image des Betriebssystems (ca. 110 MB), Entwicklungspakete (z. B. gcc, ca. 150 MB), Poetry selbst (ca. 40 MB), die Abhängigkeitsbibliotheken des Projekts (ca. 80 MB) und den Quellcode (ca. 5 MB), was insgesamt 385 MB ergibt.
Andererseits werden in $S_{\text{multi}}$ nur die Abhängigkeitsbibliotheken (80 MB) und der Quellcode (5 MB) in das Basis-Image (110 MB) kopiert, was insgesamt 195 MB ergibt.&lt;/p>
$$ R = \left( 1 - \frac{195}{385} \right) \times 100 \approx 49.35\% $$&lt;p>Wie gezeigt, kann durch die Einführung von Multi-Stage-Builds die Image-Größe um etwa die Hälfte reduziert werden. Die Reduzierung der Image-Größe führt direkt zu kürzeren Pull-Zeiten aus der Registry, Einsparungen beim Festplattenspeicher und einer Erhöhung der Sicherheit durch Verkleinerung der Angriffsfläche (Attack Surface).&lt;/p>
&lt;hr>
&lt;h2 id="4-orchestrierung-mehrerer-container-mit-docker-compose">4. Orchestrierung mehrerer Container mit Docker Compose
&lt;/h2>&lt;p>In der modernen Entwicklung von Webanwendungen ist eine Microservices-Architektur üblich, in der mehrere Komponenten wie Webserver, Datenbanken und Cache-Server zusammenarbeiten. Um diese in einer lokalen Umgebung zentral zu verwalten, wird &lt;code>docker-compose.yml&lt;/code> verwendet.&lt;/p>
&lt;p>In diesem Fall werden wir ein 3-Schicht-System bestehend aus &amp;ldquo;Web (FastAPI)&amp;rdquo;, &amp;ldquo;Database (PostgreSQL)&amp;rdquo; und &amp;ldquo;Cache (Redis)&amp;rdquo; lokal aufbauen.&lt;/p>
&lt;h3 id="architekturdiagramm-mermaid">Architekturdiagramm (Mermaid)
&lt;/h3>&lt;p>Das folgende Diagramm ist ein Blockdiagramm, das die Beziehungen zwischen den einzelnen Containern, dem Netzwerk und den Volumes auf dem lokalen Rechner darstellt.&lt;/p>
&lt;pre class="mermaid">
graph TD
User[&amp;#34;Host-Maschine (Browser/curl)&amp;#34;] --&amp;gt;|Localhost:8000| Web[&amp;#34;FastAPI Web-Container&amp;#34;]
subgraph &amp;#34;Docker Bridge Netzwerk (app-network)&amp;#34;
Web --&amp;gt;|Port 5432| DB[&amp;#34;PostgreSQL-Container&amp;#34;]
Web --&amp;gt;|Port 6379| Redis[&amp;#34;Redis-Container&amp;#34;]
end
DB --&amp;gt; Volume1[&amp;#34;Benanntes Volume (postgres_data)&amp;#34;]
Redis --&amp;gt; Volume2[&amp;#34;Benanntes Volume (redis_data)&amp;#34;]
HostDir[&amp;#34;Host-Quellcode (./src)&amp;#34;] -.-&amp;gt;|Bind Mount| Web
&lt;/pre>
&lt;h3 id="implementierung-und-detaillierte-erklärung-der-docker-composeyml">Implementierung und detaillierte Erklärung der docker-compose.yml
&lt;/h3>&lt;p>Im Folgenden zeigen wir ein Beispiel für eine robuste &lt;code>docker-compose.yml&lt;/code>, die für den Aufbau einer praktischen Umgebung geeignet ist.&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"># Host-Code im schreibgeschützten Modus einhängen (für Hot Reloading)&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-und-datenpersistenz">Volumes und Datenpersistenz
&lt;/h3>&lt;p>Container sind grundsätzlich &amp;ldquo;zustandslos (stateless)&amp;rdquo; und &amp;ldquo;kurzlebig (ephemeral)&amp;rdquo;. Wenn ein Container zerstört wird, gehen auch die internen Daten verloren. Um Datenbankdaten oder Caches beizubehalten, muss ein Bereich des Dateisystems der Host-Maschine im Container gemountet werden.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Bind Mount&lt;/strong>: Das &lt;code>./src:/app/src:ro&lt;/code> im obigen &lt;code>web&lt;/code>-Service ist ein Beispiel dafür. Ein bestimmtes Verzeichnis auf dem Host wird direkt in den Container gemappt. Dies wird verwendet, um lokale Code-Änderungen sofort im Container widerzuspiegeln (Hot Reloading). Aus Sicherheitsgründen ist es eine Best Practice, die Option &lt;code>:ro&lt;/code> (Read-Only) hinzuzufügen, um zu verhindern, dass der Host-Quellcode vom Container aus geändert wird.&lt;/li>
&lt;li>&lt;strong>Benanntes Volume (Named Volume)&lt;/strong>: Hierunter fallen &lt;code>postgres_data&lt;/code> und &lt;code>redis_data&lt;/code>. Es handelt sich um Bereiche, die Docker intern verwaltet (z.B. &lt;code>/var/lib/docker/volumes/&lt;/code>). Sie bieten eine bessere I/O-Leistung als Bind Mounts und verbergen die Unterschiede zwischen den Dateisystemen verschiedener Betriebssysteme. Für die Persistenz von Datenbanken sollte immer diese Methode verwendet werden.&lt;/li>
&lt;/ul>
&lt;h3 id="netzwerk-networking-und-service-discovery">Netzwerk (Networking) und Service Discovery
&lt;/h3>&lt;p>Docker Compose erstellt standardmäßig für jedes Projekt ein eigenes Bridge-Netzwerk, wie das obige &lt;code>app-network&lt;/code>.
Container, die zum selben Netzwerk gehören, können einander über den &amp;ldquo;Service-Namen (z. B. &lt;code>db&lt;/code>, &lt;code>redis&lt;/code>)&amp;rdquo; als Hostnamen auflösen (DNS-Auflösung) anstatt über IP-Adressen.
Zum Beispiel kann der Web-Container über die URL &lt;code>postgresql://postgres:password@db:5432/mydb&lt;/code> auf die Datenbank zugreifen. Dies ermöglicht es, das Verbindungsziel transparent über Umgebungsvariablen umzuschalten, sowohl in lokalen Umgebungen als auch in Produktionsumgebungen.&lt;/p>
&lt;h3 id="health-checks-und-steuerung-der-startreihenfolge">Health Checks und Steuerung der Startreihenfolge
&lt;/h3>&lt;p>Die Direktive &lt;code>depends_on&lt;/code> steuert die Startreihenfolge von Containern, aber wenn Sie nur &lt;code>depends_on&lt;/code> angeben, wird der Web-Container gestartet, sobald &amp;ldquo;der DB-Container gestartet ist&amp;rdquo;. In der Realität dauert es jedoch einige Sekunden, bis der Initialisierungsprozess der Datenbank (Start des PostgreSQL-Prozesses und Vorbereitung der Tabellen) abgeschlossen ist, was dazu führen kann, dass die DB-Verbindung vom Web-Container aus fehlschlägt.
Um dies zu verhindern, kann man einen &lt;code>healthcheck&lt;/code> definieren und &lt;code>condition: service_healthy&lt;/code> festlegen. Dadurch wird sichergestellt, dass der Web-Container erst gestartet wird, nachdem verifiziert wurde, dass &amp;ldquo;die Datenbank bereit ist, Verbindungsanfragen anzunehmen&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="5-verwaltung-von-umgebungsvariablen-und-sicherheit-env">5. Verwaltung von Umgebungsvariablen und Sicherheit (.env)
&lt;/h2>&lt;p>Das Festcodieren sensibler Informationen wie Datenbankpasswörter oder API-Schlüssel in der &lt;code>docker-compose.yml&lt;/code> ist ein Anti-Pattern, das unbedingt vermieden werden sollte. Stattdessen verwenden wir eine Umgebungsvariablendatei &lt;code>.env&lt;/code>, um diese Werte zu injizieren.&lt;/p>
&lt;p>Erstellen Sie eine &lt;code>.env&lt;/code>-Datei im Projektstammverzeichnis.&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"># .env Datei (Zur .gitignore hinzufügen, um sie von der Git-Verwaltung auszuschließen)&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 liest standardmäßig die &lt;code>.env&lt;/code>-Datei im Ausführungsverzeichnis und erweitert die Platzhalter &lt;code>${VAR_NAME}&lt;/code> in der YAML-Datei. Diese Methode ermöglicht es, unterschiedliche Konfigurationswerte für Umgebungen wie lokal, Staging und Produktion sicher zu verwalten, ohne den Infrastrukturcode zu ändern.&lt;/p>
&lt;hr>
&lt;h2 id="6-das-ultimative-entwicklungserlebnis-mit-vscode-devcontainers">6. Das ultimative Entwicklungserlebnis mit VSCode DevContainers
&lt;/h2>&lt;p>Bis hierhin haben wir eine robuste Backend-Umgebung mit Docker aufgebaut. Wir können jedoch noch einen Schritt weiter gehen. Durch die Nutzung der Funktion &lt;strong>VSCode DevContainers (Remote - Containers)&lt;/strong> ist es möglich, das Backend des Editors (VSCode) selbst innerhalb des Containers auszuführen.&lt;/p>
&lt;p>Dadurch müssen weder Python noch Node.js auf der lokalen Maschine installiert werden. Alles, von Lintern (flake8/eslint) und Formattern (black/prettier) bis hin zu IDE-Erweiterungen, kann innerhalb der Codebasis definiert und mit dem gesamten Team geteilt werden.&lt;/p>
&lt;h3 id="konfiguration-von-devcontainerjson">Konfiguration von devcontainer.json
&lt;/h3>&lt;p>Erstellen Sie im Projektstammverzeichnis ein &lt;code>.devcontainer&lt;/code>-Verzeichnis und platzieren Sie die Konfigurationsdatei darin.&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>Indem Sie diese Datei in das Repository aufnehmen, wird sofort nach dem Öffnen des Projekts in VSCode die Aufforderung &amp;ldquo;Reopen in Container&amp;rdquo; angezeigt. Mit nur einem Klick werden alle notwendigen Container gestartet, Erweiterungen installiert und Sie sind sofort bereit, mit dem Coden zu beginnen. Es ist wahrlich ein magisches Erlebnis.&lt;/p>
&lt;hr>
&lt;h2 id="7-sequenz-der-anforderungsverarbeitung-und-leistungsmodellierung">7. Sequenz der Anforderungsverarbeitung und Leistungsmodellierung
&lt;/h2>&lt;p>Wir betrachten den Lebenszyklus der Anforderungsverarbeitung der Webanwendung in der aufgebauten lokalen Entwicklungsumgebung anhand eines Sequenzdiagramms und diskutieren ein mathematisches Modell für deren Leistung.&lt;/p>
&lt;h3 id="sequenzdiagramm-anforderungsfluss">Sequenzdiagramm (Anforderungsfluss)
&lt;/h3>&lt;pre class="mermaid">
sequenceDiagram
participant Client as &amp;#34;Browser / VSCode&amp;#34;
participant Web as &amp;#34;FastAPI (Web)&amp;#34;
participant Redis as &amp;#34;Redis Cache&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;Check Cache for user:123&amp;#34;
activate Redis
alt &amp;#34;Cache Hit (Daten vorhanden)&amp;#34;
Redis--&amp;gt;&amp;gt;Web: &amp;#34;Return Cached User Data&amp;#34;
Web--&amp;gt;&amp;gt;Client: &amp;#34;200 OK (Fast Response)&amp;#34;
else &amp;#34;Cache Miss (Keine Daten)&amp;#34;
Redis--&amp;gt;&amp;gt;Web: &amp;#34;Null (Not Found)&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;Return Database Row&amp;#34;
deactivate DB
Web-&amp;gt;&amp;gt;Redis: &amp;#34;SET user:123 Data (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 (Standard Response)&amp;#34;
end
deactivate Web
&lt;/pre>
&lt;h3 id="mathematisches-modell-der-verarbeitungsverzögerung-latenz">Mathematisches Modell der Verarbeitungsverzögerung (Latenz)
&lt;/h3>&lt;p>Wir modellieren mathematisch die durchschnittliche Anforderungsverarbeitungszeit $T_{\text{total}}$ im obigen System.
Wir definieren die Latenz jeder Verarbeitung wie folgt:&lt;/p>
&lt;ul>
&lt;li>$T_{\text{net}}$: Netzwerklatenz zwischen Client und Web-Container&lt;/li>
&lt;li>$T_{\text{app}}$: Reine Verarbeitungszeit auf Anwendungsseite (Serialisierung usw.)&lt;/li>
&lt;li>$T_{\text{cache}}$: Lese-/Schreibzeit von/nach Redis&lt;/li>
&lt;li>$T_{\text{db}}$: Ausführungszeit für Abfragen an PostgreSQL&lt;/li>
&lt;li>$p_{\text{miss}}$: Cache-Miss-Rate ($0 \le p_{\text{miss}} \le 1$)&lt;/li>
&lt;/ul>
&lt;p>Dann wird die durchschnittliche Antwortzeit durch die folgende Erwartungswertformel dargestellt:&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>In einer lokalen Entwicklungsumgebung (innerhalb von Docker) liegt $T_{\text{net}}$ nahe bei 0. Beachtenswert ist jedoch die &lt;strong>I/O-Leistung bei Bind Mounts&lt;/strong>. Insbesondere bei der Verwendung von Docker Desktop auf Windows/macOS tendiert $T_{\text{app}}$ (wie z. B. die Zeit zum Laden von Code) dazu, aufgrund des Overhead bei der Dateifreigabe zwischen dem Host-Betriebssystem und der VM (Container) anzusteigen. Um diesen Engpass zu beheben, wird dringend eine Architektur empfohlen, bei der entweder die gesamten Quellcodes in einem benannten Volume mit den zuvor erwähnten DevContainers abgelegt werden oder die Docker-Engine nativ in einer WSL2-Umgebung (Windows Subsystem for Linux 2) ausgeführt wird.&lt;/p>
&lt;hr>
&lt;h2 id="8-leistungsoptimierung-für-docker-builds-layer-cache-strategie">8. Leistungsoptimierung für Docker-Builds: Layer-Cache-Strategie
&lt;/h2>&lt;p>Beim Schreiben eines Dockerfile ändert sich die Build-Zeit drastisch, je nachdem, ob Sie den Mechanismus des &amp;ldquo;Layer Caches&amp;rdquo; verstehen oder nicht.
Docker erstellt Dateisystemdifferenzen (Ebenen) für jede Anweisung im Dockerfile (wie &lt;code>FROM&lt;/code>, &lt;code>RUN&lt;/code>, &lt;code>COPY&lt;/code>) und hält sie als Cache bereit. Bei einem erneuten Build wird der Cache der unveränderten Ebenen wiederverwendet.&lt;/p>
&lt;p>Ein wichtiges Prinzip lautet: &lt;strong>&amp;ldquo;Schreiben Sie in der Reihenfolge von der geringsten zur höchsten Änderungshäufigkeit.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;p>Betrachten wir die Modellierung der Auswirkungen von Quellcodeänderungen auf die Build-Zeit. Sei $T_{\text{build}}$ die Gesamt-Build-Zeit, $T_{\text{layer}_i}$ die Ausführungszeit jedes Schritts und das Vorhandensein eines Cache-Treffers der boolesche Wert $c_i \in \{0, 1\}$ (1 bei Cache-Treffer).&lt;/p>
$$ T_{\text{build}} = T_{\text{init}} + \sum_{i=1}^{n} (1 - c_i) \times T_{\text{layer}_i} $$&lt;p>Sobald ein Cache-Miss ($c_k = 0$) in Ebene $k$ auftritt, wird der Cache für alle nachfolgenden Ebenen $j > k$ ungültig ($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"># Schlechtes Beispiel (Quellcode wird zuerst kopiert)&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>In obigem Fall führt das Ändern nur einer Codezeile zu einem Cache-Miss beim ersten &lt;code>COPY&lt;/code>, und das zeitaufwändige &lt;code>RUN poetry install&lt;/code> wird jedes Mal ausgeführt.&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"># Gutes Beispiel (Abhängigkeiten werden zuerst aufgelöst)&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>Durch diese Schreibweise bleibt der Layer-Cache von &lt;code>poetry install&lt;/code> ($c_i = 1$) auch bei Änderung des Quellcodes wirksam, wodurch die Build-Zeit drastisch von einigen Minuten auf wenige Sekunden reduziert wird.&lt;/p>
&lt;hr>
&lt;h2 id="9-fehlerbehebung-troubleshooting-und-tipps">9. Fehlerbehebung (Troubleshooting) und Tipps
&lt;/h2>&lt;p>Hier sind einige häufige Probleme und Lösungen beim Betrieb einer lokalen Umgebung:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Fehler durch Portkonflikt&lt;/strong>
Wenn ein Fehler wie &lt;code>Bind for 0.0.0.0:8000 failed: port is already allocated&lt;/code> auftritt, verwendet ein anderer Prozess auf dem lokalen Rechner diesen Port. Sie können dies vermeiden, indem Sie die hostseitige Portnummer ändern, z. B. auf &lt;code>ports: - &amp;quot;8080:8000&amp;quot;&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Erschöpfung des Festplattenspeichers&lt;/strong>
Wenn Sie Docker über einen längeren Zeitraum verwenden, können sich ungenutzte Images und Volumes (Dangling Images / Volumes) ansammeln und zig Gigabyte Festplattenspeicherplatz belegen. Es wird empfohlen, das System regelmäßig mit dem folgenden Befehl zu bereinigen:&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>Probleme mit Dateiberechtigungen&lt;/strong>
Wenn Sie Bind Mounts in einer Linux-Umgebung verwenden, kann der Eigentümer der innerhalb des Containers erstellten Dateien zu &lt;code>root&lt;/code> werden, was die Bearbeitung auf der Host-Seite unmöglich macht. Dieses Problem kann gelöst werden, indem ein nicht privilegierter Benutzer im Dockerfile erstellt wird, dessen UID/GID mit der Ihres eigenen Host-Betriebssystems (z. B. 1000:1000) übereinstimmt.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="10-fazit-steigerung-der-entwicklungsgeschwindigkeit-durch-reproduzierbarkeit">10. Fazit: Steigerung der Entwicklungsgeschwindigkeit durch Reproduzierbarkeit
&lt;/h2>&lt;p>Durch die Kombination von Docker, Docker Compose und VSCode DevContainers wird eine robuste lokale Entwicklungsumgebung realisiert, bei der &amp;ldquo;unabhängig davon, wer die Umgebung startet, immer exakt derselbe Zustand erreicht wird&amp;rdquo;.&lt;/p>
&lt;p>Das Einbringen des IaC-Paradigmas in die lokale Umgebung verkürzt nicht nur die anfängliche Einrichtungszeit. Es steigert die Geschwindigkeit und Qualität des gesamten Entwicklungszyklus dramatisch, indem es die Angst vor Änderungen an der Infrastrukturkonfiguration nimmt, das Experimentieren mit neuen Technologie-Stacks erleichtert und einen reibungslosen Übergang zu CI/CD-Pipelines ermöglicht.&lt;/p>
&lt;p>Bitte nutzen Sie die in diesem Artikel erläuterten Best Practices, wie z. B. die Optimierung der Image-Größe durch Multi-Stage-Builds, die Steuerung von Abhängigkeiten mithilfe von Health Checks und das Schreiben eines Dockerfiles unter Berücksichtigung des Layer-Caches, und führen Sie unbedingt das beste Entwicklungserlebnis (DX: Developer Experience) in Ihren eigenen Projekten ein.&lt;/p></description></item><item><title>Der ultimative Leitfaden zur Einrichtung der Entwicklungsumgebung in WSL2 (Windows Subsystem for Linux)</title><link>http://kenji.blog/de/p/wsl2-ultimate-development-setup-guide/</link><pubDate>Sat, 12 Sep 2026 23:00:00 +0900</pubDate><guid>http://kenji.blog/de/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 Der ultimative Leitfaden zur Einrichtung der Entwicklungsumgebung in WSL2 (Windows Subsystem for Linux)" />&lt;p>„WSL2 (Windows Subsystem for Linux 2)“, das eine native Linux-Entwicklungsumgebung unter Windows bietet, ist zu einem unverzichtbaren Werkzeug in der modernen Softwareentwicklung geworden. Es gibt jedoch einen himmelweiten Unterschied in Leistung und Entwicklungserfahrung zwischen der weiteren Nutzung im Standardzustand und dem Verständnis der Architektur zur entsprechenden Optimierung.&lt;/p>
&lt;p>Dieser Artikel beginnt mit einer Erklärung der Architektur, die das Fundament von WSL2 bildet. Er behandelt ausführlich alle Schritte zum Aufbau der „ultimativen Entwicklungsumgebung“, die professionelle Ingenieure verlangen, einschließlich Konfigurationen zur Maximierung der Leistung, Aufbau einer komfortablen Terminalumgebung, nahtlose Integration mit Docker und VS Code sowie erweiterte Netzwerkeinstellungen, mit einem Umfang von über 10.000 Zeichen.&lt;/p>
&lt;hr>
&lt;h2 id="1-wsl2-architektur-und-die-evolution-von-wsl1">1. WSL2-Architektur und die Evolution von WSL1
&lt;/h2>&lt;p>Um das Potenzial von WSL2 voll auszuschöpfen, ist es wichtig, zuerst seine interne Struktur zu verstehen. Das erste WSL (WSL1) und WSL2 unterscheiden sich grundlegend in ihrem Ansatz, Linux-Binärdateien unter Windows auszuführen.&lt;/p>
&lt;h3 id="wsl1-systemcall-übersetzungsebene">WSL1: Systemcall-Übersetzungsebene
&lt;/h3>&lt;p>WSL1 verwendete einen Mechanismus zur Übersetzung von Linux-Systemaufrufen in Windows-NT-APIs in Echtzeit. Dies hatte den Vorteil eines sehr geringen Ressourcen-Overheads, da keine virtuelle Maschine (VM) verwendet wurde. Es war jedoch schwierig, komplexe Systemaufrufe wie Dateisystem-I/O-Operationen vollständig zu emulieren. Dies führte zu einer katastrophalen Leistungseinbuße, insbesondere bei der Verarbeitung einer großen Anzahl kleiner Dateien, wie z.B. &lt;code>npm install&lt;/code> von Node.js oder Git-Repository-Operationen.&lt;/p>
&lt;h3 id="wsl2-lightweight-utility-vm-und-vollständiger-linux-kernel">WSL2: Lightweight Utility VM und vollständiger Linux-Kernel
&lt;/h3>&lt;p>Bei WSL2 wurde die Architektur erneuert, und ein von Microsoft erstellter echter Linux-Kernel läuft jetzt direkt auf einer &lt;strong>„Lightweight Utility VM“, die eine Teilmenge der Hyper-V-Architektur nutzt&lt;/strong>. Dies garantiert 100%ige Kompatibilität von Systemaufrufen, und durch die Verwendung einer virtuellen Festplatte (VHDX) mit dem nativen Linux-Dateisystem ext4 hat sich die Datei-I/O-Leistung im Vergleich zu WSL1 dramatisch verbessert.&lt;/p>
&lt;p>Das folgende Mermaid-Diagramm zeigt die strukturellen Unterschiede zwischen WSL1 und WSL2.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
subgraph &amp;#34;Windows OS-Umgebung&amp;#34;
A[&amp;#34;Windows NT-Kernel&amp;#34;]
A --&amp;gt; F[&amp;#34;NTFS-Dateisystem (C:-Laufwerk)&amp;#34;]
end
subgraph &amp;#34;WSL2-Architektur&amp;#34;
B[&amp;#34;Hyper-V-Hypervisor&amp;#34;]
B --&amp;gt; C[&amp;#34;Lightweight Utility VM&amp;#34;]
C --&amp;gt; D[&amp;#34;Linux-Kernel (Microsoft)&amp;#34;]
D --&amp;gt; E[&amp;#34;Ubuntu User Space (glibc, bash usw.)&amp;#34;]
D --&amp;gt; G[&amp;#34;Virtuelle ext4-Festplatte (.vhdx)&amp;#34;]
end
A -.-&amp;gt;|&amp;#34;Plan 9 (9P) Protocol Network File Share&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>Die wichtigste Lektion aus dieser Struktur ist: &lt;strong>„Der Zugriff auf Dateien auf der Linux-Seite (innerhalb von VHDX) ist extrem schnell, aber der Zugriff auf Dateien auf der Windows-Seite (&lt;code>/mnt/c/&lt;/code>) ist sehr langsam, da er über das 9P-Protokoll erfolgt.“&lt;/strong> Der Quellcode für Ihre Projekte muss unter dem Home-Verzeichnis (&lt;code>~&lt;/code>) auf der WSL-Seite abgelegt werden.&lt;/p>
&lt;hr>
&lt;h2 id="2-mathematische-leistungsanalyse-warum-ist-wsl2-schnell">2. Mathematische Leistungsanalyse: Warum ist WSL2 schnell?
&lt;/h2>&lt;p>Lassen Sie uns die Leistungssteigerung von WSL2 mithilfe eines mathematischen Modells quantitativ bewerten. Eine der zeitaufwändigsten Operationen in der Softwareentwicklung ist die Verarbeitung, die mit einer großen Menge an Datei-I/O einhergeht (z.B. Bibliotheksinstallation und Build).&lt;/p>
&lt;p>Die Gesamtausführungszeit $T_{total}$ eines bestimmten Prozesses wird durch die Summe der CPU-Berechnungszeit $T_{compute}$ und der Festplatten-I/O-Zeit $T_{io}$ ausgedrückt.&lt;/p>
$$ T_{total} = T_{compute} + T_{io} $$&lt;p>Im Fall von WSL1, da ein Overhead für die Konvertierung von Operationen auf der Linux-Seite in NTFS-Operationen entsteht, wird die I/O-Zeit wie folgt modelliert. Hierbei ist $n$ die Anzahl der Dateioperationen, $t_{ntfs\_syscall}$ die Ausführungszeit des Systemaufrufs auf der Windows-Seite und $t_{trans}$ der Overhead der Übersetzungsebene.&lt;/p>
$$ T_{wsl1\_io} = \sum_{i=1}^{n} (t_{ntfs\_syscall_i} + t_{trans_i}) $$&lt;p>Im Fall von WSL2, da der Kernel direkt I/O an das ext4-Dateisystem ausgibt, besteht der Overhead nur aus der sehr geringen Verzögerung $t_{virt}$ durch die Virtualisierung.&lt;/p>
$$ T_{wsl2\_io} = \sum_{i=1}^{n} (t_{ext4_i} + t_{virt_i}) $$&lt;p>In allgemeinen Dateisystemen ist $t_{ext4} \ll t_{ntfs\_syscall} + t_{trans}$. Wenn also $n$ sehr groß ist (Zehntausende bis Hunderttausende von Dateioperationen durchführen), vergrößert sich der Unterschied in der I/O-Zeit zwischen WSL1 und WSL2 exponentiell.&lt;/p>
&lt;p>Wenn wir außerdem das Overhead-Verhältnis der CPU-Berechnung in einer virtualisierten Umgebung mit $\rho$ ansetzen, bleibt es bei der neuesten hardwareunterstützten Virtualisierung (Intel VT-x / AMD-V) bei etwa $\rho \approx 0.01 \sim 0.03$ (1-3%). Daher wird selbst bei reinen Rechenaufgaben eine Leistung von $97\% \sim 99\%$ erreicht, was der einer nativen Linux-Umgebung in nichts nachsteht.&lt;/p>
&lt;hr>
&lt;h2 id="3-installation-und-aufbau-der-grundlagen">3. Installation und Aufbau der Grundlagen
&lt;/h2>&lt;p>Unter Windows 10/11 ist die Installation von WSL2 sehr einfach geworden. Öffnen Sie einfach PowerShell mit Administratorrechten und führen Sie den folgenden Befehl aus.&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 und Ubuntu werden standardmäßig installiert&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"># Wenn Sie eine bestimmte Distribution angeben&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Kann mit wsl --list --online überprüft werden&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>Nach der Installation und einem Neustart werden Sie beim ersten Start aufgefordert, einen UNIX-Benutzernamen und ein Passwort festzulegen. Dieser Benutzer ist unabhängig von Ihrem Windows-Benutzer und nur innerhalb von WSL gültig.&lt;/p>
&lt;p>Wenn Sie bereits WSL1 verwenden, können Sie es mit den folgenden Befehlen in WSL2 konvertieren.&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"># Konvertieren Sie die vorhandene Distribution in 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"># Machen Sie WSL2 zur Standardversion für zukünftige Distributionen&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-das-geheimnis-der-ressourcenkontrolle-wslconfig-und-wslconf">4. Das Geheimnis der Ressourcenkontrolle: .wslconfig und wsl.conf
&lt;/h2>&lt;p>Eine der größten Fallen von WSL2 ist der „unbegrenzte Speicherverbrauch (Aufblähen des Vmmem-Prozesses)“. Da WSL2 den Page Cache des Linux-Kernels verwendet, verbraucht es bei jedem I/O unendlich viel Host-Speicher (Windows). Um dies zu verhindern, ist es zwingend erforderlich, Ressourcen über Konfigurationsdateien zu begrenzen.&lt;/p>
&lt;p>Es gibt zwei WSL2-Konfigurationsdateien: &lt;strong>&lt;code>.wslconfig&lt;/code>, die das gesamte Windows betrifft&lt;/strong>, und &lt;strong>&lt;code>wsl.conf&lt;/code>, die das Innere jeder Distribution betrifft&lt;/strong>.&lt;/p>
&lt;h3 id="41-wslconfig-windows-seite">4.1. .wslconfig (Windows-Seite)
&lt;/h3>&lt;p>Erstellen Sie eine Datei im Windows-Benutzerprofilverzeichnis (&lt;code>C:\Users\&amp;lt;Benutzername&amp;gt;\.wslconfig&lt;/code>), um die Ressourcenzuweisung an die VM zu steuern.&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;Benutzername&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"># Maximale Speichermenge, die der VM zugewiesen werden soll. Es werden etwa 50% bis 75% des gesamten Host-Speichers empfohlen&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"># Anzahl der zu verwendenden CPU-Kerne (alle Kerne werden verwendet, wenn weggelassen)&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"># Größe der Auslagerungsdatei&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"># Speicherort der Auslagerungsdatei (wenn Sie Speicherplatz auf dem Laufwerk C sparen möchten)&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"># Aktivieren Sie das Localhost-Forwarding (um auf WSL von der Windows-Seite über localhost zuzugreifen)&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"># Speicher automatisch freigeben (nur Windows 11)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Gibt den Page Cache dynamisch frei und verhindert ein Aufblähen von 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"># Erweiterte Netzwerkfunktionen für Windows 11 22H2 und neuer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Dies ermöglicht IPv6-Unterstützung und die gemeinsame Nutzung derselben IP-Adresse zwischen WSL und 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-linux-seite">4.2. wsl.conf (Linux-Seite)
&lt;/h3>&lt;p>Bearbeiten Sie &lt;code>/etc/wsl.conf&lt;/code> in WSL, um das distributionsspezifische Verhalten zu steuern.&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 (In WSL bearbeitet)&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"># Deaktivieren Sie die Generierung von /etc/resolv.conf, das beim Start von WSL automatisch generiert wird&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Nützlich, wenn Sie ein eigenes DNS einrichten möchten (z. B. 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"># Festlegen eines eigenen Hostnamens&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"># Einstellungen beim Mounten von Windows-Laufwerken&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"># Ändern Sie den Mount-Punkt des Laufwerks C von /mnt/c auf /c (verkürzt den Pfad)&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"># systemd aktivieren (WSL 0.67.6 und neuer)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Dadurch können snap und verschiedene Daemons (wie Docker) nativ ausgeführt werden&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"># Standardmäßig angemeldeter Benutzer&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>Um diese Einstellungen anzuwenden, müssen Sie &lt;code>wsl --shutdown&lt;/code> in PowerShell ausführen, um die WSL-VM vollständig zu stoppen, und sie dann neu starten.&lt;/p>
&lt;hr>
&lt;h2 id="5-die-ultimative-terminal-umgebung-zsh--powerlevel10k">5. Die ultimative Terminal-Umgebung: Zsh + Powerlevel10k
&lt;/h2>&lt;p>Mit der Standard-Bash allein steigt Ihre Produktivität nicht. Durch die Kombination von Zsh, das sich durch leistungsstarke Vervollständigung und Sichtbarkeit auszeichnet, mit dem ultraschnellen Thema „Powerlevel10k“, bauen wir die stärkste Eingabeaufforderung.&lt;/p>
&lt;h3 id="51-installation-und-konfiguration-von-windows-terminal">5.1. Installation und Konfiguration von Windows Terminal
&lt;/h3>&lt;p>Installieren Sie „Windows Terminal“ aus dem Microsoft Store. Öffnen Sie die JSON-Einstellungen (&lt;code>settings.json&lt;/code>), legen Sie das Standardprofil auf WSL (Ubuntu) fest und ändern Sie die Schriftart in einen Nerd Font für die Entwicklung (z.B. &lt;code>HackGen Console NF&lt;/code> oder &lt;code>MesloLGS NF&lt;/code>).&lt;/p>
&lt;h3 id="52-zsh-und-oh-my-zsh-installieren">5.2. Zsh und Oh My Zsh installieren
&lt;/h3>&lt;p>Führen Sie die folgenden Befehle im WSL-Terminal aus.&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"># Pakete aktualisieren und Zsh installieren&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"># Führen Sie das Installationsskript für Oh My Zsh aus&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-einführung-von-powerlevel10k-und-plugins">5.3. Einführung von Powerlevel10k und Plugins
&lt;/h3>&lt;p>Wir werden Plugins (Syntax-Hervorhebung und Eingabevervollständigung) und das Powerlevel10k-Thema einführen, um Zsh weiter zu verbessern.&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="o">=&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>Bearbeiten Sie &lt;code>~/.zshrc&lt;/code>, um das Thema und die Plugins zu aktivieren.&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"># Änderungen an ~/.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"># Zum Plugin-Array hinzufügen&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>Wenn Sie es speichern und &lt;code>source ~/.zshrc&lt;/code> ausführen, wird der Powerlevel10k-Konfigurationsassistent (&lt;code>p10k configure&lt;/code>) gestartet. Folgen Sie den Anweisungen auf dem Bildschirm, um Ihre bevorzugte Eingabeaufforderung (Eingabeaufforderungsstil, ob Symbole vorhanden sind, anzuzeigende Informationen usw.) anzupassen. Der Git-Zweigname und -Status, die Node.js-Version, die Ausführungszeit von Befehlen usw. werden in Echtzeit angezeigt, wodurch die Entwicklungseffizienz drastisch verbessert wird.&lt;/p>
&lt;hr>
&lt;h2 id="6-vs-code-remote---nahtlose-integration-mit-wsl">6. VS Code Remote - Nahtlose Integration mit WSL
&lt;/h2>&lt;p>Für die Entwicklung auf WSL2 gibt es eine „Remote - WSL“-Erweiterung, die Ihnen den nahtlosen Zugriff auf Dateien innerhalb von WSL von der auf der Windows-Seite installierten IDE (Visual Studio Code) ermöglicht.&lt;/p>
&lt;h3 id="erklärung-der-architektur">Erklärung der Architektur
&lt;/h3>&lt;p>Das folgende Sequenzdiagramm zeigt, wie VS Code mit WSL2 kommuniziert.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
autonumber
participant U as &amp;#34;Entwickler&amp;#34;
participant V as &amp;#34;VS Code UI (Windows)&amp;#34;
participant S as &amp;#34;VS Code Server (WSL2)&amp;#34;
participant F as &amp;#34;ext4-Dateisystem (WSL2)&amp;#34;
U-&amp;gt;&amp;gt;V: &amp;#34;Geben Sie `code .` in WSL Terminal ein&amp;#34;
V-&amp;gt;&amp;gt;S: &amp;#34;Aufbau einer RPC-Verbindung über Vsock&amp;#34;
Note over V,S: Kommunikation über Hyper-V-Sockets ohne TCP/IP
S-&amp;gt;&amp;gt;F: &amp;#34;Quelldateien lesen / Linter ausführen&amp;#34;
F--&amp;gt;&amp;gt;S: &amp;#34;Daten &amp;amp; Analyse zurückgeben&amp;#34;
S--&amp;gt;&amp;gt;V: &amp;#34;Language Server-Ergebnisse an UI streamen&amp;#34;
V--&amp;gt;&amp;gt;U: &amp;#34;Syntax-Highlighting &amp;amp; Fehler anzeigen&amp;#34;
&lt;/pre>
&lt;p>Der VS Code auf der Windows-Seite fungiert als reiner „Thin Client (UI)“, und rechenintensive Aufgaben wie der Language Server, der Debugger und die Terminal-Ausführung werden alle vom „VS Code Server“ auf der WSL-Seite erledigt. Auf diese Weise können Sie die Umgebung auf der WSL-Seite sauber halten, ohne Node.js oder Python auf der Windows-Seite zu installieren.&lt;/p>
&lt;h3 id="wesentliche-vs-code-einstellungen">Wesentliche VS Code-Einstellungen
&lt;/h3>&lt;p>Installieren Sie &lt;strong>&amp;ldquo;WSL&amp;rdquo; (ms-vscode-remote.remote-wsl)&lt;/strong> aus den &amp;ldquo;Erweiterungen&amp;rdquo; von VS Code. Navigieren Sie dann im WSL-Terminal zum Projektverzeichnis und führen Sie einfach &lt;code>code .&lt;/code> aus, um den VS Code auf der Windows-Seite mit dem geöffneten Verzeichnis zu starten.&lt;/p>
&lt;p>&lt;strong>Wichtiger Hinweis (Problem mit dem Zeilenumbruchcode):&lt;/strong>
Windows und Linux haben unterschiedliche Zeilenumbruchcodes (Windows verwendet &lt;code>CRLF&lt;/code>, Linux verwendet &lt;code>LF&lt;/code>). Bei der Entwicklung in WSL stellen Sie bitte sicher, dass die Git-Einstellung &lt;code>core.autocrlf&lt;/code> und die Standarddateieinstellungen von VS Code auf &lt;code>LF&lt;/code> vereinheitlicht werden. Wenn Sie dies versäumen, werden Sie von mysteriösen Fehlern bei der Ausführung von Shell-Skripten oder Docker-Containern geplagt.&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"># Git-Zeilenumbruchcode-Einstellung auf der WSL-Seite&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>Fügen Sie der &lt;code>settings.json&lt;/code> (Remote-Einstellung) von VS Code auch Folgendes hinzu:&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-optimierung-von-docker-desktop-und-wsl2-integration">7. Optimierung von Docker Desktop und WSL2 Integration
&lt;/h2>&lt;p>Es gibt hauptsächlich zwei Ansätze zur Verwendung von Docker in einer WSL2-Umgebung.&lt;/p>
&lt;ol>
&lt;li>Installieren Sie &lt;strong>Docker Desktop für Windows&lt;/strong> und aktivieren Sie die WSL2-Integrationsfunktion&lt;/li>
&lt;li>Installieren Sie die &lt;strong>native Docker Engine&lt;/strong> direkt innerhalb von WSL2 (z. B. Ubuntu)&lt;/li>
&lt;/ol>
&lt;h3 id="ansatz-1-docker-desktop-empfohlen">Ansatz 1: Docker Desktop (Empfohlen)
&lt;/h3>&lt;p>Dies wird in den meisten Fällen empfohlen, da es ein einfaches Management mit einer GUI und einen transparenten Zugriff auf Container zwischen Windows und WSL ermöglicht. Überprüfen Sie Folgendes in den Einstellungen von Docker Desktop (Settings).&lt;/p>
&lt;ul>
&lt;li>Aktivieren Sie &lt;code>General&lt;/code> -&amp;gt; &lt;code>Use the WSL 2 based engine&lt;/code>.&lt;/li>
&lt;li>Aktivieren Sie &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> und aktivieren Sie die zu verwendende Distribution (Ubuntu) mit der Umschaltfläche.&lt;/li>
&lt;/ul>
&lt;p>Dies ermöglicht es Ihnen, den &lt;code>docker&lt;/code>-Befehl direkt aus dem WSL2-Terminal auszuführen, und die Kommunikation mit dem Docker-Daemon erfolgt über dedizierte Lightweight-VMs (&lt;code>docker-desktop&lt;/code> und &lt;code>docker-desktop-data&lt;/code>), die von Docker Desktop verwaltet werden.&lt;/p>
&lt;h3 id="ansatz-2-direkte-installation-der-nativen-docker-engine">Ansatz 2: Direkte Installation der nativen Docker Engine
&lt;/h3>&lt;p>Wenn Sie Unternehmensnetzwerkeinschränkungen haben (z. B. um die Kosten für Docker Desktop zu vermeiden) oder den Leistungs-Overhead so weit wie möglich reduzieren möchten, aktivieren Sie &lt;code>systemd&lt;/code> in &lt;code>/etc/wsl.conf&lt;/code> und installieren Sie Docker als reinen Ubuntu-Server.&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"># Auszug aus dem offiziellen Docker-Installationsverfahren auf WSL2 Ubuntu mit aktiviertem systemd&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"># Repository hinzufügen&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"># Fügen Sie den aktuellen Benutzer zur docker-Gruppe hinzu (um ohne sudo auszuführen)&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>Nach dem Neustart funktioniert &lt;code>systemctl start docker&lt;/code> genau wie in einer nativen Linux-Umgebung und bietet hohe Leistung.&lt;/p>
&lt;hr>
&lt;h2 id="8-integration-von-ssh-schlüsseln-nahtlose-authentifizierung-in-windows-und-wsl">8. Integration von SSH-Schlüsseln: Nahtlose Authentifizierung in Windows und WSL
&lt;/h2>&lt;p>Bei der Durchführung von SSH-Klonen in Git oder Verbindungen zu Remote-Servern über SSH ist es sehr mühsam, separate SSH-Schlüssel auf der Windows- und der WSL-Seite zu verwalten. Um Sicherheit und Komfort in Einklang zu bringen, richten wir eine Brücke vom auf der Windows-Seite laufenden SSH-Agenten (oder einem Passwort-Manager wie 1Password) zur WSL-Seite ein.&lt;/p>
&lt;p>Hier erklären wir die sicherste und modernste Methode, den &lt;strong>SSH-Agenten von 1Password&lt;/strong> oder den &lt;strong>OpenSSH Authentication Agent von Windows&lt;/strong> zu verwenden und ihn mithilfe von &lt;code>npiperelay&lt;/code> oder &lt;code>socat&lt;/code> an den UNIX-Domain-Socket von WSL2 weiterzuleiten.&lt;/p>
&lt;h3 id="ssh-agent-socket-weiterleitung">ssh-agent Socket-Weiterleitung
&lt;/h3>&lt;p>Normalerweise muss der als Named Pipe (benannte Pipe) in Windows bereitgestellte SSH-Agent in eine Socket-Datei auf der WSL-Seite konvertiert werden. Dies lässt sich mithilfe von &lt;code>wsl-ssh-agent&lt;/code> oder Funktionen von 1Password leicht erreichen.&lt;/p>
&lt;p>Aktivieren Sie im Einstellungsbildschirm von 1Password &amp;ldquo;Entwickler&amp;rdquo; -&amp;gt; &amp;ldquo;SSH-Agenten verwenden&amp;rdquo;.
Fügen Sie als Nächstes die folgenden Einstellungen zur &lt;code>~/.zshrc&lt;/code> oder &lt;code>~/.bashrc&lt;/code> auf der WSL-Seite hinzu, um den Socket bei der Anmeldung automatisch zu binden.&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"># Zu ~/.zshrc hinzufügen (Beispiel für die Verwendung des 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"># Wenn der Socket beim Start von WSL nicht existiert oder der Prozess nicht gebunden ist, mit socat und npiperelay weiterleiten&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"># Starten Sie socat im Hintergrund und verbinden Sie die Named Pipe auf der Windows-Seite mit dem UNIX-Socket auf der WSL-Seite&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;p>*Vorab müssen Sie &lt;code>npiperelay.exe&lt;/code> auf der Windows-Seite installieren und den Pfad konfigurieren.&lt;/p>
&lt;p>Nach Abschluss dieser Konfiguration wird bei Ausführung von &lt;code>ssh-add -l&lt;/code> aus dem WSL-Terminal eine Liste der öffentlichen Schlüssel von SSH-Schlüsseln angezeigt, die in 1Password oder auf der Windows-Seite registriert sind. Auf diese Weise können Sie sich sicher authentifizieren, ohne die private Schlüsseldatei nach WSL kopieren zu müssen.&lt;/p>
&lt;hr>
&lt;h2 id="9-wartung-optimierung-komprimierung-von-aufgeblähten-vhdx">9. Wartung: Optimierung (Komprimierung) von aufgeblähten VHDX
&lt;/h2>&lt;p>Einer der größten Nachteile von WSL2 ist die Tatsache, dass die Dateigröße der virtuellen Festplatte (.vhdx) auf der Windows-Seite nicht automatisch reduziert wird, selbst wenn Sie Docker-Images oder Dateien löschen. Wenn Sie lange Zeit weiterentwickeln, bläht sich die Datei ext4.vhdx auf Dutzende bis Hunderte von GB auf.&lt;/p>
&lt;p>Um Speicherplatz freizugeben, müssen Sie VHDX regelmäßig von der Windows-Seite aus optimieren (komprimieren).&lt;/p>
&lt;ol>
&lt;li>Schalten Sie zunächst WSL vollständig aus.
&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>Öffnen Sie PowerShell mit Administratorrechten und führen Sie den folgenden Befehl &lt;code>diskpart&lt;/code> oder den Befehl &lt;code>Optimize-VHD&lt;/code> des Hyper-V-Moduls aus (letzteres kann nur verwendet werden, wenn Hyper-V aktiviert ist).&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"># Wenn das Hyper-V-Modul verfügbar ist&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"># Wenn Sie diskpart verwenden&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"># Geben Sie interaktiv innerhalb des folgenden Prompts ein&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;Benutzername&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>Wenn Sie diesen Vorgang regelmäßig durchführen, können Sie die auf Laufwerk C verschwendete Kapazität zurückgewinnen.&lt;/p>
&lt;hr>
&lt;h2 id="10-fazit">10. Fazit
&lt;/h2>&lt;p>WSL2 hat den Rahmen eines bloßen „Zusatz-Linux, das unter Windows läuft“ komplett überschritten und sich zu einer leistungsstarken Entwicklungsplattform entwickelt, die einer MacOS- oder nativen Linux-Maschine in nichts nachsteht oder diese sogar übertrifft.&lt;/p>
&lt;p>Durch die Anwendung aller hier erläuterten Einstellungen (Ressourcenoptimierung durch &lt;code>.wslconfig&lt;/code>, Terminalerweiterung durch Zsh + Powerlevel10k, transparenter Zugriff durch VS Code Remote sowie SSH-Integration und VHDX-Wartung) wird eine stressfreie, schnelle und sichere „ultimative Entwicklungsumgebung“ vervollständigt.&lt;/p>
&lt;p>Der Aufbau der Umgebung erfordert zwar etwas Aufwand, aber wenn Sie die Einstellungen einmal festgelegt haben, wird sich Ihre zukünftige Engineering-Produktivität zweifellos dramatisch verbessern. Erkunden Sie gerne weitere Anpassungen basierend auf diesem Leitfaden, um sie an Ihre eigenen Projekte und Vorlieben anzupassen.&lt;/p></description></item></channel></rss>