<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Chainguard on Crimideias do caioau</title>
    <link>https://caioau.net/tags/chainguard/</link>
    <description>Recent content in Chainguard on Crimideias do caioau</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>pt-br</language>
    <copyright>This site is licensed under a CC-BY-SA 4.0 licence</copyright>
    <lastBuildDate>Mon, 16 Feb 2026 10:00:00 -0300</lastBuildDate><atom:link href="https://caioau.net/tags/chainguard/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Dockerfile: Hardening e boas práticas</title>
      <link>https://caioau.net/blog/dockerfile-hardening/</link><category>computando-arte</category>
		  <category>texto</category>
		  <category>devops</category>
		  <category>docker</category>
		  <category>security</category>
		  <category>sbom</category>
		  <category>chainguard</category>
		  
      <pubDate>Mon, 16 Feb 2026 10:00:00 -0300</pubDate>
      
      <guid>https://caioau.net/blog/dockerfile-hardening/</guid><description>&lt;p&gt;Obs.: Originalmente publicado no &lt;a href=&#34;https://caioau.net/blog/computando-arte/&#34;&gt;computando-arte&lt;/a&gt; dia 28Jan2026&lt;/p&gt;
&lt;p&gt;Dockerfile é tudo igual? Se a imagem está sendo buildada e a aplicação está rodando, posso mandar bala? Vamos ver nesse texto que não. Existem outras considerações a serem feitas, principalmente de segurança. Vamos nos debruçar para encontrar o Dockerfile mínimo contendo apenas o necessário para rodar nosso app em Python.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/feature-img.png&#34; loading=&#34;lazy&#34;
         alt=&#34;Foto de S. Laiba Ali, unsplash&#34; width=&#34;600px&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;Foto de S. Laiba Ali, &lt;a href=&#34;https://unsplash.com/photos/blue-red-green-and-yellow-lego-blocks-zncK6BaaDgo&#34;&gt;unsplash&lt;/a&gt;&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;nosso-exemplo-api-em-python-com-flask&#34;&gt;Nosso exemplo: API em Python com Flask&lt;/h2&gt;
