ARQUITETURA SEM DAEMON DO PODMAN Sistema Operacional Linux (Kernel: namespaces + cgroups) Sem Daemon — fork/exec direto via conmon Container 1 Sem root UID mapeado Container 2 Sem root UID mapeado Pod (namespace de rede compartilhado) Container 3 App :8080 Container 4 BD :5432 Cada container é um processo filho — nenhum daemon central necessário

Podman (Pod Manager) é um motor de containers de código aberto e sem daemon, desenvolvido pela Red Hat, que fornece uma CLI compatível com Docker para construir, executar e gerenciar containers e pods OCI. Diferentemente do Docker, o Podman não requer um daemon em segundo plano com privilégios de root, tornando-o inerentemente mais seguro tanto para estações de trabalho de desenvolvimento quanto para servidores de produção. Se você tem usado Docker e está procurando uma alternativa mais segura, compatível com systemd e que execute containers como seu usuário regular, o Podman é a ferramenta a adotar.

Este guia cobre tudo que você precisa para começar com o Podman no Ubuntu: instalação, execução de containers sem root, gerenciamento de imagens, criação de pods, compatibilidade com Compose, integração com systemd, redes e um caminho completo de migração a partir do Docker.

Pré-requisitos

Antes de começar, certifique-se de ter:

  • Um sistema executando Ubuntu 22.04 ou 24.04 (edição desktop ou servidor)
  • Acesso ao terminal com privilégios sudo
  • Uma conexão estável com a internet
  • Familiaridade básica com containers e a linha de comando do Linux
  • Pelo menos 2 GB de espaço livre em disco para imagens

Nota: O Podman funciona em qualquer distribuição Linux moderna, mas este guia foca no Ubuntu. Se você está migrando do Docker, nenhuma instalação do Docker é necessária — o Podman o substitui completamente.

O Que É o Podman?

Podman é uma ferramenta de gerenciamento de containers que implementa a mesma interface CLI que o Docker, mas com uma arquitetura fundamentalmente diferente. O nome vem de Pod Manager, refletindo seu suporte nativo para pods estilo Kubernetes — grupos de containers que compartilham namespaces de rede e IPC.

Características principais do Podman:

  • Sem daemon: Nenhum serviço em segundo plano é executado como root. Cada comando podman lança containers diretamente como processos filhos via conmon (o monitor de containers).
  • Sem root por padrão: Os containers são executados sob sua conta de usuário regular usando user namespaces do Linux, sem necessidade de privilégios root.
  • Compatível com OCI: O Podman constrói e executa imagens que estão em conformidade com a especificação Open Container Initiative (OCI), garantindo total compatibilidade com imagens e registros Docker.
  • Pods nativos: O Podman pode agrupar containers em pods, espelhando a semântica de pods do Kubernetes para desenvolvimento e testes locais.
  • Integração com systemd: O Podman gera arquivos de unidade systemd a partir de containers em execução, facilitando o gerenciamento do ciclo de vida dos containers como serviços do sistema.

Podman vs Docker

Entender as diferenças arquiteturais entre Podman e Docker ajuda você a tomar uma decisão informada e planejar sua migração.

CaracterísticaPodmanDocker
ArquiteturaSem daemon (fork/exec)Cliente-servidor (daemon dockerd)
Requisito de rootSem root por padrãoRequer daemon root (modo sem root opcional)
Runtime de containerscrun / runc via conmoncontainerd + runc
Compatibilidade CLISubstituto direto (podman = docker)CLI nativa
Suporte a podsNativo (estilo Kubernetes)Não disponível
Suporte Composepodman-compose / podman composedocker compose (plugin integrado)
Integração systemdNativa (podman generate systemd)Requer arquivos de unidade manuais
Formato de imagemOCI / DockerOCI / Docker
Ferramenta de buildBuildah (integrado)BuildKit
Modelo de segurançaSem daemon root, user namespacesDaemon root, sem root opcional
SocketOpcional (podman.socket)Obrigatório (docker.socket)

A diferença mais significativa é o daemon. O Docker requer que o daemon dockerd esteja em execução o tempo todo como root, criando um único ponto de falha e um vetor potencial de escalonamento de privilégios. O Podman elimina isso completamente — quando você executa podman run, ele diretamente cria um novo processo para o container usando conmon como monitor de containers. Se o próprio Podman falhar, os containers em execução continuam operando.

