Conteúdos

Podman: contêineres rootless com mais controle no Linux

Contêineres facilitam testar aplicações, separar dependências e reproduzir serviços em máquinas diferentes. A tecnologia é útil, mas a forma como o runtime é executado também importa: um comando simples pode criar processos, redes, volumes e permissões no host.

O Podman é uma alternativa compatível com o ecossistema de contêineres OCI e com muitos comandos conhecidos do Docker. Para o meu uso, ele apresenta uma proposta mais segura e flexível que a instalação Docker tradicional porque não depende de um daemon central privilegiado e permite executar contêineres diretamente como um usuário comum.

Isso não significa que todo contêiner Podman seja automaticamente seguro. Imagens, volumes, portas, permissões e opções privilegiadas continuam exigindo revisão. A vantagem é começar com menos privilégios e adicionar acesso somente quando o serviço realmente precisar.

O que muda em relação ao Docker tradicional

Em uma instalação Docker tradicional, o cliente conversa com o daemon, que normalmente executa com privilégios elevados. Esse modelo é prático e funciona bem, mas um usuário que consegue falar com o socket do Docker pode, na prática, obter capacidades muito próximas às de root no host.

O Podman não mantém um daemon central obrigatório para executar os contêineres. O comando inicia o processo de acordo com a solicitação e pode trabalhar em modo rootless, usando o namespace de usuário para mapear o root de dentro do contêiner para um usuário sem privilégios na máquina.

O Docker também possui um modo rootless. Portanto, a comparação justa não é “Podman seguro e Docker inseguro”. A diferença está no padrão de operação: no Podman, o fluxo daemonless e rootless é uma escolha natural desde o começo, enquanto muitas instalações Docker começam com um daemon privilegiado.

Imagens, contêineres e dados

Uma imagem é um artefato imutável usado como base. O contêiner é o processo criado a partir dessa imagem. Volumes e bind mounts guardam dados fora da camada efêmera do contêiner, e a rede define como o serviço se comunica com outros processos.

Se eu remover um contêiner, os dados que estavam apenas na camada dele podem desaparecer. Por isso, separo o ciclo de vida da aplicação do ciclo de vida dos dados e documento onde ficam os volumes importantes.

Primeiros comandos

podman run --name web -d -p 8080:80 docker.io/library/httpd
podman ps
podman logs web
podman stop web
podman rm web

O primeiro comando baixa a imagem httpd do registro indicado, cria o contêiner e publica a porta 80 do contêiner na porta 8080 do host. A imagem é escrita com o registro completo para evitar depender de uma busca ambígua.

Depois posso conferir os contêineres ativos, consultar logs, parar o processo e remover o recurso. O --rm também pode remover automaticamente um contêiner temporário quando ele termina, mas não uso essa opção para serviços cujos logs ou estado ainda preciso investigar.

Para consultar as imagens locais, uso:

podman images
podman inspect web

Executando sem root

O modo rootless é o recurso que mais pesa na minha escolha. Quando executo:

podman run --name web-rootless -d -p 8080:80 docker.io/library/httpd

como usuário comum, o processo do contêiner não recebe automaticamente privilégios de root no sistema hospedeiro. O root visto dentro do contêiner fica limitado pelo mapeamento de usuários e pelas permissões disponíveis para a conta que iniciou o Podman.

Essa redução de privilégio diminui o impacto de alguns erros de configuração e de uma possível falha no serviço. Uma aplicação comprometida ainda pode acessar tudo o que foi montado ou exposto para ela, mas não começa com a mesma capacidade de um processo root no host.

Portas abaixo de 1024, dispositivos, diretórios protegidos e algumas funções de rede podem exigir configuração adicional. Em vez de conceder root imediatamente, prefiro usar uma porta não privilegiada, como 8080, e deixar o proxy reverso cuidar da porta pública quando necessário.

Volumes e permissões

Volumes são uma das partes que mais geram confusão no modo rootless. O processo do contêiner precisa conseguir ler ou escrever no diretório montado, e essa permissão deve ser analisada no contexto do usuário que iniciou o Podman.