&lt;p&gt;Nesse texto vamos explorar bastante esse exemplo, que retorna um &amp;ldquo;Hello world&amp;rdquo; simples, e pra fazer uma graça um endpoint que retorna de volta o que foi enviado no caminho da url.&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d75f00&#34;&gt;from&lt;/span&gt; flask &lt;span style=&#34;color:#d75f00&#34;&gt;import&lt;/span&gt; Flask
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app = Flask(__name__)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;@app.route&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;hello_default&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5f8700&#34;&gt;return&lt;/span&gt; hello(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;@app.route&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/hello/&amp;lt;string:hellomsg&amp;gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;hello&lt;/span&gt;(hellomsg: &lt;span style=&#34;color:#0087ff&#34;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#0087ff&#34;&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    res = &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;hello world!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5f8700&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;len&lt;/span&gt;(hellomsg) &amp;gt; &lt;span style=&#34;color:#00afaf&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        res = hellomsg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5f8700&#34;&gt;return&lt;/span&gt; res
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;if&lt;/span&gt; __name__ == &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    app.run(host=&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
app.py&lt;/p&gt;
&lt;p&gt;Pra quem quiser brincar com eles, todos os códigos e arquivos utilizados nesse texto estão disponíveis no seguinte repositório &lt;a href=&#34;https://gitlab.com/caioau/caioau.gitlab.io/-/tree/master/static/blog/dockerfile-hardening/exemplo?ref_type=heads&#34;&gt;gitlab.com/caioau/caioau.gitlab.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Junto do Dockerfile temos o nosso requirements.txt:&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Flask~=3.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gunicorn~=23.0.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
requirements.txt&lt;/p&gt;
&lt;p&gt;Para quem não está familiarizado com a notação ~= estamos usando apontando para versão compatível, como as bibliotecas utilizam versionamento semântico (&lt;a href=&#34;https://semver.org/lang/pt-BR/&#34;&gt;semver.org&lt;/a&gt;) vamos utilizar versões mais novas mas dentro do mesmo menor (minor), mas sem mudanças que quebrem as funcionalidades atuais. A linha Flask~=3.1.2 equivale a Flask&amp;gt;=3.1.2,Flask==3.1.*&lt;/p&gt;
&lt;h2 id=&#34;dockerfile-v0&#34;&gt;Dockerfile v0&lt;/h2&gt;
&lt;p&gt;Com o código-fonte do nosso app, podemos seguir com o Dockerfile.&lt;/p&gt;
&lt;p&gt;A fim de ajudar no debug do app, vamos incluir o vim e curl nas imagens.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; debian:bullseye&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; apt-get update &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    apt-get install -y &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    python3-pip python3-dev &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    build-essential &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    curl &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    vim
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; apt-get clean &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /usr/src/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; . /usr/src/app/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; pip3 install -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; rm -rf ~/.cache/pip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; 8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;CMD&lt;/span&gt; [ &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;gunicorn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-w&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-b&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;0.0.0.0:8000&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--access-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--error-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;app:app&amp;#34;&lt;/span&gt; ]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dockerfile-v0&lt;/p&gt;
&lt;p&gt;O que está acontecendo? Utilizando uma imagem base do Debian, instalamos o Python com outros pacotes que fazem a compilação (build-essential e python3-dev). E daí na próxima instrução deletamos o índice do apt-get.&lt;/p&gt;
&lt;p&gt;Mudamos a pasta de trabalho (WORKDIR) e copiamos o código-fonte da aplicação lá, instalamos as dependências da aplicação e similarmente com os índices do apt-get deletamos o cache do pip.&lt;/p&gt;
&lt;p&gt;Por fim, configuramos o comando que sobe a aplicação, utilizando o gunicorn como servidor web Python.&lt;/p&gt;
&lt;p&gt;Quando colocamos para rodar a imagem, a aplicação funciona \o/&lt;/p&gt;
&lt;p&gt;Porém, além de outros problemas de que vamos falar logo, o tamanho da imagem: 570MB, tá bom pra você quase 600 megabytes por um simples hello world?&lt;/p&gt;
&lt;p&gt;Fica até o final, porque &lt;del&gt;vai ter bolo&lt;/del&gt; vamos reduzir o tamanho dessa imagem para 10x menor.&lt;/p&gt;
&lt;p&gt;Observação: Nesse texto, quando estivermos falando do tamanho da imagem, estamos nos referindo ao tamanho sem compressão, ou seja, o valor reportado por docker image ls, ao passo que o tamanho que aparece na página WEB no dockerhub ou outros registries é o tamanho com compressão. Por exemplo, uma imagem de 522 MB sem compressão resulta em 192 MB com compressão.&lt;/p&gt;
&lt;h2 id=&#34;dissecando-imagens-com-dive&#34;&gt;Dissecando imagens com dive&lt;/h2&gt;
&lt;p&gt;A nossa primeira dica é usar o dive para &amp;ldquo;dissecar&amp;rdquo; a imagem. Uma vez carregada, conseguimos acompanhar como estão os arquivos, então podemos ir &amp;ldquo;caminhando&amp;rdquo; a partir da camada inicial até a final como os arquivos foram sendo alterados e dessa forma conseguimos mais facilmente visualizar o que está acontecendo e identificar pontos de melhoria.&lt;/p&gt;
&lt;p&gt;Para instalar, basta baixar o binário do github: &lt;a href=&#34;https://github.com/wagoodman/dive&#34;&gt;github.com/wagoodman/dive&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Com ele instalado basta executar com o nome da imagem&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/dive.gif&#34; loading=&#34;lazy&#34; width=&#34;800px&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Bora ver como o dive analisa nossa imagem? Carregando ele podemos o histórico das instruções do nosso Dockerfile, cada instrução gera uma camada e vamos caminhando nesse histórico. Como são muitos arquivos na imagem base, podemos mostrar apenas os arquivos modificados (pressionando Ctrl+U). Vamos retomar esse ponto importante, mas preste atenção na instrução &lt;code&gt;COPY . .&lt;/code&gt; quais arquivos são copiados, além do código-fonte.&lt;/p&gt;
&lt;p&gt;Com a imagem analisada percebemos dois erros: os índices do apt e o cache do pip não foram limpos, aumentando o tamanho da imagem final desnecessariamente. Isso aconteceu pois a deleção dos arquivos não está na mesma instrução (RUN) do que a criação deles, propagando para a próxima camada.&lt;/p&gt;
&lt;p&gt;Repare no canto inferior esquerdo que a ferramenta dá algumas dicas de onde melhorar, para a imagem ficar mais eficiente.&lt;/p&gt;
&lt;h2 id=&#34;use-dockerignore&#34;&gt;Use dockerignore&lt;/h2&gt;
&lt;p&gt;O outro erro da nossa v0 foi que alguns arquivos sensíveis vazaram, em particular o arquivo .env com credenciais. Isso aconteceu pois quando copiamos os arquivos em COPY . . todos arquivos no contexto do docker são copiados.&lt;/p&gt;
&lt;p&gt;Como resolver? Podemos colocar tudo o que podemos copiar no Docker dentro de uma pasta dedicada, mas teríamos que manter esse controle.&lt;/p&gt;
&lt;p&gt;Uma solução mais robusta é utilizar o arquivo .dockerignore (&lt;a href=&#34;https://docs.docker.com/build/concepts/context/#dockerignore-files&#34;&gt;documentação&lt;/a&gt;), que funciona de uma forma similar ao .gitignore, limitando a quais arquivos é permitido o acesso no contexto Docker.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# ignora tudo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# permite codigos fonte
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;!/src
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;!*.py
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;!requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;!entrypoint.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# especifico do python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;**/__pycache__/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;**/*.py[cod]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# C extensions
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*.so
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;**/.ipynb_checkpoints/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;.dockerignore&lt;/p&gt;
&lt;p&gt;Acima temos um exemplo de dockerignore que resolve nosso problema, onde todos os arquivos são por padrão bloqueados, e então vamos criando exceções como arquivos de código-fonte.&lt;/p&gt;
&lt;h2 id=&#34;dockerfile-v1&#34;&gt;Dockerfile v1&lt;/h2&gt;
&lt;p&gt;Com as lições aprendidas na versão anterior, bora arrumar os erros que encontramos?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; debian:bullseye&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; apt-get update &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    apt-get install -y --no-install-recommends &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    python3-pip python3-dev python3-venv &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    build-essential &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    curl &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    vim &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    apt-get clean &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; useradd -u &lt;span style=&#34;color:#00afaf&#34;&gt;1000&lt;/span&gt; -U -m --shell /bin/bash python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/python/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --chown=python:python . /home/python/app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; python3 -m venv .venv &amp;amp;&amp;amp; . .venv/bin/activate &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    pip3 install --no-cache-dir -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ENV&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;PATH&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/home/python/app/.venv/bin:&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#4e4e4e&#34;&gt;# &amp;#34;ativa&amp;#34; o venv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; 8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;CMD&lt;/span&gt; [ &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;gunicorn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-w&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-b&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;0.0.0.0:8000&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--access-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--error-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;app:app&amp;#34;&lt;/span&gt; ]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dockerfile-v1&lt;/p&gt;
&lt;p&gt;O que mudamos da versão anterior? Colocamos a deleção dos arquivos desnecessários na mesma instrução (no caso do pip install utilizamos a opção &amp;ndash;no-cache-dir).&lt;/p&gt;
&lt;p&gt;Também usamos um ambiente virtual (venv) para melhor lidar com as dependências Python.&lt;/p&gt;
&lt;p&gt;E por fim, para não rodar como root, criamos um usuário não root e o utilizamos sempre que possível. Se atente que o pip install foi executado como não root.&lt;/p&gt;
&lt;p&gt;E o tamanho? Apesar de só termos mexido no cache do pip e os índices, a nova imagem é tem 520MB , aproximadamente 50MB menor (~10%).&lt;/p&gt;
&lt;h2 id=&#34;user-não-root-basta&#34;&gt;User não root basta?&lt;/h2&gt;
&lt;p&gt;Criamos um usuário não root e paramos de usar o root, mas isso basta? A resposta é não, pois caso a aplicação esteja comprometida, o ataque pode usar qualquer binário presente na imagem para realizar ações mal-intencionadas. Um excelente site explorando isso é o &lt;a href=&#34;https://gtfobins.github.io/&#34;&gt;GTFOBins&lt;/a&gt; que mostra como fazer essas explorações para cada binário.&lt;/p&gt;
&lt;p&gt;Outro argumento é o princípio do privilégio mínimo que dita que devemos apenas usar as permissões mínimas necessárias para o funcionamento dos nossos sistemas, caso contrário as permissões excedentes podem ser abusadas.&lt;/p&gt;
&lt;p&gt;Bora para uma revisão rápida de permissão de arquivos no Linux? O octeto de permissão é definido pelas permissões (do mais significativo para menos) ler (Read), escrever (Write) e executar (eXecute). E temos esse octeto três vezes (da esquerda pra direita): Para o dono, para o grupo e para outros.&lt;/p&gt;
&lt;p&gt;Bora para um exemplo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;O dono vai poder ler (4), escrever (2) e executar (1) -&amp;gt; 4 + 2 + 1 = 7&lt;/li&gt;
&lt;li&gt;O grupo vai poder ler (4) e executar (1) -&amp;gt; 4 + 1 = 5&lt;/li&gt;
&lt;li&gt;Por fim outros vão poder apenas ler (4) -&amp;gt; 4&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Resultado: Executando chmod 754 vai gerar o resultado que queremos.&lt;/p&gt;
&lt;p&gt;Até aí tudo bem, mas além desses 3 dígitos tem um quarto dígito, normalmente omitido, à esquerda que define mais um octeto o Suid , Guid e o Sticky Bit. Se a gente setar o suid no nosso exemplo anterior, a permissão que tínhamos 754 vira 4754 (adicionando o 4 à esquerda).&lt;/p&gt;
&lt;p&gt;E o que faz esse suid? Quando setado o arquivo quando executado não é executado por quem executa, mas por quem é dono do arquivo, que tipicamente é o root, ou seja, qualquer usuário &amp;ldquo;vira root&amp;rdquo; (o sudo funciona assim).&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/commitstrip-chmod.png&#34; loading=&#34;lazy&#34;
         alt=&#34;commitstrip.com/en/2016/06/29/chmod-what/&#34; width=&#34;500px&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;a href=&#34;https://www.commitstrip.com/en/2016/06/29/chmod-what/&#34;&gt;commitstrip.com/en/2016/06/29/chmod-what/&lt;/a&gt;&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Bora mostrar na prática?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; debian:bullseye&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; cp /bin/bash /bin/bash-suid &amp;amp;&amp;amp; chmod u+s /bin/bash-suid
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; useradd -u &lt;span style=&#34;color:#00afaf&#34;&gt;1000&lt;/span&gt; -U -m --shell /bin/bash python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/python/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dockerfile-setuid&lt;/p&gt;
&lt;p&gt;No dockerfile acima criamos um novo bash chamado bash-uid, com a permissão suid, agora mesmo que estejamos rodando como um usuário não root, se invocado esse bash especial escalamos o privilégio para root.&lt;/p&gt;
&lt;p&gt;Para desarmar essa possibilidade, suba o container com a opção &lt;strong&gt;no-new-privileges&lt;/strong&gt; que efetivamente protege contra a escalação de privilégio.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/demo-suid.png&#34; loading=&#34;lazy&#34;
         alt=&#34;demonstrando o setuid&#34; width=&#34;800px&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;demonstrando o setuid&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Repare que quando executamos o bash especial efetivamente se tornamos root, porém com a opção no-new-privileges habilitada resolvemos o problema.&lt;/p&gt;
&lt;p&gt;Para outras boas práticas de segurança para containers docker consulte a excelente cartilha da OWASP (comunidade que publica diversas boas práticas de segurança para aplicações web): &lt;a href=&#34;https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html&#34;&gt;OWASP Docker Security Cheat Sheet&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;dockerfile-v2-introduzindo-multistage&#34;&gt;Dockerfile v2: introduzindo multistage&lt;/h2&gt;
&lt;p&gt;Até então estamos instalando compiladores necessários para o pip install, utilizando o pacote build-essential, porém em tempo de execução os mesmos não são necessários, esse é o cenário que a funcionalidade do multi-stage do docker resolve.&lt;/p&gt;
&lt;p&gt;O multi-stage acontece quando utilizamos a instrução FROM múltiplas vezes, criando estágios separados, tipicamente para o build e um estágio final utilizado em tempo de execução, dessa forma os artefatos resultantes do build são passados pro estágio final, e os compiladores e outras ferramentas do build são instalados apenas no estágio de build, resultando uma imagem final menor.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; python:3.13 AS builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; useradd -u &lt;span style=&#34;color:#00afaf&#34;&gt;1000&lt;/span&gt; -U -m --shell /bin/bash python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/python/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --chown=python:python . /home/python/app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; python3 -m venv .venv &amp;amp;&amp;amp; . .venv/bin/activate &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    pip3 install --no-cache-dir -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; python:3.13-slim AS runtime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; useradd -u &lt;span style=&#34;color:#00afaf&#34;&gt;1000&lt;/span&gt; -U -m --shell /bin/bash python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/python/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --chown=python:python --from=builder /home/python/app/ /home/python/app/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ENV&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;PATH&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/home/python/app/.venv/bin:&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; 8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;CMD&lt;/span&gt; [ &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;gunicorn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-w&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-b&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;0.0.0.0:8000&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--access-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--error-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;app:app&amp;#34;&lt;/span&gt; ]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dockerfile-v2&lt;/p&gt;
&lt;p&gt;Dessa vez optamos por usar as imagens oficiais do python, então não precisamos instalar o python em si e os compiladores que precisamos em tempo de build. Agora o grande pulo do gato do multi-stage, as imagens de build e runtime são diferentes, a de build (python:3.13) têm 1.1GB e a de runtime (python:3.13-slim) aproximadamente 10% do seu tamanho com 120MB.&lt;/p&gt;
&lt;p&gt;Outra mudança na imagem base, até então estávamos usando a release bullseye do Debian, mas consultando o &lt;a href=&#34;https://endoflife.date/&#34;&gt;endoflife.date&lt;/a&gt; podemos ver que essa release perdeu suporte principal, agora com a imagem python a tag 3.13 aponta para a release corrente do stable do Debian. Além de usarmos a variante slim da imagem do debian, sempre que possível opte por essa opção.&lt;/p&gt;
&lt;p&gt;Uma dica valiosa para sempre manter suas dependências atualizadas é utilizar o dependabot ou similares como o renovate, que periodicamente atualiza as dependências automaticamente abrindo um pull request com a atualização.&lt;/p&gt;
&lt;p&gt;Como ficou o tamanho? Essa versão ficou com 130 MB, um quarto da nossa primeira versão.&lt;/p&gt;
&lt;h2 id=&#34;fazendo-nosso-app-em-golang&#34;&gt;Fazendo nosso app em Golang&lt;/h2&gt;
&lt;p&gt;Até agora estávamos usando Python no nosso app, porém para o próximo conceito de imagens distroless, usar uma linguagem compilada, em particular Go, pois ele permite a compilação estática, ou seja toda a aplicação fica &amp;ldquo;empacotada&amp;rdquo; em apenas um binário, sem precisar de outros arquivos/pacotes para que a nossa app funcione.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;42
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;45
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;46
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;47
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;48
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;49
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;50
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;51
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;52
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;53
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;54
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;55
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;56
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;57
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;58
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;59
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;60
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;61
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;62
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;63
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;64
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;65
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-golang&#34; data-lang=&#34;golang&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d75f00&#34;&gt;package&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d75f00&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;rootHandler&lt;/span&gt;(w http.ResponseWriter, req *http.Request) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    log.&lt;span style=&#34;color:#0087ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;%v&amp;#34;&lt;/span&gt;, req)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#0087ff&#34;&gt;Fprintf&lt;/span&gt;(w, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;hello world!\n&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;helloHandler&lt;/span&gt;(w http.ResponseWriter, req *http.Request) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    log.&lt;span style=&#34;color:#0087ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;%v&amp;#34;&lt;/span&gt;, req)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    msg := req.&lt;span style=&#34;color:#0087ff&#34;&gt;PathValue&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;msg&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#0087ff&#34;&gt;Fprintf&lt;/span&gt;(w, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;%s&amp;#34;&lt;/span&gt;, msg+&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;weatherHandler&lt;/span&gt;(w http.ResponseWriter, req *http.Request) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url := &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;https://wttr.in/?T&amp;amp;lang=pt-br&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ua := &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;curl/8.5.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    log.&lt;span style=&#34;color:#0087ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;making a GET request to url=&amp;#34;&lt;/span&gt;, url, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    client := http.Client{ &lt;span style=&#34;color:#4e4e4e&#34;&gt;// set a request timeout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e4e4e&#34;&gt;&lt;/span&gt;        Timeout: &lt;span style=&#34;color:#00afaf&#34;&gt;20&lt;/span&gt; * time.Second,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r, err := http.&lt;span style=&#34;color:#0087ff&#34;&gt;NewRequest&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;, url, &lt;span style=&#34;color:#d75f00&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5f8700&#34;&gt;if&lt;/span&gt; err != &lt;span style=&#34;color:#d75f00&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#0087ff&#34;&gt;panic&lt;/span&gt;(err)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r.Header.&lt;span style=&#34;color:#0087ff&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;, ua)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    resp, err := client.&lt;span style=&#34;color:#0087ff&#34;&gt;Do&lt;/span&gt;(r)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5f8700&#34;&gt;if&lt;/span&gt; err != &lt;span style=&#34;color:#d75f00&#34;&gt;nil&lt;/span&gt; || resp.StatusCode != http.StatusOK {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        log.&lt;span style=&#34;color:#0087ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;making a GET request to url=&amp;#34;&lt;/span&gt;, url, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;Failed! Returning a 500&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        log.&lt;span style=&#34;color:#0087ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;err=&amp;#34;&lt;/span&gt;, err)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        w.&lt;span style=&#34;color:#0087ff&#34;&gt;WriteHeader&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fmt.&lt;span style=&#34;color:#0087ff&#34;&gt;Fprintf&lt;/span&gt;(w, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;request failed!\n&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5f8700&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5f8700&#34;&gt;defer&lt;/span&gt; resp.Body.&lt;span style=&#34;color:#0087ff&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    log.&lt;span style=&#34;color:#0087ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;making a GET request to url=&amp;#34;&lt;/span&gt;, url, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;Done! Response code=&amp;#34;&lt;/span&gt;, resp.Status)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    written, err := io.&lt;span style=&#34;color:#0087ff&#34;&gt;Copy&lt;/span&gt;(w, resp.Body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5f8700&#34;&gt;if&lt;/span&gt; err != &lt;span style=&#34;color:#d75f00&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        log.&lt;span style=&#34;color:#0087ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;Error writing response after %d bytes: %v&amp;#34;&lt;/span&gt;, written, err)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    apiPort := &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;8000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    http.&lt;span style=&#34;color:#0087ff&#34;&gt;HandleFunc&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;, rootHandler)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    http.&lt;span style=&#34;color:#0087ff&#34;&gt;HandleFunc&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/weather/&amp;#34;&lt;/span&gt;, weatherHandler)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    http.&lt;span style=&#34;color:#0087ff&#34;&gt;HandleFunc&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/hello/{msg}&amp;#34;&lt;/span&gt;, helloHandler)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    log.&lt;span style=&#34;color:#0087ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;Listening on port=&amp;#34;&lt;/span&gt;, apiPort)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;panic&lt;/span&gt;(http.&lt;span style=&#34;color:#0087ff&#34;&gt;ListenAndServe&lt;/span&gt;(&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;+apiPort, &lt;span style=&#34;color:#d75f00&#34;&gt;nil&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;app.go&lt;/p&gt;
&lt;p&gt;Nosso app continua igual à versão em Python, mas agora temos um endpoint a mais que faz um request externo para o site &lt;a href=&#34;https://wttr.in/&#34;&gt;wttr.in&lt;/a&gt; obter a previsão do tempo.&lt;/p&gt;
&lt;p&gt;E como fica o nosso Dockerfile? Como Golang é uma linguagem compilada vamos mostrar nesse exemplo a funcionalidade do multi-stage ao extremo: Criando um container com apenas o binário da nossa app.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; golang:1.25 AS builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; useradd -u &lt;span style=&#34;color:#00afaf&#34;&gt;1000&lt;/span&gt; -U -m --shell /bin/bash nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; nonroot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/nonroot/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --chown=nonroot:nonroot . /home/nonroot/app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;CGO_ENABLED&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;0&lt;/span&gt; go build -ldflags=&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-s -w&amp;#34;&lt;/span&gt; app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; scratch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --from=builder /etc/passwd /etc/passwd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e4e4e&#34;&gt;# truque pra rodar nonroot no scratch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --from=builder /home/nonroot/app/app /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; nonroot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; 8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ENTRYPOINT&lt;/span&gt; [ &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;app&amp;#34;&lt;/span&gt; ]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;golang/Dockerfile-scratch&lt;/p&gt;
&lt;p&gt;Como podemos ver, compilamos nosso app no estágio de build, usando uma imagem que contém os compiladores e outras ferramentas para gerar o nosso binário, e como estamos compilando estaticamente (usando opção CGO_ENABLED=0) apenas o nosso binário é necessário para a aplicação funcionar. E depois do estágio de build, o estágio final não está utilizando nenhuma imagem base (SCRATCH), ou seja, nossa imagem final vai conter apenas o binário do nosso app.&lt;/p&gt;
&lt;p&gt;Para quem ficou curioso, essa imagem tem apenas 6 MB, ao passo que a imagem base de build (golang:1.25) tem 850MB.&lt;/p&gt;
&lt;p&gt;Quem quiser se aprofundar em diminuir o tamanho do binário ainda mais dá pra usar o upx (&lt;a href=&#34;https://github.com/upx/upx&#34;&gt;github.com/upx/upx&lt;/a&gt;) que faz compressão de executáveis, que reduziu o tamanho para ~2MB. Porém, acho que não vale a pena adotar essa abordagem, pois o Docker já faz essa compressão quando faz o download das imagens, então usar o upx só vai fazer seu app demorar mais para inicializar.&lt;/p&gt;
&lt;p&gt;Se subirmos o container, vemos que os endpoints &amp;ldquo;hello world&amp;rdquo; funcionam, mas o endpoint de previsão de tempo não, com o erro: &amp;ldquo;tls: failed to verify certificate: x509: certificate signed by unknown authority&amp;rdquo;. Não temos a cadeia de certificados&lt;/p&gt;
&lt;p&gt;Essa foi a nossa deixa para falarmos do conceito de imagens distroless.&lt;/p&gt;
&lt;p&gt;Imagens distroless (&lt;a href=&#34;https://github.com/GoogleContainerTools/distroless&#34;&gt;github.com/GoogleContainerTools/distroless&lt;/a&gt;) foram introduzidos pela Google, e a ideia é que as imagens base tem o mínimo necessário para rodar a aplicação, sem ter uma distribuição base como o debian por trás, ou seja não tem o apt para instalar pacotes ou shell, etc &amp;hellip;&lt;/p&gt;
&lt;p&gt;Quem tiver interesse no repositório oficial, tem exemplos para várias linguagens. O que é chato dessas imagens é que caso você precise adicionar algum pacote que a imagem base não tem você precisa aprender o sistema de build pouco intuitivo chamado Bazel.&lt;/p&gt;
&lt;p&gt;No nosso caso a imagem base distroless é a gcr.io/distroless/static, ela tem apenas 2MB. Quais pacotes ela tem? Como não temos o apt, não vamos conseguir facilmente listar os pacotes.&lt;/p&gt;
&lt;p&gt;Para resolver esse problema de identificar os pacotes vamos introduzir um conceito do Software Bill of materials (SBOM), é um &amp;ldquo;inventário&amp;rdquo; identificando todos os componentes presentes em um determinado artefato de software. Ele tem alguns formatos padrão, o mais difundido é o System Package Data Exchange (SPDX) , tipicamente representado em um arquivo json. Nesse arquivo teremos as versões de todos os componentes, suas licenças e por fim os relacionamentos (como dependências).&lt;/p&gt;
&lt;p&gt;É uma boa prática gerar o SBOM junto ao build da imagem Docker, pois isso facilita demais auditorias de segurança, por exemplo, quando identificada uma vulnerabilidade em uma biblioteca que utilizamos, conseguimos facilmente encontrar se de fato estamos seguros ou onde precisamos atuar atualizando um pacote para uma versão não vulnerável.&lt;/p&gt;
&lt;p&gt;Vamos gerar o nosso SBOM utilizando o syft (&lt;a href=&#34;https://github.com/anchore/syft&#34;&gt;github.com/anchore/syft&lt;/a&gt;), nossa imagem tem os seguintes pacotes: a cadeia de certificados que precisamos e infos de fuso horários necessários para alguns apps.&lt;/p&gt;
&lt;p&gt;Usando essa imagem como base no estágio final, nosso endpoint de previsão do tempo funciona \o/&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/weather-working.png&#34; loading=&#34;lazy&#34;
         alt=&#34;endpoint weather funcioando \o/&#34; width=&#34;800px&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;endpoint weather funcioando \o/&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;debugando-imagens-distroless&#34;&gt;Debugando imagens distroless&lt;/h2&gt;
&lt;p&gt;Uma das maiores dificuldades em utilizar as imagens mínimas distroless é a de fazer o debug das aplicações, por exemplo, rodar um debugger com breakpoints para investigar algum bug.&lt;/p&gt;
&lt;p&gt;Vamos abordar duas formas de resolver isso, a primeira é ter duas versões do Dockerfile, uma mínima utilizada em produção e uma versão &amp;ldquo;desenvolvedor&amp;rdquo; que inclui um shell, o gerenciador de pacotes como o apt e outros pacotes para esse fim.&lt;/p&gt;
&lt;p&gt;Outra abordagem é &amp;ldquo;anexar&amp;rdquo; um container de debug junto ao container da aplicação, também chamado de container sidecar, o container de debug tem um shell e as ferramentas necessárias para fazer o debug e atua lado-a-lado da aplicação rodando.&lt;/p&gt;
&lt;p&gt;Bora ver os pacotes da aplicação? Subi nosso app Golang com um container chamado golang, então vamos subir outro container usando o mesmo namespace de processos (pid) e na mesma rede, conforme o comando abaixo:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker run --rm -it --privileged --pid container:golang --network container:golang nicolaka/netshoot&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Observação: a imagem nicolaka/netshoot (&lt;a href=&#34;https://github.com/nicolaka/netshoot&#34;&gt;github.com/nicolaka/netshoot&lt;/a&gt;) é uma imagem com diversas ferramentas de rede instaladas. Para Kubernetes a imagem bretfisher/shpod (&lt;a href=&#34;https://github.com/bretfisher/shpod&#34;&gt;github.com/bretfisher/shpod&lt;/a&gt;) é ótima com diversas ferramentas para fazer debug do cluster.&lt;/p&gt;
&lt;p&gt;Por que o container precisa ser privilegiado? Para conseguirmos acessar os arquivos do outro arquivo, vá em /proc/1/root , e você estará no filesystem da aplicação. Onde 1 é o id do processo do app.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/wizardzines-procfs.png&#34; loading=&#34;lazy&#34;
         alt=&#34;wizardzines.com/comics/proc&#34; width=&#34;600px&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;a href=&#34;https://wizardzines.com/comics/proc/&#34;&gt;wizardzines.com/comics/proc&lt;/a&gt;&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Antes de capturar os pacotes, bora dar um tutorial rápido de Wireshark? O wireguark é um aplicativo desktop que faz 2 coisas em uma, primeiro ele captura os pacotes passando na maquina e depois ele tem uma interface muito completa para visualizar o tráfego, vendo detalhes de cada pacote, possibilitando filtros e fazendo visualizações como  diagramas de estado e estatísticas para ajudar a entender o que está acontecendo.&lt;/p&gt;
&lt;p&gt;No nosso caso, como estamos utilizando containers, não vamos ter a interface gráfica do Wireshark, então podemos fazer de duas formas: capturar os pacotes utilizando o tcpdump (que não tem interface gráfica), salvar um arquivo pcap e visualizar no Wireshark. A outra opção é utilizar uma alternativa &amp;ldquo;terminal&amp;rdquo; do Wireshark, o termshark, com ele teremos uma experiência parecida com a original.&lt;/p&gt;
&lt;p&gt;Para abrir o termshark precisamos especificar uma interface da qual os pacotes serão capturados, no nosso caso só temos uma interface, então não precisamos. Uma vez aberto, podemos ver que mesmo sem mandar muitos requests pro nosso app tem muitos pacotes que não são do nosso interesse, como os pacotes do protocolo ARP. Então é uma mão na roda usar filtros, podemos filtrar por IP, por porta , protocolo, etc &amp;hellip;. Tem uma colinha dos filtros nesse link: &lt;a href=&#34;https://medium.com/hacker-toolbelt/wireshark-filters-cheat-sheet-eacdc438969c&#34;&gt;https://medium.comhacker-toolbelt/wireshark-filters-cheat-sheet-eacdc438969c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Com o termshark aberto e filtrando apenas pacotes HTTP, no print abaixo podemos ver a aplicação rodando no terminal superior esquerdo, um request sendo feito com curl no terminal da direita e abaixo estamos rodando a versão&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/termshark.png&#34; loading=&#34;lazy&#34; width=&#34;800px&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Fechando o parêntese do nosso tutorial 101 do wireshark, se tiver interesse em um texto aprofundado escreva pra gente :)&lt;/p&gt;
&lt;p&gt;Para facilitar nossa vida, tem uma ferramenta que faz essa abordagem de maneira simplificada, o cdebug (&lt;a href=&#34;https://github.com/iximiuz/cdebug&#34;&gt;github.com/iximiuz/cdebug&lt;/a&gt;), com uma feature adicional: fazer redirecionamento de portas não públicas (semelhante ao kubectl port-forward).&lt;/p&gt;
&lt;h2 id=&#34;fazendo-o-scan-de-vulnerabilidades-nas-imagens&#34;&gt;Fazendo o scan de vulnerabilidades nas imagens&lt;/h2&gt;
&lt;p&gt;Até agora o nosso intuito era diminuir o tamanho das imagens, pois dessa forma teríamos uma superfície de ataque menor, mas não medimos se de fato temos menos vulnerabilidades.&lt;/p&gt;
&lt;p&gt;Vamos adotar o grype (&lt;a href=&#34;https://github.com/anchore/grype&#34;&gt;github.com/anchore/grype&lt;/a&gt;), outra opção muito boa é o trivy (&lt;a href=&#34;https://github.com/aquasecurity/trivy&#34;&gt;github.com/aquasecurity/trivy&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;A nossa primeira versão (v1) tem 1334 CVEs :/ , das quais 6 são critical, 257 high, 894 medium, etc.&lt;/p&gt;
&lt;p&gt;Já a nossa versão multistage (v2) tem 10x menos vulnerabilidades: com 136 CVEs , das quais 4 critical, 6 high, 36 medium.&lt;/p&gt;
&lt;p&gt;Como pode um simples hello world ter 1300 CVEs? Em resumo, é porque imagens baseadas em Debian não atualizam por completo as versões para corrigir as CVEs, vamos falar em mais detalhes na próxima seção.&lt;/p&gt;
&lt;h2 id=&#34;debian-estamos-sendo-justos-com-ele&#34;&gt;Debian: Estamos sendo justos com ele?&lt;/h2&gt;
&lt;p&gt;Vimos que a nossa imagem tem mais de mil vulnerabilidades, mas por que isso acontece? Estou de fato em risco?&lt;/p&gt;
&lt;p&gt;A resposta é que provavelmente o problema não é tão grave quanto parece, só que a maneira que os scanners funcionam não bate bem da maneira que o Debian opera. O Debian quando tem sua versão stable declarada todos os pacotes são congelados na versão que estão e são feitos diversos testes para que tudo funcione até que seja lançada ao público a release.&lt;/p&gt;
&lt;p&gt;Quando bugs são encontrados, de segurança ou não, o Debian muitas vezes simplesmente aplica a mudança (patch) que corrige o problema em cima da versão que saiu no stable.&lt;/p&gt;
&lt;p&gt;Ao passo que os scanners de segurança funcionam identificando os pacotes e outros componentes de software (SBOM) e cruzar com um banco de dados de vulnerabilidades.&lt;/p&gt;
&lt;p&gt;Ou seja, os scanners não estão nem aí pras mudanças que o Debian aplicou.&lt;/p&gt;
&lt;p&gt;Por exemplo, nossa primeira versão de ambos o trivy e grype reportaram a CVE-2023-23914 (HSTS ignored on multiple requests) no curl, que de fato é uma vulnerabilidade crítica. Pois bora tentar reproduzir a vulnerabilidade?&lt;/p&gt;
&lt;p&gt;Na página da CVE (&lt;a href=&#34;https://curl.se/docs/CVE-2023-23914.html&#34;&gt;curl.se/docs/CVE-2023-23914.html&lt;/a&gt;), basta rodar o seguinte: &lt;code&gt;curl --hsts &amp;quot;&amp;quot; https://curl.se http://curl.se&lt;/code&gt;, quando vulnerável, o curl vai fazer o segundo request sem https, mesmo com o site esforçando HSTS. Porém, o comando falha pois a feature de HSTS nem foi introduzida na versão do curl adotada no Debian Bullseye. Ou seja, é um falso positivo.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/false-positive.png&#34; loading=&#34;lazy&#34; width=&#34;500px&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Um excelente blog post falando sobre essa situação é &lt;a href=&#34;https://www.linuxserver.io/blog/image-vulnerability-scanning-and-you&#34;&gt;Image Vulnerability Scanning and You -- linuxserver&lt;/a&gt;, da linuxserver, grupo que disponibiliza imagens docker para diversas aplicações open source, no blog post eles mostram como esses resultados aparentemente alarmante de scanners de vulnerabilidades, são falsos positivos. Eles deram um exemplo de uma vulnerabilidade, a CVE-2020-16156, que só pode ser explorada caso um usuário altere configurações de maneira maliciosa, ou seja, para explorar a vulnerabilidade você já teria que estar comprometido, o que é um problema muito maior.&lt;/p&gt;
&lt;p&gt;O scanner grype tem uma opção para apenas considerar vulnerabilidades que de fato serão corrigidas (&amp;ndash;only-fixed), rodando essa opção na nossa v2, as 130 vulnerabilidades caem para 2, uma de severidade medium e outra unknown.&lt;/p&gt;
&lt;h2 id=&#34;imagens-chainguard&#34;&gt;Imagens chainguard&lt;/h2&gt;
&lt;p&gt;As imagens da Chainguard são imagens produzidas pela empresa de mesmo nome que, além de serem menores, fazem um grande esforço para as imagens estarem com os pacotes atualizados e com as correções de segurança aplicadas.&lt;/p&gt;
&lt;p&gt;Outra feature legal dessas imagens é que toda vez que um pacote é instalado o SBOM dele é automaticamente gerado, criando um melhor lastro do conteúdo da imagem.&lt;/p&gt;
&lt;p&gt;Para quem está acostumado com imagens baseadas em debian precisa se acostumar pois as imagens do chainguard são baseadas no alpine, ou seja, ao invés do gerenciador de pacotes apt é utilizado o apk, então tem uma certa &amp;ldquo;curva de aprendizado&amp;rdquo; para se acostumar, uma dica pra encontrar os pacotes equivalentes é utilizar o apk search com cmd para procurar o pacote que contém aquele comando, por exemplo para instalar o ldd, faça: apk search cmd:ldd e o pacote associado será o posix-libc-utils.&lt;/p&gt;
&lt;p&gt;Outra diferença entre as imagens baseadas no Debian e do Alpine é o shell, nas imagens Debian o shell adotado é o bash, enquanto no Alpine é um shell mais limitado o ash (provido pelo busybox), então se seus scripts contém &amp;ldquo;bashismos&amp;rdquo; você precisa ver o que faz mais sentido entre tornar eles interoperáveis (posix-compliant) ou instalar o bash na imagem.&lt;/p&gt;
&lt;p&gt;Apesar de ser baseada no alpine, as imagens chainguard não utilizam a biblioteca padrão musl do alpine, mas sim a implementação mais difundida da GNU a glibc, vamos retomar essa diferença mais a frente.&lt;/p&gt;
&lt;p&gt;Bora colocar nossa app Python para usar o Chainguard?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; cgr.dev/chainguard/wolfi-base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;3&lt;/span&gt;.12
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; apk add python-&lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt; py&lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt;-pip python-&lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt;-dev &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    build-base openssl-dev vim curl &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    rm -rf /var/cache/apk/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; nonroot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/nonroot/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --chown=nonroot:nonroot . /home/nonroot/app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; python3 -m venv .venv &amp;amp;&amp;amp; . .venv/bin/activate &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    pip3 install --no-cache-dir -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ENV&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;PATH&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/home/nonroot/app/.venv/bin:&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; 8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;CMD&lt;/span&gt; [ &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;gunicorn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-w&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-b&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;0.0.0.0:8000&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--access-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--error-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;app:app&amp;#34;&lt;/span&gt; ]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dockerfile-v3&lt;/p&gt;
&lt;p&gt;A imagem base da Chainguard é o wolfi, ela é uma imagem pequena da qual instalamos os pacotes de que precisamos.&lt;/p&gt;
&lt;p&gt;A principal diferença é que os pacotes têm outros nomes, por exemplo, o equivalente do build-essential é o build-base, e diferentemente do Debian podemos escolher qual versão do Python vamos adotar.&lt;/p&gt;
&lt;p&gt;Já vem com um usuário não root, então basta utilizar ele.&lt;/p&gt;
&lt;p&gt;Quem tiver curiosidade em inspecionar a imagem com o dive, os SBOMs SPDX de cada pacote estão em /var/lib/db/sbom/.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/chainguard-cves.png&#34; loading=&#34;lazy&#34; width=&#34;500px&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;E as CVEs? É aqui que a Chainguard brilha, nenhuma CVE reportada no Trivy ^_^, porém apesar da Chainguard ter uma postura bastante proativa para manter toda cadeia de suprimento segura e atualizada, você precisa periodicamente rebuildar as imagens para usar as versões mais atuais dos pacotes e das nossas bibliotecas de que dependemos (que permitimos que sejam atualizadas para versões compatíveis).&lt;/p&gt;
&lt;p&gt;Quem tiver interesse em aprender mais sobre as imagens chainguard eles tem excelentes guias com passo-a-passo, exemplo e cursos em &lt;a href=&#34;https://edu.chainguard.dev/&#34;&gt;edu.chainguard.dev&lt;/a&gt; gostei bastante da dinâmica dos cursos, com vídeos curtos e acompanhados de um texto do que é mostrado no vídeo.&lt;/p&gt;
&lt;h2 id=&#34;criando-imagens-distroless-da-chainguard-com-melange&#34;&gt;Criando imagens distroless da Chainguard com Melange&lt;/h2&gt;
&lt;p&gt;No exemplo anterior utilizamos a imagem base da Chainguard para o nosso app Python, porém ela não é uma imagem distroless, visto que ela tem um shell, o apk e etc. &amp;hellip; A Chainguard tem imagens distroless do Python e outras linguagens e projetos, porém só podemos usar gratuitamente sua tag latest&lt;/p&gt;
&lt;p&gt;Para termos uma imagem distroless pra chamar de nossa, vamos utilizar o sistema de build da Chainguard, o Melange.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/chainguard-melange.png&#34; loading=&#34;lazy&#34;
         alt=&#34;edu.chainguard.dev/open-source/build-tools/melange/overview&#34; width=&#34;600px&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;a href=&#34;https://edu.chainguard.dev/open-source/build-tools/melange/overview/&#34;&gt;edu.chainguard.dev/open-source/build-tools/melange/overview&lt;/a&gt;&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Primeiramente precisamos empacotar nossa app python em um pacote alpine apk usando o melange, para fazer esse empacotamento teremos uma pipeline de build no melange declarada a partir do arquivo yaml abaixo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;42
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;45
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;46
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;47
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;48
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;49
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;50
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;51
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;52
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;package&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;name&lt;/span&gt;: hello-crud
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#00afaf&#34;&gt;0.0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;epoch&lt;/span&gt;: &lt;span style=&#34;color:#00afaf&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;description&lt;/span&gt;: REST hello world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;copyright&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#0087ff&#34;&gt;license&lt;/span&gt;: Apache-2.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#0087ff&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;dependencies&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;runtime&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - python-3.12
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;accounts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;groups&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#0087ff&#34;&gt;groupname&lt;/span&gt;: nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#0087ff&#34;&gt;gid&lt;/span&gt;: &lt;span style=&#34;color:#00afaf&#34;&gt;65532&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;users&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#0087ff&#34;&gt;username&lt;/span&gt;: nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#0087ff&#34;&gt;uid&lt;/span&gt;: &lt;span style=&#34;color:#00afaf&#34;&gt;65532&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;run-as&lt;/span&gt;: nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;contents&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;keyring&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - ./melange.rsa.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;repositories&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - https://packages.wolfi.dev/os
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;packages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - busybox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - glibc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - glibc-locale-posix
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - openssl-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - build-base
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - python-3.12
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - py3.12-pip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pipeline&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#0087ff&#34;&gt;name&lt;/span&gt;: Build Python application
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#0087ff&#34;&gt;runs&lt;/span&gt;: |&lt;span style=&#34;color:#00afaf&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      VENVDIR=/usr/share/webapps/hello-server/venv
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      EXECDIR=&amp;#34;${{targets.destdir}}/usr/bin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      WEBAPPDIR=&amp;#34;${{targets.destdir}}/usr/share/webapps/hello-server&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      mkdir -p &amp;#34;${EXECDIR}&amp;#34; &amp;#34;${WEBAPPDIR}&amp;#34; /usr/share/webapps/hello-server
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      cd /usr/share/webapps/hello-server
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      echo -e &amp;#34;\n\n#########################################\n&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      python3 -m venv ${VENVDIR}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      cd /home/build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      sh -c &amp;#34;. ${VENVDIR}/bin/activate &amp;amp;&amp;amp; pip3 install --no-compile --no-cache-dir -r requirements.txt &amp;amp;&amp;amp; pip3 uninstall -y pip&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      cp -r ${VENVDIR} ${WEBAPPDIR}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      cp app.py ${WEBAPPDIR}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;      chown -R 65532:65532 ${WEBAPPDIR}&lt;/span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;melange.yaml&lt;/p&gt;
&lt;p&gt;Nesse yaml a gente declara as informações do nosso pacote, como nome, versão e licença e as dependências em tempo de execução dele, no nosso caso apenas o python3.12.&lt;/p&gt;
&lt;p&gt;Em seguida declaramos o que o nosso ambiente de build precisa: os pacotes de build, o usuário não root e os repositórios wolfi para usarmos os pacotes da chainguard (poderíamos usar o alpine se quiser).&lt;/p&gt;
&lt;p&gt;Por fim a pipeline de build em si, ou seja uma sequência de comandos shell que builda a app e copia tudo para uma pasta em targets.destdir.&lt;/p&gt;
&lt;p&gt;Fizemos uma pequena alteração no nosso pip install, utilizando a flag &amp;ndash;no-compile que não gera os arquivos .pyc, dessa forma o venv fica menor. Tem um excelente blog post explicando os trade-offs dessa abordagem: &lt;a href=&#34;https://aleksac.me/blog/dont-use-pythondontwritebytecode-in-your-dockerfiles/&#34;&gt;Stop putting this into your Python Dockerfiles  -- Aleksa Cukovic&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Bora buildar nosso pacote?&lt;/p&gt;
&lt;p&gt;Na primeira vez precisamos gerar uma chave privada para assinar o pacote:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker run --rm -v &amp;quot;${PWD}&amp;quot;:/work cgr.dev/chainguard/melange keygen&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Não se preocupe com os comandos, criei um makefile no repositório que executa os comandos em sequência.&lt;/p&gt;
&lt;p&gt;Então o build:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker run --privileged --rm -v &amp;quot;${PWD}&amp;quot;:/work cgr.dev/chainguard/melange build melange.yaml --arch amd64 --signing-key melange.rsa&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Pronto! Uma vez executado, teremos nosso pacote alpine na pasta packages.&lt;/p&gt;
&lt;p&gt;Com o nosso pacote alpine pronto, bora criar o container que faz o deploy do nosso app? É agora que surge o apko, nele declaramos o container usado em tempo de execução (runtime) contendo o pacote previamente gerado, é como se fosse um Dockerfile, mas feito de forma declarativa.&lt;/p&gt;
&lt;p&gt;Agora o nosso apko.yaml:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;contents&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;keyring&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - ./melange.rsa.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;repositories&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - https://packages.wolfi.dev/os
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#39;@local /work/packages&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;packages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - hello-crud@local
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;accounts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;groups&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#0087ff&#34;&gt;groupname&lt;/span&gt;: nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#0087ff&#34;&gt;gid&lt;/span&gt;: &lt;span style=&#34;color:#00afaf&#34;&gt;65532&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;users&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#0087ff&#34;&gt;username&lt;/span&gt;: nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#0087ff&#34;&gt;uid&lt;/span&gt;: &lt;span style=&#34;color:#00afaf&#34;&gt;65532&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;run-as&lt;/span&gt;: nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;PATH&lt;/span&gt;: /usr/share/webapps/hello-server/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;work-dir&lt;/span&gt;: /usr/share/webapps/hello-server/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;entrypoint&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#0087ff&#34;&gt;command&lt;/span&gt;: gunicorn -w 2 -b 0.0.0.0:8000 --access-logfile - --error-logfile - app:app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;apko.yaml&lt;/p&gt;
&lt;p&gt;No nosso apko declaramos os repositórios da chainguard (ou alpine), os pacotes: no nosso caso apenas o pacote da nossa app, o usuário não root e as condições pro nosso app rodar como variaveis de ambiente e o comando entrypoint.&lt;/p&gt;
&lt;p&gt;Para buildar nossa imagem:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker run --rm --workdir /work -v ${PWD}:/work cgr.dev/chainguard/apko build apko.yaml hello-crud:test hello-crud-server.tar --arch host&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Cuidado que a imagem não é carregada automaticamente no docker, você precisa fazer docker image load -i hello-crud-server.tar&lt;/p&gt;
&lt;p&gt;E o resultado? A imagem ficou com 65MB \o/&lt;/p&gt;
&lt;p&gt;Em retrospectiva a nossa primeira versão do dockerfile tinha 570MB, a versão multistage usando debian 190MB e agora quase 10x menor com 65MB, não vai embora ainda não porque vamos melhorar ainda mais.&lt;/p&gt;
&lt;h2 id=&#34;distroless-sem-o-melange-e-apko&#34;&gt;Distroless sem o melange e apko&lt;/h2&gt;
&lt;p&gt;Na seção anterior mostrei como usar o melange e o apko para declarativamente criar imagens mínimas para sua aplicação, porém é um sistema de build dedicado que você vai ter que aprender e manter, minha intenção era mostrar que não é um bicho de sete cabeças , pelo contrário o melange e o apko são bastante amigáveis.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://caioau.net/blog/dockerfile-hardening/build-systems.png&#34; loading=&#34;lazy&#34; width=&#34;500px&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Porém pra quem não quiser aprender um novo sistema de build e não se importa em quebrar a cabeça fazendo um Dockerfile especializado temos essa alternativa.&lt;/p&gt;
&lt;p&gt;A peça crítica para esse Dockerfile funcionar é que o gerenciador de pacotes apk suporta chroot, ou seja podemos instalar pacotes em outro sistema de arquivos por &amp;ldquo;fora da caixa&amp;rdquo;, sem precisarmos instalar o apk em si ou ter um shell para conseguir rodar qualquer comando durante o build.&lt;/p&gt;
&lt;p&gt;talk is cheap, show me the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;42
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;45
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;46
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;47
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;48
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;49
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;50
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;51
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;52
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;53
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;54
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;55
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;56
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;57
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;58
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#454545&#34;&gt;59
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#8a8a8a;background-color:#1c1c1c;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;ROOTFS&lt;/span&gt;=/new_root
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;3&lt;/span&gt;.12
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e4e4e&#34;&gt;# nonroot user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;PGID&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;PUID&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; cgr.dev/chainguard/wolfi-base AS appbuilder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; pyversion
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; apk add python-&lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt; py&lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt;-pip python-&lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt;-dev build-base openssl-dev &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    rm -rf /var/cache/apk/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; nonroot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/nonroot/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --chown=nonroot:nonroot . /home/nonroot/app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; python3 -m venv .venv &amp;amp;&amp;amp; . .venv/bin/activate &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    pip3 install --no-compile --no-cache-dir -r requirements.txt &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    pip3 uninstall -y pip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; cgr.dev/chainguard/wolfi-base AS chrootbuilder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; ROOTFS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; pyversion
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; PGID
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; PUID
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; mkdir -p &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt;/etc/apk/keys &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    cp -v /etc/apk/keys/* &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt;/etc/apk/keys/ &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    cp -v /etc/apk/repositories  &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt;/etc/apk/repositories
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; apk add shadow &amp;amp;&amp;amp; &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    rm -rf /var/cache/apk/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; apk add --no-commit-hooks --root &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt; --initdb glibc glibc-locale-posix &lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    python-&lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;pyversion&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt; &amp;amp;&amp;amp;&lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    rm -rf &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt;/var/cache/apk/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;RUN&lt;/span&gt; groupadd -g &lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;PGID&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt; -R &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt; nonroot &amp;amp;&amp;amp;&lt;span style=&#34;color:#af0000&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#af0000&#34;&gt;&lt;/span&gt;    useradd -u &lt;span style=&#34;color:#00afaf&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;PUID&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;}&lt;/span&gt; -g nonroot -m --shell /bin/sh -R &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt; nonroot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; scratch AS runtime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ARG&lt;/span&gt; ROOTFS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --from=chrootbuilder &lt;span style=&#34;color:#0087ff&#34;&gt;$ROOTFS&lt;/span&gt; /
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; nonroot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; /home/nonroot/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;COPY&lt;/span&gt; --chown=nonroot:nonroot --from=appbuilder /home/nonroot/app/ /home/nonroot/app/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;ENV&lt;/span&gt; &lt;span style=&#34;color:#0087ff&#34;&gt;PATH&lt;/span&gt;=&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;/home/nonroot/app/.venv/bin:&lt;/span&gt;&lt;span style=&#34;color:#0087ff&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#00afaf&#34;&gt; 8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5f8700&#34;&gt;CMD&lt;/span&gt; [ &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;gunicorn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-w&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-b&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;0.0.0.0:8000&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--access-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;--error-logfile&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00afaf&#34;&gt;&amp;#34;app:app&amp;#34;&lt;/span&gt; ]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dockerfile-v4&lt;/p&gt;
&lt;p&gt;O Dockerfile tem 3 estágios: um que faz o &amp;ldquo;build&amp;rdquo; do nosso venv e da app, um que gera o ambiente chroot com as dependências de tempo de execução e o estágio final que junta os dois. Fiz dessa forma para separar a nossa &amp;ldquo;imagem base&amp;rdquo; com o runtime de python, que é desacoplado da nossa app e o build do venv que aí sim depende da nossa app, dessa forma rebuilds com cache só fazem o build o que mudou.&lt;/p&gt;
&lt;p&gt;O grande pulo do gato é o uso das flags do apk: -R apontando para chroot, &amp;ndash;no-commit-hooks pois os hooks não se aplicam quando usando chroots e &amp;ndash;initdb para inicializar o database do apk, sem isso o database não será gerado e ferramentas de SBOM não funcionam.&lt;/p&gt;
&lt;p&gt;E o resultado? O tamanho ficou muito próximo do apko (65MB), com apenas alguns KBs de diferença.&lt;/p&gt;
&lt;h2 id=&#34;glibc-vs-musl-o-inimigo-agora-é-outro&#34;&gt;glibc vs musl: O inimigo agora é outro&lt;/h2&gt;
&lt;p&gt;Quanto comecei minha jornada com Docker e comecei a colocar meus apps Python no docker, na época pelo menos era inviável usar imagens base alpine pois não tinha os wheels pré-compilados para biblioteca padrão c musl do alpine então qualquer app que precisava do numpy o build demorava demais pra compilar, então deixei de lado as imagens alpine.&lt;/p&gt;
&lt;p&gt;Mas agora quando tentei novamente o pypi tem os wheels pré-compilados pro musl e outras arquiteturas como o arm \o/&lt;/p&gt;
&lt;p&gt;Porém as imagens da chainguard apesar de serem baseadas no alpine não utilizam a musl, mas sim a implementação mais difundida a glibc, tem um artigo deles bastante completo explicando o diversos aspectos por trás dessa decisão, como compatibilidade com binários dinamicamente linkados:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://edu.chainguard.dev/chainguard/chainguard-images/about/images-compiled-programs/glibc-vs-musl/&#34;&gt;glibc vs. musl -- Chainguard&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;O dockerfile ficou igual ao dockerfile-v4, porém mudando a imagem base do wolfi para a release mais recente do alpine (alpine:3.23). E o tamanho da imagem ficou uns ~15MB menor que a do melange (50MB).&lt;/p&gt;
&lt;p&gt;Bora fazer uma retrospectiva de como foi evoluindo o tamanho da nossa imagem Python? Podemos ver na tabela abaixo que começamos com o nosso Dockerfile v0 bem tradicional com quase 600MB e com o multistage o tamanho caiu para um quarto da v0 e metade disso usando distroless.&lt;/p&gt;





&lt;table class=&#34;table w-auto table-sm table-striped table-hover table-bordered&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Versão&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Tamanho [MB]&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Percentual de v0&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;v0&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;570&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;v1 (delete dos caches e índices)&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;520&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;91%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;v2 (multistage)&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;130&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;22%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;v4 (distroless chroot/melange)&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;65&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;11%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;v5 (distroless com alpine+musl)&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;50&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;9%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Observação: Omitimos a v3 pois nela o objetivo era migrar para imagens baseadas em alpine, sem o foco em otimizar seu tamanho.&lt;/p&gt;
&lt;h2 id=&#34;hadolint&#34;&gt;Hadolint&lt;/h2&gt;
&lt;p&gt;Pra fechar o texto, a última dica é utilizar o Hadolint (&lt;a href=&#34;https://github.com/hadolint/hadolint&#34;&gt;github.com/hadolint/hadolint&lt;/a&gt;), ele dá excelentes dicas para as boas práticas de que falamos aqui, tem extensão pro VSCode e de quebra roda o outro linter excelente para shell &lt;a href=&#34;http://shellcheck.net/&#34;&gt;shellcheck.net&lt;/a&gt; dentro das instruções RUN, então você leva dois linters dentro de um.&lt;/p&gt;
&lt;h2 id=&#34;conclusão&#34;&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;Resgatando a provocação inicial, espero a essa altura ter te convencido de que dockerfile não é tudo igual, que não posta a aplicação funcionar para termos um bom dockerfile.&lt;/p&gt;
&lt;p&gt;O princípio que mais exploramos é tornar a imagem enxuta possível, pois além de imagens menores serem mais performáticas, elas têm uma superfície de ataque menor e dessa forma conseguimos identificar quais dependências são realmente necessárias em tempo de execução da aplicação.&lt;/p&gt;
&lt;p&gt;Para &amp;ldquo;enxugar&amp;rdquo; as imagens vimos como o dive é uma ferramenta muito prática para dissecar camada a camada as imagens e identificar os pontos de melhoria, e o conceito de multi-stage para separar o build e o runtime.&lt;/p&gt;
&lt;p&gt;Por fim, levando ao extremo o objetivo do multi-stage , vimos o conceito das imagens distroless e como fazer elas com o melange e o apko, porém o desafio de debugar essas imagens.&lt;/p&gt;
&lt;p&gt;Espero que esse texto te auxilie a criar imagens Docker melhores e muito obrigado por chegar até aqui!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