Instalar o Podman no Ubuntu

O Podman está disponível nos repositórios oficiais do Ubuntu a partir do Ubuntu 22.04. Instale-o junto com suas ferramentas de suporte:

sudo apt update
sudo apt install -y podman

Verifique a instalação:

podman --version

Saída esperada:

podman version 4.9.3

Verifique as informações do sistema para confirmar que o modo sem root está disponível:

podman info --format '{{.Host.Security.Rootless}}'

Isso deve retornar true quando executado como usuário não root.

Para a versão mais recente do Podman (se a versão do repositório do Ubuntu estiver desatualizada), você pode adicionar o repositório oficial do Kubic:

sudo mkdir -p /etc/apt/keyrings
curl -fsSL "https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/Release.key" \
  | gpg --dearmor \
  | sudo tee /etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg > /dev/null

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg] \
  https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/ /" \
  | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list > /dev/null

sudo apt update
sudo apt install -y podman

Configurar Registros de Containers

Por padrão, o Podman requer nomes de imagem totalmente qualificados (ex., docker.io/library/nginx). Para habilitar nomes curtos como nginx, configure os registros de busca não qualificados:

sudo tee /etc/containers/registries.conf.d/00-unqualified-search.conf <<'EOF'
[registries.search]
registries = ['docker.io', 'quay.io', 'ghcr.io']
EOF

Alternativamente, edite /etc/containers/registries.conf e adicione os registros de busca na seção [registries.search].

Executar Seu Primeiro Container

Com o Podman instalado, execute um container de teste como seu usuário regular (não root):

podman run --rm docker.io/library/hello-world

Você deve ver a familiar mensagem “Hello from Docker!”, confirmando que o Podman pode baixar e executar imagens OCI. Note que nenhum sudo é necessário.

Execute um container interativo:

podman run -it --rm docker.io/library/ubuntu:24.04 bash

Dentro do container, verifique o usuário:

whoami
# root (dentro do user namespace do container)
id
# uid=0(root) gid=0(root) groups=0(root)

Embora você apareça como root dentro do container, na realidade está executando como seu usuário regular no host. Este é o poder dos containers sem root com mapeamento de user namespace.

Saia do container com exit ou Ctrl+D.

Containers sem Root

Containers sem root são a característica definidora do Podman. Entender como funcionam ajuda a solucionar problemas de permissão e projetar implantações seguras de containers.

Como Funcionam os Containers sem Root

Quando você executa um container como usuário não root, o Podman usa user namespaces do Linux para criar um ambiente isolado onde:

  1. O processo do container se vê como root (UID 0) dentro do container.
  2. No host, o processo é executado como um UID subordinado mapeado do intervalo permitido do seu usuário.
  3. O mapeamento é definido em /etc/subuid e /etc/subgid.

Verifique os mapeamentos de UID/GID subordinados do seu usuário:

cat /etc/subuid
# jc:100000:65536

cat /etc/subgid
# jc:100000:65536

Isso significa que o usuário jc pode mapear UIDs de 100000 a 165535 dentro dos containers. O UID 0 do container mapeia para o UID do seu usuário no host, e os UIDs 1-65535 dentro do container mapeiam para os UIDs 100000-165535 do host.

Verificar a Operação sem Root

Execute um container e verifique o processo a partir do host:

podman run -d --name test-rootless docker.io/library/nginx:alpine

A partir de outro terminal no host:

ps aux | grep nginx
# jc  12345  ... nginx: master process

O processo nginx é executado como seu usuário (jc), não como root. Se o container fosse comprometido, o atacante teria apenas os privilégios do seu usuário — não acesso root ao host.

Configurar User Namespaces

Se /etc/subuid ou /etc/subgid não contêm entradas para seu usuário, adicione-as:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

Após modificar esses arquivos, reinicie o armazenamento do Podman para aplicar as alterações:

podman system migrate

Trabalhar com Imagens

O Podman usa o mesmo formato de imagem que o Docker e pode baixar de qualquer registro compatível com OCI.

Baixar Imagens

# Baixar do Docker Hub
podman pull docker.io/library/nginx:alpine

# Baixar do Quay.io
podman pull quay.io/podman/hello

# Baixar do GitHub Container Registry
podman pull ghcr.io/actions/actions-runner:latest

Listar Imagens

podman images

Saída:

REPOSITORY                        TAG       IMAGE ID      CREATED       SIZE
docker.io/library/nginx           alpine    a2bd6d6e82f0  2 weeks ago   43.3 MB
quay.io/podman/hello              latest    5dd467fce50b  3 months ago  787 kB

Construir Imagens

O Podman usa Containerfile (ou Dockerfile — ambos são suportados) e o Buildah internamente:

# Containerfile
FROM docker.io/library/python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]

Construa a imagem:

podman build -t my-python-app:latest .

Construir com um nome de arquivo específico:

podman build -f Containerfile.prod -t my-python-app:prod .

Enviar Imagens para um Registro

Marque e envie uma imagem para um registro:

podman tag my-python-app:latest quay.io/myuser/my-python-app:latest
podman login quay.io
podman push quay.io/myuser/my-python-app:latest

Remover Imagens

# Remover uma imagem específica
podman rmi docker.io/library/nginx:alpine

# Remover todas as imagens não utilizadas
podman image prune -a

Gerenciamento de Pods

Pods são um conceito emprestado do Kubernetes. Um pod agrupa um ou mais containers que compartilham o mesmo namespace de rede, o que significa que podem se comunicar através do localhost e compartilhar mapeamentos de portas.

Criar um Pod

Crie um pod com mapeamentos de portas definidos no nível do pod:

podman pod create --name my-web-pod -p 8080:80 -p 5432:5432

Adicionar Containers a um Pod

Adicione um container nginx e um container PostgreSQL ao pod:

podman run -d --pod my-web-pod --name web-server docker.io/library/nginx:alpine

podman run -d --pod my-web-pod --name db-server \
  -e POSTGRES_PASSWORD=secretpass \
  -e POSTGRES_DB=appdb \
  docker.io/library/postgres:16-alpine

Ambos os containers agora compartilham o mesmo namespace de rede. O container nginx pode se conectar ao PostgreSQL em localhost:5432, e clientes externos acessam o nginx via host:8080.

Gerenciar Pods

# Listar todos os pods
podman pod ls

# Ver detalhes do pod
podman pod inspect my-web-pod

# Parar todos os containers em um pod
podman pod stop my-web-pod

# Iniciar um pod
podman pod start my-web-pod

# Remover um pod e seus containers
podman pod rm -f my-web-pod

Gerar YAML do Kubernetes a partir de Pods

Uma das características únicas do Podman é gerar manifestos do Kubernetes a partir de pods em execução:

podman generate kube my-web-pod > my-web-pod.yaml

Isso cria um arquivo YAML compatível com Kubernetes que você pode implantar diretamente em um cluster Kubernetes com kubectl apply -f my-web-pod.yaml. Isso torna o Podman uma excelente ferramenta para desenvolvimento local quando seu alvo de produção é o Kubernetes.

Podman Compose

O Podman suporta arquivos Docker Compose para stacks de aplicações multi-container. Existem duas abordagens:

Usando podman-compose

Instale o podman-compose (uma reimplementação comunitária em Python):

sudo apt install -y python3-pip
pip3 install podman-compose

Use-o exatamente como o docker-compose:

podman-compose up -d
podman-compose ps
podman-compose logs -f
podman-compose down

Usando o Comando Integrado podman compose

O Podman 4.7+ inclui um comando integrado podman compose que delega para um provedor de compose externo (docker-compose ou podman-compose):

podman compose up -d
podman compose down

Exemplo de docker-compose.yml

Um arquivo docker-compose.yml padrão funciona sem modificação:

version: "3.8"
services:
  web:
    image: docker.io/library/nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api

  api:
    image: docker.io/library/node:20-alpine
    working_dir: /app
    volumes:
      - ./api:/app
    command: node server.js
    environment:
      - DB_HOST=db
      - DB_PORT=5432

  db:
    image: docker.io/library/postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: secretpass
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Execute com Podman Compose:

podman-compose up -d

Gerar Unidades systemd a partir de Containers

O Podman se integra com o systemd para gerenciar containers como serviços do sistema. Isso é especialmente útil para servidores onde você precisa que os containers iniciem na inicialização e reiniciem em caso de falha.

Gerar um Arquivo de Unidade a partir de um Container em Execução

Primeiro, inicie um container:

podman run -d --name my-nginx -p 8080:80 docker.io/library/nginx:alpine

Gere a unidade systemd:

podman generate systemd --new --name my-nginx > ~/.config/systemd/user/container-my-nginx.service