Para um conteúdo que não deve ser alterado pelo servidor web, posso montar o diretório como somente leitura:

podman run --name site -d -p 8080:80 \
  -v "$PWD/site:/usr/local/apache2/htdocs:ro" \
  docker.io/library/httpd

A opção :ro reduz o que o processo pode fazer com os arquivos. Não monto meu diretório pessoal inteiro, nem uso volumes com mais acesso do que a aplicação precisa. Em sistemas com SELinux, também preciso avaliar a etiqueta do volume e usar as opções de relabeling apropriadas ao ambiente.

Imagens e cadeia de confiança

Executar rootless reduz privilégios, mas não torna uma imagem confiável. Escolho registros conhecidos, verifico o projeto de origem, acompanho atualizações e evito imagens sem manutenção. Para serviços importantes, também considero fixar a imagem por digest em vez de aceitar sempre a tag móvel latest.

Não uso --privileged como solução para um erro de permissão. Essa opção amplia muito as capacidades do contêiner e elimina parte do benefício de começar com uma operação restrita. Primeiro identifico qual acesso está faltando e concedo somente aquele recurso.

Também removo capacidades que o serviço não necessita quando isso é compatível com a aplicação. Opções como --read-only, --cap-drop=all e --security-opt=no-new-privileges podem ajudar, mas precisam ser testadas individualmente; copiar uma lista de opções sem entender o serviço pode apenas criar falhas difíceis de diagnosticar.

Pods, systemd e Quadlet

O Podman também trabalha com pods, que agrupam contêineres e compartilham alguns recursos de rede. Essa organização é útil quando uma aplicação precisa de um serviço principal e de um componente auxiliar, mas não crio pods apenas para reproduzir uma arquitetura que não exige essa separação.

Para serviços Linux, a integração com o systemd é uma das partes mais flexíveis do Podman. O Quadlet permite descrever contêineres, volumes e redes em arquivos declarativos que o systemd pode iniciar, parar e reiniciar junto com o usuário ou com o sistema.

Isso evita depender de um daemon central para manter o serviço ativo e aproxima a operação dos mecanismos que já uso para logs, reinicialização e dependências. Ainda preciso definir backups dos volumes, política de atualização e uma forma de verificar se a nova imagem está funcionando antes de substituir a anterior.

O Podman também pode ser usado por ferramentas compatíveis com a sintaxe do Docker, mas não assumo compatibilidade perfeita em todos os comandos ou extensões. Testo o fluxo e consulto a documentação quando o projeto depende de uma integração específica.

Podman e Distrobox

O Distrobox usa contêineres para oferecer ambientes de outras distribuições integrados ao desktop e ao terminal. O Podman pode ser o mecanismo de contêiner por trás desse fluxo, enquanto o Distrobox se preocupa em tornar o ambiente confortável para uso interativo.

São casos de uso diferentes. Para um serviço, penso em imagem, rede, volume, logs e reinicialização. Para um ambiente de desenvolvimento, também preciso considerar terminal, arquivos do usuário, editor e integração com o sistema. A mesma base de contêiner não significa que a operação deve ser tratada do mesmo jeito.

Minha conclusão

O Podman oferece uma alternativa mais segura e flexível à instalação Docker tradicional quando valorizo execução daemonless e contêineres rootless. Poder iniciar um serviço como usuário comum reduz a quantidade de privilégios envolvidos e torna mais claro quais recursos o contêiner realmente recebeu.

Ainda assim, o resultado depende da operação. Uma imagem maliciosa, um volume amplo, uma porta publicada sem necessidade ou o uso de --privileged pode anular boa parte do cuidado inicial. Segurança não vem apenas do nome da ferramenta; vem das permissões mínimas, das imagens verificadas, das atualizações e dos backups.

Para mim, o Podman se destaca por combinar compatibilidade com o ecossistema de contêineres, integração com Linux e liberdade para operar serviços sem um daemon central privilegiado. É uma base prática para desenvolvimento e serviços, desde que imagens, dados e permissões sejam tratados como partes importantes da aplicação.