<?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/pt/tags/docker/</link><description>Recent content in Docker on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 01:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>Passos para Construir um Ambiente de Desenvolvimento Local Reprodutível usando Docker</title><link>http://kenji.blog/pt/p/docker-reproducible-local-dev-environment/</link><pubDate>Sun, 13 Sep 2026 01:00:00 +0900</pubDate><guid>http://kenji.blog/pt/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 Passos para Construir um Ambiente de Desenvolvimento Local Reprodutível usando Docker" />&lt;h2 id="1-introdução-rompendo-com-o-na-minha-máquina-funciona">1. Introdução: Rompendo com o &amp;ldquo;Na minha máquina funciona&amp;rdquo;
&lt;/h2>&lt;p>No ambiente de desenvolvimento de software, o problema de &amp;ldquo;Na minha máquina funciona&amp;rdquo; (It works on my machine), causado por diferenças de ambiente entre os desenvolvedores, tem sido um fator de desperdício de tempo em muitos projetos por um longo período. Diferenças de sistema operacional, versões de linguagens instaladas, dependências de bibliotecas e conflitos de ferramentas instaladas globalmente fazem com que o ambiente local esteja sempre exposto à &amp;ldquo;incerteza de estado&amp;rdquo;.&lt;/p>
&lt;p>O que resolve fundamentalmente esses desafios são as tecnologias de contêineres, como o &lt;strong>Docker&lt;/strong>, e o paradigma de &lt;strong>Infrastructure as Code (IaC)&lt;/strong>. Ao conteinerizar o ambiente de desenvolvimento local, é possível alcançar isolamento em nível de SO e gerenciar a versão do ambiente em si junto com a base de código.&lt;/p>
&lt;p>Neste artigo, utilizando Docker, Docker Compose e VSCode DevContainers, explicaremos de forma minuciosa os passos para construir um &lt;strong>&amp;ldquo;ambiente de desenvolvimento local reprodutível em que o estado será exatamente o mesmo, não importando quem, quando ou em qual máquina ele for iniciado&amp;rdquo;&lt;/strong>, juntamente com os profundos mecanismos técnicos por trás disso, incluindo perspectivas matemáticas.&lt;/p>
&lt;hr>
&lt;h2 id="2-a-afinidade-entre-infrastructure-as-code-iac-e-a-tecnologia-de-contêineres">2. A Afinidade entre Infrastructure as Code (IaC) e a Tecnologia de Contêineres
&lt;/h2>&lt;h3 id="princípios-do-iac-e-sua-aplicação-ao-ambiente-local">Princípios do IaC e sua Aplicação ao Ambiente Local
&lt;/h3>&lt;p>Infrastructure as Code (IaC) é a abordagem de gerenciar a configuração e o provisionamento da infraestrutura através de arquivos de definição legíveis por máquina, em vez de processos manuais. Os princípios centrais do IaC incluem os seguintes elementos:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Abordagem Declarativa (Declarative Approach)&lt;/strong>: Define &amp;ldquo;como o estado final deve ser&amp;rdquo; em vez de &amp;ldquo;como alterar o estado&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>Idempotência (Idempotency)&lt;/strong>: Não importa quantas vezes o script seja executado, o mesmo resultado (estado) é sempre garantido.&lt;/li>
&lt;li>&lt;strong>Controle de Versão (Version Control)&lt;/strong>: O estado da infraestrutura é salvo como código em um VCS, como o Git, permitindo o rastreamento do histórico de alterações e a revisão por pares.&lt;/li>
&lt;/ol>
&lt;p>Praticar IaC no ambiente de desenvolvimento local significa codificar o &amp;ldquo;estado ideal&amp;rdquo; do ambiente de desenvolvimento usando &lt;code>Dockerfile&lt;/code>, &lt;code>docker-compose.yml&lt;/code> e &lt;code>devcontainer.json&lt;/code>. Isso proporciona uma experiência de integração (onboarding) na qual os novos membros da equipe podem clonar o repositório e executar apenas um comando para começar a desenvolver imediatamente.&lt;/p>
&lt;h3 id="recursos-do-kernel-que-suportam-a-tecnologia-de-contêineres">Recursos do Kernel que Suportam a Tecnologia de Contêineres
&lt;/h3>&lt;p>A tecnologia de contêineres, diferente da virtualização baseada em hypervisor como as máquinas virtuais (VMs), é uma tecnologia de virtualização leve que isola os processos enquanto compartilha o kernel do SO hospedeiro. Para realizar isso, os seguintes recursos do kernel do Linux são usados principalmente:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Namespaces&lt;/strong>: Fornece visualizações independentes dos recursos do sistema (PID, rede, pontos de montagem, usuários, etc.) para cada processo.&lt;/li>
&lt;li>&lt;strong>Cgroups (Control Groups)&lt;/strong>: Limita e aloca os recursos físicos (CPU, memória, E/S de disco, etc.) que um processo pode usar.&lt;/li>
&lt;li>&lt;strong>UnionFS (Union File System)&lt;/strong>: Uma tecnologia que sobrepõe transparentemente várias árvores de diretórios (camadas) e as apresenta como um único sistema de arquivos. As camadas de imagem do Docker dependem dessa tecnologia.&lt;/li>
&lt;/ul>
&lt;p>Vamos considerar um modelo matemático para a restrição de recursos. Seja $M_{\text{total}}$ a capacidade total de memória da máquina host e $m_i$ o limite de memória para $n$ contêineres rodando no host. A condição necessária para que o sistema opere de forma estável, considerando a memória base $M_{\text{os}}$ consumida pelo SO host e outros processos, pode ser expressa pela seguinte inequação:&lt;/p>
$$ \sum_{i=1}^{n} m_i \le M_{\text{total}} - M_{\text{os}} $$&lt;p>Ao definir estritamente $m_i$ para cada contêiner usando Cgroups, mesmo que um contêiner específico cause um vazamento de memória, podemos evitar que o OOM (Out Of Memory) Killer derrube outros contêineres ou o sistema host inteiro.&lt;/p>
&lt;hr>
&lt;h2 id="3-design-eficiente-do-dockerfile-dominando-os-multi-stage-builds">3. Design Eficiente do Dockerfile: Dominando os Multi-stage Builds
&lt;/h2>&lt;p>O primeiro passo para um ambiente reprodutivo é o design do &lt;code>Dockerfile&lt;/code> que define o ambiente de execução da aplicação. Aqui, usando Python (FastAPI) como exemplo, explicaremos as melhores práticas para um Dockerfile seguro e leve utilizando &lt;strong>multi-stage builds&lt;/strong> (builds de múltiplos estágios).&lt;/p>
&lt;p>O multi-stage build é uma técnica que usa várias instruções &lt;code>FROM&lt;/code> em um único &lt;code>Dockerfile&lt;/code> para separar o ambiente de build (um ambiente pesado contendo compiladores e ferramentas de desenvolvimento) do ambiente de execução (um ambiente leve contendo apenas os artefatos necessários).&lt;/p>
&lt;h3 id="exemplo-prático-de-dockerfile-para-python-fastapi">Exemplo Prático de Dockerfile para Python FastAPI
&lt;/h3>&lt;p>O código a seguir é um exemplo de um &lt;code>Dockerfile&lt;/code> avançado que combina o gerenciamento de dependências com o Poetry e multi-stage builds.&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 (Ambiente de build)&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"># Configuração de variáveis de ambiente necessárias&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"># Instalação de pacotes dependentes&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"># Cópia dos arquivos de dependência e instalação&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 (Ambiente de execução)&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"># Criação de um usuário sem privilégios mínimos&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"># Copia apenas o ambiente virtual (dependências) do 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"># Cópia do código da aplicação&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"># Mudança para o usuário sem privilégios&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"># Comando padrão ao iniciar o contêiner&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="avaliação-matemática-do-tamanho-da-imagem-por-multi-stage-build">Avaliação Matemática do Tamanho da Imagem por Multi-stage Build
&lt;/h3>&lt;p>Seja $S_{\text{single}}$ o tamanho da imagem quando construída em um único estágio, e $S_{\text{multi}}$ o tamanho da imagem quando o multi-stage build é aplicado. A taxa de redução de tamanho $R$ é calculada da seguinte forma:&lt;/p>
$$ R = \left( 1 - \frac{S_{\text{multi}}}{S_{\text{single}}} \right) \times 100 \ (\%) $$&lt;p>Por exemplo, suponha que $S_{\text{single}}$ inclua a imagem base do SO (cerca de 110 MB), pacotes de desenvolvimento (como gcc, cerca de 150 MB), o próprio Poetry (cerca de 40 MB), as bibliotecas dependentes do projeto (cerca de 80 MB) e o código fonte (cerca de 5 MB), totalizando 385 MB.
Por outro lado, em $S_{\text{multi}}$, apenas as bibliotecas dependentes (80 MB) e o código fonte (5 MB) são copiados para a imagem base (110 MB), resultando em um total de 195 MB.&lt;/p>
$$ R = \left( 1 - \frac{195}{385} \right) \times 100 \approx 49.35\% $$&lt;p>Dessa forma, introduzir o multi-stage build pode reduzir o tamanho da imagem pela metade. A redução do tamanho da imagem traduz-se diretamente em tempos de pull mais curtos do registro, economia de espaço em disco e melhor segurança devido à redução da superfície de ataque (Attack Surface).&lt;/p>
&lt;hr>
&lt;h2 id="4-orquestração-de-múltiplos-contêineres-com-docker-compose">4. Orquestração de Múltiplos Contêineres com Docker Compose
&lt;/h2>&lt;p>No desenvolvimento moderno de aplicações web, arquiteturas de microsserviços em que vários componentes colaboram, como servidores web, bancos de dados e servidores de cache, são comuns. Para gerenciá-los centralmente no ambiente local, usamos o &lt;code>docker-compose.yml&lt;/code>.&lt;/p>
&lt;p>Desta vez, construiremos localmente um sistema de 3 camadas com &amp;ldquo;Web (FastAPI)&amp;rdquo;, &amp;ldquo;Database (PostgreSQL)&amp;rdquo; e &amp;ldquo;Cache (Redis)&amp;rdquo;.&lt;/p>
&lt;h3 id="diagrama-de-arquitetura-mermaid">Diagrama de Arquitetura (Mermaid)
&lt;/h3>&lt;p>O diagrama abaixo é um diagrama de blocos que representa o relacionamento entre cada contêiner, a rede e os volumes na máquina local.&lt;/p>
&lt;pre class="mermaid">
graph TD
User[&amp;#34;Máquina Host (Navegador/curl)&amp;#34;] --&amp;gt;|Localhost:8000| Web[&amp;#34;Contêiner Web FastAPI&amp;#34;]
subgraph &amp;#34;Rede Bridge do Docker (app-network)&amp;#34;
Web --&amp;gt;|Porta 5432| DB[&amp;#34;Contêiner PostgreSQL&amp;#34;]
Web --&amp;gt;|Porta 6379| Redis[&amp;#34;Contêiner Redis&amp;#34;]
end
DB --&amp;gt; Volume1[&amp;#34;Volume Nomeado (postgres_data)&amp;#34;]
Redis --&amp;gt; Volume2[&amp;#34;Volume Nomeado (redis_data)&amp;#34;]
HostDir[&amp;#34;Código Fonte do Host (./src)&amp;#34;] -.-&amp;gt;|Bind Mount| Web
&lt;/pre>
&lt;h3 id="implementação-e-explicação-detalhada-do-docker-composeyml">Implementação e Explicação Detalhada do docker-compose.yml
&lt;/h3>&lt;p>Abaixo, é mostrado um exemplo de um &lt;code>docker-compose.yml&lt;/code> robusto que pode suportar a construção de um ambiente prático.&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"># Monta o código do host como somente leitura (para hot reload)&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-volumes-e-persistência-de-dados">Volumes (Volumes) e Persistência de Dados
&lt;/h3>&lt;p>Por princípio, os contêineres são &amp;ldquo;sem estado&amp;rdquo; (stateless) e &amp;ldquo;efêmeros&amp;rdquo; (ephemeral). Quando um contêiner é destruído, os dados internos também são perdidos. Para reter dados do banco de dados ou caches, é necessário montar uma área do sistema de arquivos da máquina host no contêiner.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Bind Mount (Montagem de Ligação)&lt;/strong>: O &lt;code>./src:/app/src:ro&lt;/code> no serviço &lt;code>web&lt;/code> acima se enquadra nisso. Ele mapeia um diretório específico do host diretamente para dentro do contêiner. Usado para refletir as edições de código local imediatamente no contêiner (hot reload). Do ponto de vista de segurança, a melhor prática é adicionar a opção &lt;code>:ro&lt;/code> (Read-Only) para evitar que o código fonte do host seja modificado a partir do contêiner.&lt;/li>
&lt;li>&lt;strong>Named Volume (Volume Nomeado)&lt;/strong>: &lt;code>postgres_data&lt;/code> e &lt;code>redis_data&lt;/code> se enquadram nisso. É uma área gerenciada internamente pelo Docker (por exemplo, &lt;code>/var/lib/docker/volumes/&lt;/code>), com desempenho de E/S superior aos bind mounts e absorve as diferenças de sistema de arquivos entre os SOs. Sempre use este método para a persistência de bancos de dados.&lt;/li>
&lt;/ul>
&lt;h3 id="rede-networking-e-descoberta-de-serviços">Rede (Networking) e Descoberta de Serviços
&lt;/h3>&lt;p>O Docker Compose cria, por padrão, uma rede de ponte (bridge network) exclusiva para cada projeto. É a &lt;code>app-network&lt;/code> mencionada acima.
Contêineres pertencentes à mesma rede podem resolver nomes (resolução DNS) usando o &amp;ldquo;nome do serviço&amp;rdquo; (ex: &lt;code>db&lt;/code>, &lt;code>redis&lt;/code>) como hostname, em vez do endereço IP.
Por exemplo, do contêiner Web, é possível acessar o banco de dados pela URL &lt;code>postgresql://postgres:password@db:5432/mydb&lt;/code>. Isso torna possível alternar os destinos de conexão de forma transparente por meio de variáveis de ambiente, tanto no ambiente local quanto em produção.&lt;/p>
&lt;h3 id="verificação-de-integridade-healthcheck-e-controle-da-ordem-de-inicialização">Verificação de Integridade (Healthcheck) e Controle da Ordem de Inicialização
&lt;/h3>&lt;p>A diretiva &lt;code>depends_on&lt;/code> controla a ordem de inicialização dos contêineres, mas apenas especificar &lt;code>depends_on&lt;/code> fará com que o contêiner Web seja iniciado assim que o &amp;ldquo;contêiner do DB for iniciado&amp;rdquo;. Na realidade, o processo de inicialização do DB (início do processo do PostgreSQL e preparação das tabelas) leva vários segundos, o que pode causar erros de conexão do DB a partir do contêiner Web.
Para evitar isso, é possível definir um &lt;code>healthcheck&lt;/code> e especificar &lt;code>condition: service_healthy&lt;/code> para iniciar o contêiner Web apenas após confirmar que &amp;ldquo;o DB está em um estado em que pode aceitar requisições de conexão&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="5-gerenciamento-de-variáveis-de-ambiente-e-segurança-env">5. Gerenciamento de Variáveis de Ambiente e Segurança (.env)
&lt;/h2>&lt;p>O hardcoding de informações sensíveis, como senhas de banco de dados e chaves de API, no &lt;code>docker-compose.yml&lt;/code> é um antipadrão que deve ser evitado a todo custo. Em vez disso, usamos um arquivo de variáveis de ambiente &lt;code>.env&lt;/code> para injetar esses valores.&lt;/p>
&lt;p>Crie um arquivo &lt;code>.env&lt;/code> na raiz do projeto.&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"># Arquivo .env (Lembre-se de adicioná-lo ao .gitignore para não ser gerenciado pelo Git)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">POSTGRES_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">supersecretpassword&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">POSTGRES_DB&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">devdb&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">API_SECRET_KEY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">dev_secret_key_12345&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>O Docker Compose lê, por padrão, o arquivo &lt;code>.env&lt;/code> localizado no diretório de execução e expande os espaços reservados &lt;code>${VAR_NAME}&lt;/code> dentro do arquivo YAML. Com este método, é possível gerenciar com segurança valores de configuração diferentes para cada ambiente (como local, staging e produção) sem alterar o código da infraestrutura.&lt;/p>
&lt;hr>
&lt;h2 id="6-a-melhor-experiência-de-desenvolvimento-com-vscode-devcontainers">6. A Melhor Experiência de Desenvolvimento com VSCode DevContainers
&lt;/h2>&lt;p>Até aqui, construímos um ambiente de backend robusto usando Docker. No entanto, podemos ir um passo além. Utilizando o recurso &lt;strong>VSCode DevContainers (Remote - Containers)&lt;/strong>, torna-se possível executar o próprio backend do editor (VSCode) dentro do contêiner.&lt;/p>
&lt;p>Isso elimina a necessidade de instalar sequer o Python ou Node.js na máquina local e permite que tudo, desde linters (flake8/eslint) e formatadores (black/prettier) até extensões da IDE, seja definido dentro da base de código e compartilhado com toda a equipe.&lt;/p>
&lt;h3 id="configuração-do-devcontainerjson">Configuração do devcontainer.json
&lt;/h3>&lt;p>Crie um diretório &lt;code>.devcontainer&lt;/code> na raiz do projeto e coloque o arquivo de configuração dentro dele.&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>Ao incluir este arquivo no repositório, no momento em que você abre o projeto no VSCode, um prompt &amp;ldquo;Reopen in Container&amp;rdquo; será exibido. Com apenas um clique, todos os contêineres necessários são iniciados, as extensões são instaladas e você estará imediatamente pronto para começar a codificar. É uma experiência verdadeiramente mágica.&lt;/p>
&lt;hr>
&lt;h2 id="7-sequência-de-processamento-de-requisições-e-modelagem-de-desempenho">7. Sequência de Processamento de Requisições e Modelagem de Desempenho
&lt;/h2>&lt;p>Vamos verificar o ciclo de vida do processamento de requisições da aplicação web no ambiente de desenvolvimento local construído com um diagrama de sequência e considerar o modelo matemático de seu desempenho.&lt;/p>
&lt;h3 id="diagrama-de-sequência-fluxo-de-requisições">Diagrama de Sequência (Fluxo de Requisições)
&lt;/h3>&lt;pre class="mermaid">
sequenceDiagram
participant Client as &amp;#34;Navegador / VSCode&amp;#34;
participant Web as &amp;#34;FastAPI (Web)&amp;#34;
participant Redis as &amp;#34;Cache Redis&amp;#34;
participant DB as &amp;#34;PostgreSQL&amp;#34;
Client-&amp;gt;&amp;gt;Web: &amp;#34;GET /api/users/123&amp;#34;
activate Web
Web-&amp;gt;&amp;gt;Redis: &amp;#34;Verificar Cache para user:123&amp;#34;
activate Redis
alt &amp;#34;Cache Hit (Dados encontrados)&amp;#34;
Redis--&amp;gt;&amp;gt;Web: &amp;#34;Retornar Dados de Usuário em Cache&amp;#34;
Web--&amp;gt;&amp;gt;Client: &amp;#34;200 OK (Resposta Rápida)&amp;#34;
else &amp;#34;Cache Miss (Dados não encontrados)&amp;#34;
Redis--&amp;gt;&amp;gt;Web: &amp;#34;Nulo (Não Encontrado)&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;Retornar Linha do Banco de Dados&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 (Resposta Padrão)&amp;#34;
end
deactivate Web
&lt;/pre>
&lt;h3 id="modelo-matemático-de-atraso-de-processamento-latência">Modelo Matemático de Atraso de Processamento (Latência)
&lt;/h3>&lt;p>Modelaremos matematicamente o tempo médio de processamento de requisições $T_{\text{total}}$ no sistema acima.
A latência de cada processamento é definida a seguir:&lt;/p>
&lt;ul>
&lt;li>$T_{\text{net}}$: Latência de rede entre o cliente e o contêiner Web&lt;/li>
&lt;li>$T_{\text{app}}$: Tempo de processamento puro no lado da aplicação (como serialização)&lt;/li>
&lt;li>$T_{\text{cache}}$: Tempo gasto lendo e escrevendo no Redis&lt;/li>
&lt;li>$T_{\text{db}}$: Tempo gasto na execução de consultas ao PostgreSQL&lt;/li>
&lt;li>$p_{\text{miss}}$: Taxa de cache miss ($0 \le p_{\text{miss}} \le 1$)&lt;/li>
&lt;/ul>
&lt;p>O tempo médio de resposta é expresso pela seguinte fórmula de valor esperado:&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>No ambiente de desenvolvimento local (dentro do Docker), $T_{\text{net}}$ fica quase próximo a 0, mas o que deve ser notado é a &lt;strong>performance de E/S durante o bind mount&lt;/strong>. Especialmente ao usar o Docker Desktop no Windows/macOS, devido ao overhead de compartilhamento de arquivos entre o SO host e a VM (contêiner), $T_{\text{app}}$ (tempo de carregamento do código, etc.) tende a se tornar inflado. Para eliminar esse gargalo de desempenho, é altamente recomendada uma arquitetura que utilize DevContainers, conforme mencionado anteriormente, colocando todo o código fonte dentro de um volume nomeado ou executando a engine do Docker nativamente em um ambiente WSL2 (Windows Subsystem for Linux 2).&lt;/p>
&lt;hr>
&lt;h2 id="8-otimização-do-desempenho-do-build-do-docker-estratégia-de-cache-de-camadas">8. Otimização do Desempenho do Build do Docker: Estratégia de Cache de Camadas
&lt;/h2>&lt;p>Ao escrever um Dockerfile, entender o mecanismo de &amp;ldquo;cache de camadas&amp;rdquo; muda drasticamente o tempo de build.
O Docker cria um diferencial de sistema de arquivos (camada) para cada instrução no Dockerfile (&lt;code>FROM&lt;/code>, &lt;code>RUN&lt;/code>, &lt;code>COPY&lt;/code>, etc.) e a retém como cache. Nas reconstruções, o cache das camadas inalteradas é reutilizado.&lt;/p>
&lt;p>O princípio importante é &lt;strong>&amp;ldquo;escrever as instruções em ordem crescente da frequência de alterações&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Vamos considerar a modelagem do impacto das alterações do código fonte no tempo de build. Seja o tempo total de build $T_{\text{build}}$, o tempo de execução de cada etapa $T_{\text{layer}_i}$ e a presença ou ausência do cache hit o valor booleano $c_i \in \{0, 1\}$ (1 quando houver cache hit).&lt;/p>
$$ T_{\text{build}} = T_{\text{init}} + \sum_{i=1}^{n} (1 - c_i) \times T_{\text{layer}_i} $$&lt;p>Uma vez que ocorre um cache miss ($c_k = 0$) na camada $k$, o cache é invalidado ($c_j = 0$) para todas as camadas subsequentes $j > k$.&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"># Exemplo ruim (Copiando o código fonte primeiro)&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>Neste caso, mudar apenas uma linha de código causará um cache miss na primeira instrução &lt;code>COPY&lt;/code>, resultando na demorada instrução &lt;code>RUN poetry install&lt;/code> sendo executada a cada vez.&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"># Bom exemplo (Resolvendo as dependências primeiro)&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>Se for escrito dessa forma, mesmo que o código fonte seja alterado, o cache da camada para o &lt;code>poetry install&lt;/code> ($c_i = 1$) será efetivo, e o tempo de build será reduzido drasticamente de minutos para segundos.&lt;/p>
&lt;hr>
&lt;h2 id="9-solução-de-problemas-e-dicas-troubleshooting">9. Solução de Problemas e Dicas (Troubleshooting)
&lt;/h2>&lt;p>Aqui estão problemas comuns e soluções ao operar em um ambiente local.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Erro de Conflito de Portas&lt;/strong>
Se ocorrer um erro como &lt;code>Bind for 0.0.0.0:8000 failed: port is already allocated&lt;/code>, outro processo na máquina local está usando essa porta. Você pode evitar isso alterando o número da porta do lado do host para algo como &lt;code>ports: - &amp;quot;8080:8000&amp;quot;&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Esgotamento do Espaço em Disco&lt;/strong>
Ao usar o Docker por um longo tempo, imagens ou volumes não utilizados (Dangling Images / Volumes) podem se acumular, consumindo dezenas de GB do espaço em disco. Recomenda-se limpar regularmente o sistema com o seguinte comando:&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>Problema de Permissões de Arquivos&lt;/strong>
Ao usar bind mounts no ambiente Linux, o proprietário dos arquivos criados no contêiner será &lt;code>root&lt;/code>, e não será possível editá-los no lado do host. Você pode resolver isso criando um usuário sem privilégios no Dockerfile que coincida com o seu próprio UID/GID do SO host (ex: 1000:1000).&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="10-conclusão-a-melhoria-na-velocidade-de-desenvolvimento-trazida-pela-reprodutibilidade">10. Conclusão: A Melhoria na Velocidade de Desenvolvimento Trazida pela Reprodutibilidade
&lt;/h2>&lt;p>Ao combinar o Docker, Docker Compose e VSCode DevContainers, um ambiente de desenvolvimento local robusto é alcançado, onde &amp;ldquo;não importa quem inicie o ambiente, o estado será perfeitamente o mesmo&amp;rdquo;.&lt;/p>
&lt;p>Trazer o paradigma IaC para o ambiente local não reduz apenas o tempo de configuração inicial. Ele melhora drasticamente a velocidade e a qualidade de todo o ciclo de desenvolvimento, removendo a ansiedade em relação às mudanças de configuração da infraestrutura, facilitando a experimentação de novas pilhas de tecnologias e possibilitando uma transição suave para as pipelines de CI/CD.&lt;/p>
&lt;p>Utilize as melhores práticas explicadas neste artigo, como a otimização do tamanho da imagem por meio de multi-stage builds, controle de dependências usando healthchecks e a escrita do Dockerfile focada no cache de camadas, e, com certeza, implemente a melhor experiência de desenvolvimento (DX: Developer Experience) em seu próprio projeto.&lt;/p></description></item><item><title>Guia de Configuração Definitivo do Ambiente de Desenvolvimento para WSL2 (Windows Subsystem for Linux)</title><link>http://kenji.blog/pt/p/wsl2-ultimate-development-setup-guide/</link><pubDate>Sat, 12 Sep 2026 23:00:00 +0900</pubDate><guid>http://kenji.blog/pt/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 Guia de Configuração Definitivo do Ambiente de Desenvolvimento para WSL2 (Windows Subsystem for Linux)" />&lt;p>O &amp;ldquo;WSL2 (Windows Subsystem for Linux 2)&amp;rdquo;, que fornece um ambiente de desenvolvimento nativo do Linux no Windows, tornou-se uma ferramenta indispensável no desenvolvimento de software moderno. No entanto, há uma diferença imensa em desempenho e experiência de desenvolvimento entre usá-lo em seu estado padrão e ajustá-lo adequadamente após entender sua arquitetura.&lt;/p>
&lt;p>Neste artigo, explicaremos detalhadamente todo o processo para construir o &amp;ldquo;ambiente de desenvolvimento definitivo&amp;rdquo; exigido por engenheiros profissionais. Começando com uma explicação da arquitetura fundamental do WSL2, abordaremos configurações para maximizar o desempenho, a construção de um ambiente de terminal confortável, a integração perfeita com Docker e VS Code, e configurações avançadas de rede.&lt;/p>
&lt;hr>
&lt;h2 id="1-a-arquitetura-do-wsl2-e-a-evolução-a-partir-do-wsl1">1. A Arquitetura do WSL2 e a Evolução a partir do WSL1
&lt;/h2>&lt;p>Para extrair totalmente o potencial do WSL2, é importante primeiro entender sua estrutura interna. O WSL original (WSL1) e o WSL2 têm abordagens fundamentalmente diferentes para executar binários do Linux no Windows.&lt;/p>
&lt;h3 id="wsl1-camada-de-tradução-de-chamadas-de-sistema">WSL1: Camada de Tradução de Chamadas de Sistema
&lt;/h3>&lt;p>O WSL1 adotava um mecanismo que traduzia chamadas de sistema do Linux para a API NT do Windows em tempo real. Isso tinha a vantagem de uma sobrecarga de recursos muito baixa, já que não usava uma máquina virtual (VM). No entanto, era difícil emular perfeitamente chamadas de sistema complexas, como operações de E/S do sistema de arquivos, resultando em uma degradação de desempenho terrível ao lidar com um grande número de arquivos pequenos, como &lt;code>npm install&lt;/code> do Node.js ou operações de repositório do Git.&lt;/p>
&lt;h3 id="wsl2-vm-utilitária-leve-e-kernel-linux-completo">WSL2: VM Utilitária Leve e Kernel Linux Completo
&lt;/h3>&lt;p>No WSL2, a arquitetura foi renovada, e um kernel Linux real construído pela Microsoft agora roda diretamente em uma &lt;strong>&amp;ldquo;VM utilitária leve&amp;rdquo; que utiliza um subconjunto da arquitetura Hyper-V&lt;/strong>. Isso garante 100% de compatibilidade de chamadas de sistema, e o uso de um disco virtual (VHDX) com o sistema de arquivos ext4 nativo do Linux melhorou drasticamente o desempenho de E/S de arquivos em comparação com o WSL1.&lt;/p>
&lt;p>O diagrama Mermaid a seguir mostra as diferenças estruturais entre o WSL1 e o WSL2.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
subgraph &amp;#34;Ambiente do SO Windows&amp;#34;
A[&amp;#34;Kernel Windows NT&amp;#34;]
A --&amp;gt; F[&amp;#34;Sistema de Arquivos NTFS (Unidade C:)&amp;#34;]
end
subgraph &amp;#34;Arquitetura do WSL2&amp;#34;
B[&amp;#34;Hypervisor Hyper-V&amp;#34;]
B --&amp;gt; C[&amp;#34;VM Utilitária Leve&amp;#34;]
C --&amp;gt; D[&amp;#34;Kernel Linux (Microsoft)&amp;#34;]
D --&amp;gt; E[&amp;#34;Espaço de Usuário Ubuntu (glibc, bash, etc.)&amp;#34;]
D --&amp;gt; G[&amp;#34;Disco Virtual ext4 (.vhdx)&amp;#34;]
end
A -.-&amp;gt;|&amp;#34;Compartilhamento de Arquivos de Rede via Protocolo Plan 9 (9P)&amp;#34;| D
style B fill:#f9f,stroke:#333,stroke-width:2px
style D fill:#bbf,stroke:#333,stroke-width:2px
&lt;/pre>
&lt;p>A lição importante a ser tirada dessa estrutura é que &lt;strong>&amp;ldquo;o acesso aos arquivos no lado do Linux (dentro do VHDX) é extremamente rápido, mas o acesso aos arquivos no lado do Windows (&lt;code>/mnt/c/&lt;/code>) é muito lento porque passa pelo protocolo 9P&amp;rdquo;&lt;/strong>. O código-fonte do projeto deve ser sempre colocado no diretório inicial (&lt;code>~&lt;/code>) do lado do WSL.&lt;/p>
&lt;hr>
&lt;h2 id="2-análise-matemática-do-desempenho-por-que-o-wsl2-é-rápido">2. Análise Matemática do Desempenho: Por que o WSL2 é rápido?
&lt;/h2>&lt;p>Vamos avaliar quantitativamente a melhoria de desempenho do WSL2 usando um modelo matemático. Uma das operações mais demoradas no desenvolvimento de software é o processamento que envolve E/S de um grande número de arquivos (por exemplo, instalação de bibliotecas e compilação).&lt;/p>
&lt;p>O tempo total de execução $T_{total}$ de um determinado processo é expresso como a soma do tempo de computação pela CPU $T_{compute}$ e o tempo de E/S de disco $T_{io}$.&lt;/p>
$$ T_{total} = T_{compute} + T_{io} $$&lt;p>No caso do WSL1, ocorre uma sobrecarga ao converter as operações do lado do Linux em operações NTFS, então o tempo de E/S é modelado da seguinte forma. Aqui, $n$ é o número de operações de arquivo, $t_{ntfs\_syscall}$ é o tempo de execução da chamada de sistema do lado do Windows, e $t_{trans}$ é a sobrecarga da camada de tradução.&lt;/p>
$$ T_{wsl1\_io} = \sum_{i=1}^{n} (t_{ntfs\_syscall_i} + t_{trans_i}) $$&lt;p>Por outro lado, no caso do WSL2, o kernel emite E/S diretamente para o sistema de arquivos ext4, então a sobrecarga é apenas um pequeno atraso $t_{virt}$ devido à virtualização.&lt;/p>
$$ T_{wsl2\_io} = \sum_{i=1}^{n} (t_{ext4_i} + t_{virt_i}) $$&lt;p>Em sistemas de arquivos comuns, como $t_{ext4} \ll t_{ntfs\_syscall} + t_{trans}$, quando $n$ é muito grande (dezenas a centenas de milhares de operações de arquivo), a diferença no tempo de E/S entre o WSL1 e o WSL2 aumenta exponencialmente.&lt;/p>
&lt;p>Além disso, assumindo que a taxa de sobrecarga do cálculo da CPU em um ambiente virtualizado seja $\rho$, na virtualização mais recente assistida por hardware (Intel VT-x / AMD-V), ela fica em torno de $\rho \approx 0.01 \sim 0.03$ (1 a 3%). Portanto, mesmo em tarefas puramente computacionais, ele oferece $97\% \sim 99\%$ de desempenho comparável ao de um ambiente Linux nativo.&lt;/p>
&lt;hr>
&lt;h2 id="3-instalação-e-construção-da-base">3. Instalação e Construção da Base
&lt;/h2>&lt;p>No Windows 10/11, a instalação do WSL2 tornou-se muito simples. Basta abrir o PowerShell com privilégios de administrador e executar o seguinte comando:&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 e Ubuntu são instalados por padrão&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"># Ao especificar uma distribuição específica&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Pode ser verificado com wsl --list --online&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-install&lt;/span> &lt;span class="n">-d&lt;/span> &lt;span class="n">Ubuntu&lt;/span>&lt;span class="p">-&lt;/span>&lt;span class="mf">24.04&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Após a instalação e reinicialização, você será solicitado a configurar um nome de usuário UNIX e senha na primeira inicialização. Esse usuário é independente do usuário do Windows e é válido apenas dentro do WSL.&lt;/p>
&lt;p>Se você já estiver usando o WSL1, poderá convertê-lo para o WSL2 com os seguintes comandos:&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"># Converter uma distribuição existente para 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"># Definir o WSL2 como padrão para distribuições adicionadas no futuro&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-os-segredos-do-controle-de-recursos-wslconfig-e-wslconf">4. Os Segredos do Controle de Recursos: .wslconfig e wsl.conf
&lt;/h2>&lt;p>Uma das maiores armadilhas do WSL2 é o &amp;ldquo;consumo ilimitado de memória (inchaço do processo Vmmem)&amp;rdquo;. Como o WSL2 usa o cache de página do kernel Linux, ele consome infinitamente a memória do host (Windows) a cada E/S. Para evitar isso, é essencial limitar os recursos por meio de arquivos de configuração.&lt;/p>
&lt;p>Os arquivos de configuração do WSL2 são divididos em dois: &lt;strong>&lt;code>.wslconfig&lt;/code> que afeta todo o Windows&lt;/strong> e &lt;strong>&lt;code>wsl.conf&lt;/code> que afeta o interior de cada distribuição&lt;/strong>.&lt;/p>
&lt;h3 id="41-wslconfig-lado-do-windows">4.1. .wslconfig (Lado do Windows)
&lt;/h3>&lt;p>Crie um arquivo no diretório de perfil de usuário do Windows (&lt;code>C:\Users\&amp;lt;NomeDoUsuario&amp;gt;\.wslconfig&lt;/code>) para controlar a alocação de recursos para a VM.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># C:\Users\&amp;lt;NomeDoUsuario&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"># Quantidade máxima de memória alocada à VM. Recomenda-se cerca de 50% a 75% da memória total do host&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"># Número de núcleos de CPU a serem usados (usa todos os núcleos se omitido)&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"># Tamanho do arquivo de swap&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">swap&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">8GB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Destino de salvamento do arquivo de swap (se desejar economizar espaço na unidade C)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># swapfile=D:\\wsl\\swap.vhdx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Habilitar o encaminhamento do localhost (para acessar o WSL do lado do Windows através do localhost)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">localhostForwarding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Liberar memória automaticamente (Apenas Windows 11)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Libera dinamicamente o cache de página para evitar o inchaço do 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"># Recursos avançados de rede disponíveis no Windows 11 22H2 e posteriores&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Isso permite suporte a IPv6 e compartilhamento do mesmo endereço IP entre o WSL e o 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-lado-do-linux">4.2. wsl.conf (Lado do Linux)
&lt;/h3>&lt;p>Edite &lt;code>/etc/wsl.conf&lt;/code> dentro do WSL para controlar o comportamento específico da distribuição.&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 (Editado dentro do WSL)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[network]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Desativa a geração automática de /etc/resolv.conf na inicialização do WSL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Útil se você deseja definir um DNS personalizado (por exemplo, 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"># Define um nome de host personalizado&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"># Configurações de montagem para unidades do Windows&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">enabled&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">options&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;metadata,uid=1000,gid=1000,umask=022&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Muda o ponto de montagem da unidade C de /mnt/c para /c (encurta o caminho)&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"># Ativa o systemd (WSL 0.67.6 e posteriores)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Isso permite que snap e vários daemons (como o Docker) sejam executados nativamente&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"># Usuário de login padrão&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>Para aplicar essas configurações, você deve executar &lt;code>wsl --shutdown&lt;/code> no PowerShell para parar completamente a VM do WSL antes de reiniciar.&lt;/p>
&lt;hr>
&lt;h2 id="5-o-ambiente-de-terminal-definitivo-zsh--powerlevel10k">5. O Ambiente de Terminal Definitivo: Zsh + Powerlevel10k
&lt;/h2>&lt;p>A produtividade não aumentará se você mantiver o bash padrão. Combinaremos o Zsh, que se orgulha de funções poderosas de autocompletar e visibilidade, com o tema ultrarrápido &amp;ldquo;Powerlevel10k&amp;rdquo; para construir o prompt mais forte.&lt;/p>
&lt;h3 id="51-introdução-e-configuração-do-windows-terminal">5.1. Introdução e Configuração do Windows Terminal
&lt;/h3>&lt;p>Instale o &amp;ldquo;Windows Terminal&amp;rdquo; a partir da Microsoft Store. Abra as configurações JSON (&lt;code>settings.json&lt;/code>), defina o perfil padrão para o WSL (Ubuntu) e altere a fonte para uma Nerd Font focada em desenvolvimento (por exemplo, &lt;code>HackGen Console NF&lt;/code> ou &lt;code>MesloLGS NF&lt;/code>).&lt;/p>
&lt;h3 id="52-instalação-do-zsh-e-oh-my-zsh">5.2. Instalação do Zsh e Oh My Zsh
&lt;/h3>&lt;p>Execute os seguintes comandos no terminal do WSL:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Atualização de pacotes e instalação do Zsh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> sudo apt upgrade -y
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt install -y zsh git curl
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Executa o script de instalação do Oh My Zsh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sh -c &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-introdução-ao-powerlevel10k-e-plugins">5.3. Introdução ao Powerlevel10k e Plugins
&lt;/h3>&lt;p>Introduziremos plugins (realce de sintaxe e autocompletar) e o tema Powerlevel10k que aprimoram ainda mais o Zsh.&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>Edite &lt;code>~/.zshrc&lt;/code> para ativar o tema e os plugins.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Alterações em ~/.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"># Adicionar ao array de plugins&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">plugins&lt;/span>&lt;span class="o">=(&lt;/span>git zsh-autosuggestions zsh-syntax-highlighting&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ao salvar e executar &lt;code>source ~/.zshrc&lt;/code>, o assistente de configuração do Powerlevel10k (&lt;code>p10k configure&lt;/code>) será iniciado. Siga as instruções na tela para personalizar o prompt ao seu gosto (estilo do prompt, presença de ícones, informações a serem exibidas, etc.). O nome e o status do branch do Git, a versão do Node.js, o tempo de execução do comando, entre outros, serão exibidos em tempo real, melhorando drasticamente a eficiência do desenvolvimento.&lt;/p>
&lt;hr>
&lt;h2 id="6-vs-code-remote---integração-perfeita-com-o-wsl">6. VS Code Remote - Integração Perfeita com o WSL
&lt;/h2>&lt;p>No desenvolvimento com o WSL2, a extensão &amp;ldquo;Remote - WSL&amp;rdquo; é o mecanismo que permite o acesso perfeito aos arquivos dentro do WSL a partir do IDE (Visual Studio Code) instalado no lado do Windows.&lt;/p>
&lt;h3 id="explicação-da-arquitetura">Explicação da Arquitetura
&lt;/h3>&lt;p>O diagrama de sequência a seguir mostra como o VS Code se comunica com o WSL2.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
autonumber
participant U as &amp;#34;Desenvolvedor&amp;#34;
participant V as &amp;#34;IU do VS Code (Windows)&amp;#34;
participant S as &amp;#34;Servidor VS Code (WSL2)&amp;#34;
participant F as &amp;#34;Sistema de Arquivos ext4 (WSL2)&amp;#34;
U-&amp;gt;&amp;gt;V: &amp;#34;Digitar `code .` no Terminal WSL&amp;#34;
V-&amp;gt;&amp;gt;S: &amp;#34;Estabelecer Conexão RPC via Vsock&amp;#34;
Note over V,S: Comunica-se por soquetes Hyper-V sem usar TCP/IP
S-&amp;gt;&amp;gt;F: &amp;#34;Ler Arquivos de Origem / Executar Linter&amp;#34;
F--&amp;gt;&amp;gt;S: &amp;#34;Retornar Dados e Análise&amp;#34;
S--&amp;gt;&amp;gt;V: &amp;#34;Transmitir resultados do Servidor de Idioma para a IU&amp;#34;
V--&amp;gt;&amp;gt;U: &amp;#34;Exibir realce de sintaxe e erros&amp;#34;
&lt;/pre>
&lt;p>O VS Code no lado do Windows funciona como um mero &amp;ldquo;cliente fino (IU)&amp;rdquo;, e todos os processos pesados como Servidor de Linguagem (Language Server), depurador e execução no terminal são tratados pelo &amp;ldquo;VS Code Server&amp;rdquo; no lado do WSL. Isso permite que você mantenha seu ambiente limpo usando apenas o lado do WSL, sem ter que instalar o Node.js ou Python no lado do Windows.&lt;/p>
&lt;h3 id="configurações-essenciais-do-vs-code">Configurações Essenciais do VS Code
&lt;/h3>&lt;p>Instale a extensão &lt;strong>&amp;ldquo;WSL&amp;rdquo; (ms-vscode-remote.remote-wsl)&lt;/strong> a partir de &amp;ldquo;Extensões&amp;rdquo; no VS Code. Em seguida, navegue até o diretório do seu projeto no terminal do WSL e simplesmente execute &lt;code>code .&lt;/code> para iniciar o VS Code no lado do Windows com esse diretório aberto.&lt;/p>
&lt;p>&lt;strong>Nota importante (Problema com o código de quebra de linha):&lt;/strong>
Windows e Linux usam códigos de quebra de linha diferentes (Windows usa &lt;code>CRLF&lt;/code>, Linux usa &lt;code>LF&lt;/code>). Ao desenvolver no WSL, certifique-se de unificar a configuração &lt;code>core.autocrlf&lt;/code> do Git e as configurações padrão de arquivos do VS Code para &lt;code>LF&lt;/code>. Se não fizer isso, você poderá sofrer com erros misteriosos ao executar scripts de shell ou contêineres Docker.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Configuração do código de quebra de linha do Git no lado do WSL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git config --global core.autocrlf input
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Adicione também o seguinte ao &lt;code>settings.json&lt;/code> (configurações remotas) do VS 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;/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-otimização-do-docker-desktop-e-integração-wsl2">7. Otimização do Docker Desktop e Integração WSL2
&lt;/h2>&lt;p>Para usar o Docker no ambiente WSL2, existem principalmente duas abordagens:&lt;/p>
&lt;ol>
&lt;li>Instalar o &lt;strong>Docker Desktop for Windows&lt;/strong> e ativar o recurso de integração com o WSL2&lt;/li>
&lt;li>Instalar o &lt;strong>Docker Engine nativo&lt;/strong> diretamente dentro do WSL2 (Ubuntu, etc.)&lt;/li>
&lt;/ol>
&lt;h3 id="abordagem-1-docker-desktop-recomendado">Abordagem 1: Docker Desktop (Recomendado)
&lt;/h3>&lt;p>Esta abordagem é recomendada na maioria dos casos porque facilita o gerenciamento via GUI e o acesso transparente a contêineres entre Windows/WSL. Verifique o seguinte nas Configurações (Settings) do Docker Desktop:&lt;/p>
&lt;ul>
&lt;li>Em &lt;code>General&lt;/code>, marque a opção &lt;code>Use the WSL 2 based engine&lt;/code>.&lt;/li>
&lt;li>Em &lt;code>Resources&lt;/code> -&amp;gt; &lt;code>WSL Integration&lt;/code>, marque a opção &lt;code>Enable integration with my default WSL distro&lt;/code> e ligue a chave seletora para a distribuição (Ubuntu) a ser usada.&lt;/li>
&lt;/ul>
&lt;p>Isso permite que o comando &lt;code>docker&lt;/code> seja executado diretamente do terminal do WSL2, e a comunicação com o daemon do Docker ocorra por meio de uma VM leve dedicada (&lt;code>docker-desktop&lt;/code> e &lt;code>docker-desktop-data&lt;/code>) gerenciada pelo Docker Desktop.&lt;/p>
&lt;h3 id="abordagem-2-instalação-direta-do-docker-engine-nativo">Abordagem 2: Instalação Direta do Docker Engine Nativo
&lt;/h3>&lt;p>Se houver restrições de rede corporativa (como evitar taxas de licenciamento do Docker Desktop) ou se você quiser reduzir ao máximo a sobrecarga de desempenho, ative o &lt;code>systemd&lt;/code> em &lt;code>/etc/wsl.conf&lt;/code> e instale o Docker como um servidor Ubuntu puro.&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"># Trecho do procedimento oficial de instalação do Docker no Ubuntu WSL2 com systemd ativado&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"># Adição do repositório&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"># Adicionar o usuário atual ao grupo docker (para executar sem sudo)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo usermod -aG docker &lt;span class="nv">$USER&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Após a reinicialização, o &lt;code>systemctl start docker&lt;/code> funcionará exatamente como em um ambiente Linux nativo, oferecendo alto desempenho.&lt;/p>
&lt;hr>
&lt;h2 id="8-integração-da-chave-ssh-autenticação-perfeita-entre-windows-e-wsl">8. Integração da Chave SSH: Autenticação Perfeita entre Windows e WSL
&lt;/h2>&lt;p>Ao clonar repositórios Git via SSH ou conectar-se a servidores remotos via SSH, é muito trabalhoso gerenciar chaves SSH separadamente nos lados do Windows e do WSL. Para equilibrar segurança e conveniência, configuraremos uma ponte entre o agente SSH em execução no lado do Windows (ou um gerenciador de senhas como o 1Password) e o lado do WSL.&lt;/p>
&lt;p>Aqui, explicaremos o método de usar a &lt;strong>funcionalidade de agente SSH do 1Password&lt;/strong> ou o &lt;strong>OpenSSH Authentication Agent do Windows&lt;/strong> como a abordagem mais segura e moderna, encaminhando-o para o soquete de domínio UNIX do WSL2 usando &lt;code>npiperelay&lt;/code> e &lt;code>socat&lt;/code>.&lt;/p>
&lt;h3 id="encaminhamento-de-soquete-do-ssh-agent">Encaminhamento de Soquete do ssh-agent
&lt;/h3>&lt;p>O agente SSH, que normalmente é fornecido como um Named Pipe (pipe nomeado) no Windows, deve ser convertido em um arquivo de soquete no lado do WSL. É fácil fazer isso usando recursos fornecidos pelo &lt;code>wsl-ssh-agent&lt;/code> ou pelo 1Password.&lt;/p>
&lt;p>Na tela de configurações do 1Password, ative &amp;ldquo;Developer&amp;rdquo; -&amp;gt; &amp;ldquo;Usar Agente SSH&amp;rdquo;.
Em seguida, adicione as seguintes configurações ao &lt;code>~/.zshrc&lt;/code> ou &lt;code>~/.bashrc&lt;/code> do lado do WSL para vincular automaticamente o soquete ao fazer login.&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"># Adição ao ~/.zshrc (Exemplo ao usar o 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"># Encaminhar usando socat e npiperelay se o soquete não existir ou o processo não estiver vinculado quando o WSL iniciar&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"># Inicia o socat em segundo plano e conecta o Named Pipe do lado do Windows ao soquete UNIX do lado do WSL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>setsid socat UNIX-LISTEN:&lt;span class="nv">$SSH_AUTH_SOCK&lt;/span>,fork EXEC:&lt;span class="s2">&amp;#34;npiperelay.exe -ei -s //./pipe/openssh-ssh-agent&amp;#34;&lt;/span>,nofork &lt;span class="p">&amp;amp;&lt;/span>&lt;span class="o">)&lt;/span> &amp;gt;/dev/null 2&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>É necessário instalar o &lt;code>npiperelay.exe&lt;/code> no lado do Windows e adicionar seu caminho ao PATH antecipadamente.&lt;/li>
&lt;/ul>
&lt;p>Quando essa configuração estiver concluída, a execução de &lt;code>ssh-add -l&lt;/code> a partir do terminal do WSL exibirá uma lista de chaves públicas das chaves SSH registradas no 1Password ou no lado do Windows. Isso permite que você passe pela autenticação com segurança, sem copiar arquivos de chave privada para dentro do WSL.&lt;/p>
&lt;hr>
&lt;h2 id="9-manutenção-otimização-compactação-de-vhdx-inchado">9. Manutenção: Otimização (Compactação) de VHDX Inchado
&lt;/h2>&lt;p>Uma das maiores falhas do WSL2 é a especificação de que &amp;ldquo;mesmo se você excluir imagens do Docker ou arquivos, o tamanho do arquivo do disco virtual do lado do Windows (.vhdx) não será reduzido automaticamente&amp;rdquo;. Após um longo período de desenvolvimento, o arquivo ext4.vhdx pode inchar para dezenas a centenas de gigabytes.&lt;/p>
&lt;p>Para liberar espaço em disco, você deve otimizar (Compactar) periodicamente o VHDX no lado do Windows.&lt;/p>
&lt;ol>
&lt;li>Primeiro, desligue completamente o WSL.
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-shutdown&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>Abra o PowerShell com privilégios de administrador e execute o comando &lt;code>diskpart&lt;/code> a seguir ou o comando &lt;code>Optimize-VHD&lt;/code> do módulo Hyper-V (o último só pode ser usado se o Hyper-V estiver ativado).&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"># Quando o módulo Hyper-V está disponível&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"># Quando usar o diskpart&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">diskpart&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Digite interativamente no prompt abaixo&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;NomeDoUsuario&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>Ao executar essa operação regularmente, você pode recuperar o espaço consumido desnecessariamente na unidade C.&lt;/p>
&lt;hr>
&lt;h2 id="10-conclusão">10. Conclusão
&lt;/h2>&lt;p>O WSL2 transcendeu completamente o quadro de ser apenas um &amp;ldquo;Linux de bônus rodando no Windows&amp;rdquo; e evoluiu para uma plataforma de desenvolvimento poderosa que rivaliza ou até supera o MacOS ou máquinas Linux nativas.&lt;/p>
&lt;p>Ao aplicar todas as configurações explicadas desta vez (otimização de recursos com &lt;code>.wslconfig&lt;/code>, aprimoramento de terminal com Zsh + Powerlevel10k, acesso transparente com VS Code Remote e integração SSH e manutenção de VHDX), o &amp;ldquo;ambiente de desenvolvimento definitivo&amp;rdquo; livre de estresse, rápido e seguro estará completo.&lt;/p>
&lt;p>Demora um pouco para configurar o ambiente, mas uma vez que você consolide suas configurações, não há dúvida de que sua produtividade em engenharia melhorará drasticamente de agora em diante. Sinta-se à vontade para explorar mais personalizações com base neste guia para atender aos seus próprios projetos e preferências.&lt;/p></description></item></channel></rss>