A flag --new garante que o arquivo de unidade crie um container novo cada vez (em vez de reiniciar um existente), o que é a prática recomendada.

Habilitar e Iniciar o Serviço

mkdir -p ~/.config/systemd/user
systemctl --user daemon-reload
systemctl --user enable --now container-my-nginx.service

Habilitar Lingering para Sessões sem Login

Por padrão, os serviços systemd de usuário param quando o usuário faz logout. Habilite o lingering para mantê-los em execução:

sudo loginctl enable-linger $USER

Verificar o Serviço

systemctl --user status container-my-nginx.service

Quadlet (Podman 4.4+)

Para Podman 4.4 e posterior, o Quadlet fornece um formato declarativo mais simples. Crie um arquivo .container em ~/.config/containers/systemd/:

# ~/.config/containers/systemd/my-nginx.container
[Container]
Image=docker.io/library/nginx:alpine
PublishPort=8080:80
Volume=./html:/usr/share/nginx/html:ro

[Service]
Restart=always

[Install]
WantedBy=default.target

Recarregue o systemd e inicie o serviço:

systemctl --user daemon-reload
systemctl --user start my-nginx.service

Migrar do Docker para o Podman

Se você está usando Docker atualmente, o caminho de migração para o Podman é direto.

Instalar o Pacote de Compatibilidade Docker

sudo apt install -y podman-docker

Isso instala um comando docker que é alias para o podman e cria um socket de emulação /var/run/docker.sock. Scripts existentes que chamam docker usarão o Podman em seu lugar.

Migrar Imagens Docker

Exporte imagens do Docker e importe-as no Podman:

# No sistema Docker
docker save my-app:latest -o my-app.tar

# No sistema Podman
podman load -i my-app.tar

Converter Arquivos Docker Compose

A maioria dos arquivos docker-compose.yml funciona sem modificação. Os principais ajustes a observar:

  1. Qualificar completamente os nomes de imagem: Substitua nginx:alpine por docker.io/library/nginx:alpine
  2. Modo de rede: Alguns modos de rede específicos do Docker podem diferir
  3. Plugins de volume: Plugins de volume do Docker não são suportados; use os drivers de volume nativos do Podman

Atualizar Pipelines CI/CD

Substitua comandos docker por podman nos scripts do seu pipeline, ou instale podman-docker para que o alias docker cuide disso:

# Exemplo de GitHub Actions
steps:
  - name: Install Podman
    run: sudo apt install -y podman podman-docker

  - name: Build image
    run: podman build -t my-app:${{ github.sha }} .

  - name: Push image
    run: |
      podman login -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_PASS }} ghcr.io
      podman push my-app:${{ github.sha }} ghcr.io/${{ github.repository }}:${{ github.sha }}

Redes

O modelo de rede do Podman difere entre os modos com root e sem root.

Redes sem Root

No modo sem root, o Podman usa slirp4netns ou pasta (Podman 5.0+) para fornecer conectividade de rede sem privilégios de root:

  • slirp4netns: Cria um dispositivo TAP em um user namespace, fornecendo rede baseada em NAT. O encaminhamento de portas acima de 1024 funciona sem root.
  • pasta: Uma alternativa mais nova e rápida que fornece desempenho aprimorado e menor sobrecarga.

Mapear portas no modo sem root:

podman run -d -p 8080:80 docker.io/library/nginx:alpine

Nota: Vincular a portas abaixo de 1024 (ex., 80, 443) requer privilégios de root ou ajustar o início de portas não privilegiadas do sistema com sudo sysctl net.ipv4.ip_unprivileged_port_start=80.

CNI e Netavark

O Podman suporta dois backends de rede:

  • CNI (Container Network Interface): O backend legacy usando plugins CNI.
  • Netavark: A pilha de rede moderna baseada em Rust (padrão no Podman 4.0+).

Criar uma rede personalizada:

podman network create my-network

Executar containers na rede personalizada:

podman run -d --network my-network --name container-a docker.io/library/alpine sleep 3600
podman run -d --network my-network --name container-b docker.io/library/alpine sleep 3600

Containers na mesma rede podem se alcançar pelo nome:

podman exec container-a ping -c 3 container-b

Inspecionar Redes

# Listar redes
podman network ls

# Inspecionar uma rede
podman network inspect my-network

# Remover uma rede
podman network rm my-network

Referência de Comandos do Podman

