<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Homelab on Blog do Dunossauro</title><link>https://blog.dunossauro.com/tags/homelab/</link><description>Blog do Dunossauro (Homelab)</description><generator>Hugo -- gohugo.io</generator><language>pt-BR</language><managingEditor>mail@dunossauro.com
(dunossauro)</managingEditor><lastBuildDate>Fri, 23 Oct 2026 19:32:25 -0300</lastBuildDate><atom:link href="/tags/homelab/feed.xml" rel="self" type="application/rss+xml"/><item><title>Podman, Quadlets e updates automáticos</title><link>https://blog.dunossauro.com/posts/podman-quadlets-update/</link><pubDate>Fri, 23 Oct 2026 19:32:25 -0300</pubDate><author>mail@dunossauro.com (dunossauro)</author><guid>https://blog.dunossauro.com/posts/podman-quadlets-update/</guid><description>&lt;blockquote>
&lt;p>Ps: esse post não é uma introdução ao podman, menos ainda ao systemd&lt;/p>&lt;/blockquote>
&lt;p>Uma das coisas mais interessantes no &lt;a href="https://podman.io/">podman&lt;/a> é a capacidade de executar containers nativamente no &lt;a href="https://www.freedesktop.org/software/systemd/man/latest/systemd.html">systemd&lt;/a> e, de quebra, os serviços ainda podem ser atualizados automaticamente via serviços do próprio podman + systemd.&lt;/p>
&lt;h2 id="uma-ideia-de-fluxo" >
&lt;div>
&lt;a href="#uma-ideia-de-fluxo">
#
&lt;/a>
Uma ideia de fluxo
&lt;/div>
&lt;/h2>
&lt;p>Imagine que você é um cliente ou desenvolve uma aplicação que solta atualizações constantes em registros. Por exemplo, aqui no meu homelab costumo usar alguns serviços, ao mesmo tempo em que desenvolvo alguns outros.&lt;/p>
&lt;p>Um caso concreto que tenho aqui é meu laboratório de observabilidade com opentelemetry. Uso basicamente 5 imagens:&lt;/p>
&lt;ul>
&lt;li>Opentelemetry-contrib&lt;/li>
&lt;li>VictoriaMetrics&lt;/li>
&lt;li>VictoriaLogs&lt;/li>
&lt;li>VictoriaTraces&lt;/li>
&lt;li>Perses dashboard&lt;/li>
&lt;/ul>
&lt;p>Acompanho o feed RSS&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> desses serviços pra sempre saber quando sai uma release nova. E toda vez que uma nova release é lançada de cada um desses serviços, tenho que ir no &lt;a href="https://linuxcontainers.org/lxc/introduction/">LXC&lt;/a> que contém todas as minhas aplicações de observabilidade e atualizar o que saiu de novo.&lt;/p>
&lt;p>Isso não é necessariamente ruim, afinal leio os changelogs e sempre acabo vendo alguma novidade, possibilidades novas, etc. Mas, sendo totalmente sincero, a maioria esmagadora das vezes as releases têm somente fixes (X.X.AQUI) e, às vezes&amp;hellip; mais de um por dia ;)&lt;/p>
&lt;p>A ideia desse post é tentar contar como resolvi esse problema de updates fazendo o podman atualizar sozinho. Se quebrar uma vez ou outra, tudo bem, posso intervir, mas não preciso fazer isso sempre, a toda nova release.&lt;/p>
&lt;blockquote>
&lt;p>Como dei o exemplo do laboratório de observabilidade, a gente pode fazer outro post focado especialmente nele e na construção desses containers. Mas hoje quero focar no mecanismo de atualizações.&lt;/p>&lt;/blockquote>
&lt;h2 id="quadlets-quando-o-podman-encontra-o-systemd" >
&lt;div>
&lt;a href="#quadlets-quando-o-podman-encontra-o-systemd">
#
&lt;/a>
Quadlets, quando o podman encontra o systemd
&lt;/div>
&lt;/h2>
&lt;p>Vamos imaginar uma imagem genérica que alguém fez push em algum registry, vamos chamar ela de &lt;code>blah&lt;/code> em sua última versão &lt;code>:latest&lt;/code>.&lt;/p>
&lt;p>O &lt;a href="https://docs.podman.io/en/latest/markdown/podman-quadlet.1.html">Quadlet&lt;/a> é uma forma de manusear containers&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup> declarativamente usando systemd &lt;a href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html">unit files&lt;/a>.&lt;/p>
&lt;p>Mas, no lugar de criar um &lt;code>[Service]&lt;/code>, criamos um &lt;code>[Container]&lt;/code>. Vamos imaginar um &lt;code>blah.container&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ini" data-lang="ini">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Unit]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Description&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">Blah, uma API boladona :)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">[Container] # a parte importante aqui!&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Image&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">192.168.15.11:3000/dunossauro/blah:latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">PublishPort&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">8000:8000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Volume&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">/home/dunossauro/pods/quadlets/blah/config.yaml:/etc/blah/config.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Volume&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">/home/dunossauro/pods/quadlets/blah/config2.yaml:/etc/blah/config2.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Service]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Restart&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">always&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Install]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">WantedBy&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">default.target&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Para começar, temos dois parâmetros principais:&lt;/p>
&lt;ul>
&lt;li>&lt;code>Image&lt;/code>: descreve o registry, a imagem e a versão. Por exemplo, se quisermos usar a imagem do python 3.15 disponível no dockerhub, usaríamos algo como &lt;code>Image=docker.io/python:3.15&lt;/code>&lt;/li>
&lt;li>&lt;code>PublishPort&lt;/code>: descreve qual porta do container será mapeada para a máquina local.&lt;/li>
&lt;/ul>
&lt;p>De forma adicional, se precisar de um volume, você pode adicionar um:&lt;/p>
&lt;ul>
&lt;li>&lt;code>Volume&lt;/code>: descreve quais arquivos serão compartilhados no volume do container. Uma coisa importante aqui é que os arquivos locais precisam necessariamente ser full path, pois isso é um serviço rodando no sistema.&lt;/li>
&lt;/ul>
&lt;p>Com esse &amp;ldquo;unit container&amp;rdquo; dizemos ao podman que queremos instalar ele:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ podman quadlet install blah.container
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/home/dunossauro/.config/containers/systemd/blah.container
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>Dica: se precisar sobrescrever o arquivo depois de alterar, use a flag &lt;code>-r&lt;/code> (&lt;code>replace&lt;/code>) para atualizar o unit gerado.&lt;/p>&lt;/blockquote>
&lt;p>E com esse comando ele vai criar um diretório de containers para seu user &lt;code>~/.config/containers/systemd/&lt;/code> e adicionar &lt;code>blah.container&lt;/code> lá.&lt;/p>
&lt;p>Agora, recarregamos a configuração do systemd:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl --user daemon-reload
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>E temos os serviços de containers já disponíveis para uso:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ systemctl status --user blah
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>○ blah.service - blah api
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Loaded: loaded &lt;span style="color:#89dceb;font-weight:bold">(&lt;/span>/home/dunossauro/.config/containers/systemd/blah.container; generated&lt;span style="color:#89dceb;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Active: inactive &lt;span style="color:#89dceb;font-weight:bold">(&lt;/span>dead&lt;span style="color:#89dceb;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Se tudo estiver certo, podemos iniciar:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl start --user blah
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Como esse comando não gera output quando dá certo:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>○ → systemctl status --user blah
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>● blah.service - blah api
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Loaded: loaded &lt;span style="color:#89dceb;font-weight:bold">(&lt;/span>/home/dunossauro/.config/containers/systemd/blah.container; generated&lt;span style="color:#89dceb;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Active: active &lt;span style="color:#89dceb;font-weight:bold">(&lt;/span>running&lt;span style="color:#89dceb;font-weight:bold">)&lt;/span> since Thu 2026-10-15 16:55:24 -03; 41s ago
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Invocation: 340e2d1506144489a76a7e1d3cb991b0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Main PID: &lt;span style="color:#fab387">57516&lt;/span> &lt;span style="color:#89dceb;font-weight:bold">(&lt;/span>conmon&lt;span style="color:#89dceb;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Tasks: &lt;span style="color:#fab387">7&lt;/span> &lt;span style="color:#89dceb;font-weight:bold">(&lt;/span>limit: 37972&lt;span style="color:#89dceb;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Memory: 139.9M &lt;span style="color:#89dceb;font-weight:bold">(&lt;/span>peak: 143M&lt;span style="color:#89dceb;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CPU: 1.520s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/blah.service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ├─libpod-payload-9803c2ae6198debc965a501a890099113eb60e3f75af489226803a7eaa7a82df
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ └─57530 /usr/local/bin/python3.15 /usr/local/bin/fastapi run --host 0.0.0.0 blah/app.py
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> └─runtime
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ├─57511 /usr/bin/pasta --config-net -t 8000-8000:8000-8000 --dns-forward 169.254.1.1 -u none -&amp;gt; └─57516 /usr/bin/conmon --api-version &lt;span style="color:#fab387">1&lt;/span> -c 9803c2ae6198debc965a501a890099113eb60e3f75af4892268&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>out &lt;span style="color:#fab387">15&lt;/span> 16:55:26 melville systemd-blah&lt;span style="color:#89dceb;font-weight:bold">[&lt;/span>57516&lt;span style="color:#89dceb;font-weight:bold">]&lt;/span>: 🌐 Server started at http://0.0.0.0:8000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>out &lt;span style="color:#fab387">15&lt;/span> 16:55:26 melville systemd-blah&lt;span style="color:#89dceb;font-weight:bold">[&lt;/span>57516&lt;span style="color:#89dceb;font-weight:bold">]&lt;/span>: Documentation at http://0.0.0.0:8000/docs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>out &lt;span style="color:#fab387">15&lt;/span> 16:55:26 melville systemd-blah&lt;span style="color:#89dceb;font-weight:bold">[&lt;/span>57516&lt;span style="color:#89dceb;font-weight:bold">]&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>out &lt;span style="color:#fab387">15&lt;/span> 16:55:26 melville systemd-blah&lt;span style="color:#89dceb;font-weight:bold">[&lt;/span>57516&lt;span style="color:#89dceb;font-weight:bold">]&lt;/span>: Logs:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>YAY! Temos nossa incrível blah api rodando.&lt;/p>
&lt;h2 id="beleza-mas-como-isso-atualiza-sozinho" >
&lt;div>
&lt;a href="#beleza-mas-como-isso-atualiza-sozinho">
#
&lt;/a>
Beleza, mas como isso atualiza sozinho?
&lt;/div>
&lt;/h2>
&lt;p>Isso é feito com uma junção de três coisinhas:&lt;/p>
&lt;ul>
&lt;li>O &amp;ldquo;container unit&amp;rdquo; precisa de duas configurações:
&lt;ul>
&lt;li>O parâmetro: &lt;code>AutoUpdate&lt;/code>; e&lt;/li>
&lt;li>A versão não pode estar pinada, vamos usar &lt;code>:latest&lt;/code>, mas poderia &lt;code>:lts-alpine&lt;/code> por exemplo&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>O serviço systemd de update do podman: &lt;code>podman-auto-update.service&lt;/code>&lt;/li>
&lt;li>O timer systemd de update do podman: &lt;code>podman-auto-update.timer&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Começando pelo &lt;code>blah.container&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ini" data-lang="ini">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Container]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Image&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">192.168.15.11:3000/dunossauro/blah:latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">PublishPort&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">8000:8000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Volume&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">/home/dunossauro/pods/quadlets/blah/config.yaml:/etc/blah/config.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Volume&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">/home/dunossauro/pods/quadlets/blah/config2.yaml:/etc/blah/config2.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">AutoUpdate&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">registry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Neste exemplo, vamos usar &lt;code>:latest&lt;/code>&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup> afinal, se queremos atualizações, não podemos travar a versão, e o &lt;code>AutoUpdate&lt;/code> recebe &lt;code>registry&lt;/code> pois é de lá que ele deve buscar as novas versões&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup>.&lt;/p>
&lt;p>Com isso, damos um replace (&lt;code>-r&lt;/code>) no nosso &lt;code>.container&lt;/code>, fazendo ele pegar a configuração mais recente:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ podman quadlet install -r blah.container
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/home/dunossauro/.config/containers/systemd/blah.container
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Como temos uma nova configuração, é interessante que você faça o restart no blah:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl restart --user blah
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Com o serviço rodando, podemos seguir para os outros serviços.&lt;/p>
&lt;p>Aí entra o &lt;code>podman-auto-update&lt;/code>, que é quem efetivamente executa o update. Ele precisa estar habilitado:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ systemctl --user &lt;span style="color:#89dceb">enable&lt;/span> podman-auto-update.service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Created symlink &lt;span style="color:#a6e3a1">&amp;#39;/home/dunossauro/.config/systemd/user/default.target.wants/podman-auto-update.service&amp;#39;&lt;/span> → &lt;span style="color:#a6e3a1">&amp;#39;/usr/lib/systemd/user/podman-auto-update.service&amp;#39;&lt;/span>.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>O serviço executa o processo de atualização quando é acionado. Quem agenda essas execuções é o timer, que dispara o serviço nos intervalos configurados.&lt;/p>
&lt;p>Para saber quando ele vai executar, esse serviço tem um timer de systemd associado a ele, o &lt;code>podman-auto-update.timer&lt;/code>. Que também precisa ser inicializado.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl --user &lt;span style="color:#89dceb">enable&lt;/span> --now podman-auto-update.timer
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Para consultar se esse timer foi ativado, você pode olhar a lista de timers:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl --user list-timers
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Por padrão, ele é executado diariamente (&lt;code>OnCalendar=daily&lt;/code>), mas você pode alterar esse comportamento e colocar o tempo que desejar, usando a &lt;a href="https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html#">sintaxe dos timers&lt;/a>.&lt;/p>
&lt;p>Para editar, você poderia fazer a reescrita do arquivo do service no systemd, ou somente lançar um edit (o que faremos):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl edit --user podman-auto-update.timer
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Por exemplo, vou deixar para rodar a cada minuto (&lt;code>OnCalendar=*-*-* *:*:00&lt;/code>) para exemplificar, mas você deve ajustar como preferir:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ini" data-lang="ini">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Unit]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Description&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">Podman auto-update timer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Timer]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">OnCalendar&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">*-*-* *:*:00&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">RandomizedDelaySec&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">30&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Persistent&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Install]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">WantedBy&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">timers.target&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="automático-é-ótimo-até-falhar" >
&lt;div>
&lt;a href="#autom%c3%a1tico-%c3%a9-%c3%b3timo-at%c3%a9-falhar">
#
&lt;/a>
Automático é ótimo, até falhar&amp;hellip;
&lt;/div>
&lt;/h2>
&lt;p>O que acontece nesses updates automáticos se alguma coisa falhar nessa nova &lt;code>:latest&lt;/code>? Nunca se sabe, não é mesmo?&lt;/p>
&lt;p>Pra isso, temos um mecanismo de health check no unit, para ele validar se está mesmo funcionando:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ini" data-lang="ini">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cba6f7">[Container]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Image&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">192.168.15.11:3000/dunossauro/blah:latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6c7086;font-style:italic"># ...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">AutoUpdate&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">registry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">HealthCmd&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">curl -f http://localhost:8000/health || exit 1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">HealthInterval&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">30s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">HealthRetries&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">Notify&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>&lt;span style="color:#a6e3a1">healthy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#89b4fa">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>HealthCmd&lt;/code>: executa qualquer comando que você precise. No caso da &amp;ldquo;blah api&amp;rdquo;, vamos fazer um curl, pra ver se ela responde. Importante dizer aqui é que o comando roda &lt;strong>no container&lt;/strong>, logo ele teria que ter o curl.&lt;/li>
&lt;li>&lt;code>HealthInterval&lt;/code>: define o intervalo entre as verificações de saúde do container.&lt;/li>
&lt;li>&lt;code>HealthRetries&lt;/code>: define quantas falhas consecutivas são toleradas antes de o container ser considerado não saudável.&lt;/li>
&lt;li>&lt;code>Notify=healthy&lt;/code>: adia a notificação de sucesso da inicialização do service ao systemd. Faz com que espere até que o container esteja saudável.&lt;/li>
&lt;/ul>
&lt;p>Com isso, quando o container subir, se não der certo após o update, o podman vai iniciar o processo de rollback para o hash anterior da mesma imagem.&lt;/p>
&lt;p>Importante frisar aqui que sem adiar o &lt;code>Notify&lt;/code>, a validação fica a cargo de entender se o container conseguiu ser inicializado. Ele poder ser inicializado sem estar saudável, por isso &lt;code>Notify&lt;/code> é importante, pois, espera que ele esteja saudável antes de terminar o processo de atualização ou de rollback.&lt;/p>
&lt;h2 id="mas-como-os-pods-se-comunicam" >
&lt;div>
&lt;a href="#mas-como-os-pods-se-comunicam">
#
&lt;/a>
Mas como os pods se comunicam?
&lt;/div>
&lt;/h2>
&lt;p>Até agora vimos como subir um serviço isolado, mas, na vida real, nossos sistemas conversam com outras coisas: a API &lt;code>blah&lt;/code> precisa bater num banco de dados, num cache ou, no meu caso da observabilidade, várias ferramentas trocando dados o tempo todo.&lt;/p>
&lt;p>No mundo perfeito do Podman Quadlet, existe um arquivo &lt;code>.network&lt;/code> (exatamente como o &lt;code>.container&lt;/code>) que você cria para isolar os bichinhos em uma rede privada bridge, onde eles resolvem uns aos outros por DNS de forma limpa.&lt;/p>
&lt;p>Mas quer saber a verdade? Se a sua &lt;code>blah&lt;/code> api precisar consultar um banco de dados que está na máquina host, ou se você quiser simplificar as pontes sem gerenciar DNS interno de container, você pode apelar para o &lt;strong>&lt;code>host.containers.internal&lt;/code>&lt;/strong>.&lt;/p>
&lt;p>Por exemplo, a string de conexão do banco na sua &lt;code>blah&lt;/code> API apontaria direto para lá:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-env" data-lang="env">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f5e0dc">DATABASE_URL&lt;/span>&lt;span style="color:#89dceb;font-weight:bold">=&lt;/span>postgres://user:pass@host.containers.internal:5432/db
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Por que não me estressei com redes customizadas para tudo? Porque mergulhar de cabeça em regras de roteamento, DNS interno do Podman (&lt;a href="https://github.com/containers/aardvark-dns">&lt;code>aardvark-dns&lt;/code>&lt;/a>), isolamento e múltiplas redes bridge é um buraco negro tão profundo que daria um post inteiro só sobre isso.&lt;/p>
&lt;h2 id="conclusão" >
&lt;div>
&lt;a href="#conclus%c3%a3o">
#
&lt;/a>
Conclusão
&lt;/div>
&lt;/h2>
&lt;p>Isso facilita bastante o &amp;ldquo;configure e deixe rodando&amp;rdquo;, perco menos tempo pensando sobre isso ou se deveria atualizar algo.&lt;/p>
&lt;p>Claro, de tempos em tempos é legal dar uma olhada no &lt;code>journalctl&lt;/code> da coisa e ver como anda. Se algum update está travado, se algo mudou que precisa ser corrigido na sua aplicação de tempos em tempos. Para aplicações, é interessante configurar alguma coisa de monitoramento, um alerta que seja, aí você sabe de verdade quando precisa intervir.&lt;/p>
&lt;p>Toda essa minha pequena configuração de quadlets de observabilidade, meu problema inicial, está nesse &lt;a href="https://codeberg.org/dunossauro/obs-pods">repo&lt;/a> e você pode dar uma olhada.&lt;/p>
&lt;p>Como você tem usado essas coisas? Me conta.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Via página de releases no github mesmo &amp;ldquo;github.com/user/projeto/releases.atom&amp;rdquo;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>volumes, redes, etc&amp;hellip; tudo que o podman pode gerenciar&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>Poderia ser qualquer tag mutável, como :latest ou :lts-alpine. Tags de versão, como :3.1.18, também podem mudar, embora normalmente sejam mantidas fixas. Para garantir a referência a uma imagem específica, use um digest.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>Você também pode usar &lt;code>AutoUpdate=local&lt;/code> se quiser, aí quando existir uma imagem local mais nova, ele atualiza.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item></channel></rss>