A tabela a seguir lista os comandos do Podman mais utilizados e seus equivalentes no Docker:

Comando PodmanEquivalente DockerDescrição
podman rundocker runCriar e iniciar um container
podman psdocker psListar containers em execução
podman ps -adocker ps -aListar todos os containers
podman imagesdocker imagesListar imagens locais
podman pulldocker pullBaixar uma imagem de um registro
podman builddocker buildConstruir uma imagem a partir de um Containerfile/Dockerfile
podman pushdocker pushEnviar uma imagem para um registro
podman execdocker execExecutar um comando em um container em execução
podman logsdocker logsVisualizar logs do container
podman stopdocker stopParar um container em execução
podman rmdocker rmRemover um container
podman rmidocker rmiRemover uma imagem
podman volume createdocker volume createCriar um volume nomeado
podman network createdocker network createCriar uma rede
podman pod createN/ACriar um pod
podman pod lsN/AListar pods
podman generate systemdN/AGerar arquivos de unidade systemd
podman generate kubeN/AGerar YAML do Kubernetes
podman system prunedocker system pruneRemover dados não utilizados
podman logindocker loginFazer login em um registro de containers
podman inspectdocker inspectVer informações detalhadas de container/imagem

Solução de Problemas

Erro: short-name resolution enforced

Problema: O Podman se recusa a baixar uma imagem usando um nome curto como nginx.

Solução: Use o nome de imagem totalmente qualificado ou configure os registros de busca:

# Usar nome totalmente qualificado
podman pull docker.io/library/nginx:alpine

# Ou configurar registros de busca
sudo tee /etc/containers/registries.conf.d/00-unqualified-search.conf <<'EOF'
[registries.search]
registries = ['docker.io', 'quay.io']
EOF

Erro: cannot find UID/GID mapping

Problema: Containers sem root falham porque os mapeamentos de UID/GID subordinados não estão configurados.

Solução: Adicione mapeamentos para seu usuário:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
podman system migrate

Erro: permission denied on volume mount

Problema: Um container sem root não consegue acessar um diretório montado por bind.

Solução: Adicione o sufixo de rótulo SELinux :Z ou :z, ou garanta que o diretório seja de propriedade do seu usuário:

# Corrigir propriedade
podman unshare chown -R 0:0 /path/to/volume

# Ou usar flag Z para SELinux
podman run -v /path/to/volume:/data:Z my-image

Container Não Consegue Vincular à Porta 80

Problema: Podman sem root não consegue vincular a portas abaixo de 1024.

Solução: Reduza o valor de início de portas não privilegiadas:

sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80
# Tornar persistente
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/99-podman-ports.conf
sudo sysctl --system

Podman Compose Falha com Erro de Rede

Problema: O podman-compose apresenta erros ao criar redes.

Solução: Certifique-se de que o backend de rede do Podman está funcionando e reinicie se necessário:

podman network ls
podman system reset --force
# Recrie seus containers após o reset

Containers Não Iniciam Após Reinicialização

Problema: Containers systemd no nível do usuário não iniciam após uma reinicialização.

Solução: Habilite o lingering para seu usuário:

sudo loginctl enable-linger $USER

Download Lento de Imagens

Problema: O download de imagens é lento no modo sem root.

Solução: Habilite o fuse-overlayfs para melhor desempenho de armazenamento:

sudo apt install -y fuse-overlayfs

Verifique se está sendo utilizado:

podman info --format '{{.Store.GraphDriverName}}'
# Deve exibir: overlay

Resumo

O Podman é um motor de containers maduro, seguro e compatível com Docker que elimina a necessidade de um processo daemon privilegiado. Sua abordagem sem root por padrão, suporte nativo a pods e integração com systemd o tornam uma excelente escolha tanto para ambientes Linux de desenvolvimento quanto de produção. Para qualquer pessoa que execute containers em servidores Linux, o Podman fornece uma clara vantagem de segurança sem sacrificar compatibilidade com o ecossistema Docker.

Neste guia você aprendeu como instalar o Podman no Ubuntu, executar containers sem root, gerenciar imagens e pods, usar o Podman Compose com arquivos docker-compose.yml existentes, gerar unidades systemd para gerenciamento automático do ciclo de vida de containers, configurar redes e migrar do Docker.

Para tópicos relacionados a containers, consulte nossos guias sobre Como Instalar o Docker no Ubuntu e Docker Compose: Guia Prático para Administradores de Sistemas.