TL;DR — Resumo Rápido

Guia completo do Podman Compose para orquestração rootless. Instale, configure e migre do Docker Compose com systemd e Quadlet no Ubuntu e Fedora.

PODMAN COMPOSE — ORQUESTRAÇÃO ROOTLESS podman pod (namespace de usuário rootless) app (Node.js) porta: 3000 depends_on: db healthcheck: /health db (PostgreSQL) porta: 5432 volume: pgdata:Z healthcheck: pg_isready redis (Cache) porta: 6379 volume: redis-data healthcheck: ping systemd Quadlet início auto unidades usuário Sem daemon root — contêineres executam como seu usuário via namespaces Linux

O Podman Compose traz o fluxo de trabalho familiar do Docker Compose para o motor de contêineres Podman, que é sem daemon e rootless. Se você procura uma alternativa ao Docker que não exija um daemon privilegiado em segundo plano, não exponha superfície de ataque root e se integre nativamente ao systemd, este guia é para você. Você aprenderá a instalar o Podman e o podman-compose, configurar namespaces de usuário rootless, migrar projetos Docker Compose existentes, gerenciar pods e habilitar o início automático através do Quadlet.

Pré-requisitos

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

  • Um sistema Linux: Ubuntu 22.04/24.04, Fedora 39+ ou RHEL/Rocky Linux 9
  • Uma conta de usuário normal (root não é necessário para operações diárias)
  • Conhecimento básico da sintaxe YAML do Docker Compose
  • Acesso a sudo apenas para a instalação inicial

Por Que Usar o Podman em Vez do Docker?

A arquitetura do Docker centraliza-se em um daemon privilegiado (dockerd) executando como root. Cada chamada ao CLI docker passa por um socket Unix de propriedade do root, o que significa que qualquer processo que possa acessar o socket Docker tem efetivamente root no host.

O Podman adota uma abordagem fundamentalmente diferente:

AspectoDockerPodman
ArquiteturaCliente-servidor daemonFork/exec, sem daemon
Privilégio padrãoExecuta como rootRootless por padrão
Suporte ComposePlugin docker composepodman-compose ou podman compose
Formato de imagemOCI (compatível com Docker)OCI (compatível com Docker)
Requisito de socket/var/run/docker.sock (root)Socket de usuário opcional
Integração systemdArquivos de unidade externosSuporte nativo com Quadlet
Compatibilidade CLIImplementação de referênciaDrop-in (alias docker=podman)

Instalação

Ubuntu 22.04 / 24.04

sudo apt update
sudo apt install -y podman
podman --version

Para Podman 5.x no Ubuntu 22.04, adicione o repositório oficial Kubic:

. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${VERSION_ID}/ /" \
  | sudo tee /etc/apt/sources.list.d/kubic-podman.list
curl -fsSL "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${VERSION_ID}/Release.key" \
  | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubic-podman.gpg
sudo apt update && sudo apt install -y podman

Fedora / RHEL / Rocky Linux

sudo dnf install -y podman          # Fedora
sudo dnf install -y container-tools # RHEL 9 / Rocky Linux 9

Alias Drop-in para Docker

sudo apt install -y podman-docker   # Ubuntu
sudo dnf install -y podman-docker   # Fedora/RHEL

Configuração de Contêineres Rootless

A operação rootless depende de namespaces de usuário Linux e mapeamentos de UID/GID definidos em /etc/subuid e /etc/subgid.

grep "^$(whoami)" /etc/subuid /etc/subgid

Se as entradas estiverem ausentes:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $(whoami)
podman system migrate
podman run --rm hello-world

Para portas abaixo de 1024:

echo 'net.ipv4.ip_unprivileged_port_start=80' | sudo tee /etc/sysctl.d/99-unprivileged-ports.conf
sudo sysctl --system

Instalação do podman-compose

# Via pip (todas as distribuições)
pip install --user podman-compose
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Fedora / RHEL
sudo dnf install -y podman-compose

# Ubuntu
sudo apt install -y podman-compose

O Podman 4.4+ inclui um subcomando podman compose embutido que delega automaticamente para podman-compose ou docker-compose:

podman compose version

Criando um compose.yaml para o Podman

O Podman Compose suporta a Especificação Compose (sintaxe v2/v3). Seus arquivos docker-compose.yml existentes funcionam sem modificações na grande maioria dos casos.

Exemplo completo de stack de produção — API Node.js com PostgreSQL e Redis:

# compose.yaml
name: myapp

services:
  api:
    build:
      context: ./api
      dockerfile: Containerfile
    image: myapp-api:latest
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DATABASE_URL: "postgresql://appuser:${DB_PASSWORD}@db:5432/appdb"
      REDIS_URL: "redis://redis:6379"
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 20s
    volumes:
      - ./api/logs:/app/logs:Z
    networks:
      - backend
    restart: unless-stopped

  db:
    image: docker.io/library/postgres:16-alpine
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: "${DB_PASSWORD}"
    volumes:
      - pgdata:/var/lib/postgresql/data:Z
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - backend
    restart: unless-stopped

  redis:
    image: docker.io/library/redis:7-alpine
    command: redis-server --save 60 1 --loglevel warning
    volumes:
      - redis-data:/data:Z
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5
    networks:
      - backend
    restart: unless-stopped

networks:
  backend:
    driver: bridge

volumes:
  pgdata:
  redis-data:

Notas específicas do Podman:

  • Prefixo docker.io/library/: O Podman não adiciona o Docker Hub como registro implícito. Sempre use referências de imagem totalmente qualificadas.
  • Rótulo de volume :Z: Em sistemas com SELinux (Fedora, RHEL, Rocky), o sufixo :Z reetiqueta o volume para que o processo do contêiner possa acessá-lo.

Inicie o stack:

podman-compose up -d
podman pod ps
podman ps
podman-compose logs -f api

Gerenciamento de Pods

Quando o podman-compose inicia um stack com múltiplos serviços, ele cria um pod do Podman que agrupa os contêineres e compartilha um namespace de rede:

podman pod ps
podman pod inspect myapp_default
podman pod stats myapp_default
podman-compose down
podman-compose down -v

Construção de Imagens com Buildah e Containerfiles

# Containerfile
FROM docker.io/library/node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

FROM docker.io/library/node:22-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
RUN adduser -D -u 1001 appuser
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
podman build -t myapp-api:latest -f Containerfile ./api

Integração com systemd: Quadlet

O Quadlet é a forma moderna de executar contêineres Podman como serviços systemd sem escrever arquivos de unidade manualmente. Vem incluído com o Podman 4.4+.

Crie ~/.config/containers/systemd/myapp-db.container:

[Unit]
Description=Banco de Dados MyApp

[Container]
Image=docker.io/library/postgres:16-alpine
Environment=POSTGRES_DB=appdb
Environment=POSTGRES_USER=appuser
EnvironmentFile=%h/.config/myapp/db.env
Volume=%h/.local/share/myapp/pgdata:/var/lib/postgresql/data:Z
HealthCmd=pg_isready -U appuser -d appdb
HealthInterval=10s

[Service]
Restart=always

[Install]
WantedBy=default.target

Ative:

systemctl --user daemon-reload
systemctl --user enable --now myapp-db
journalctl --user -u myapp-db -f
loginctl enable-linger $(whoami)

Comparação: Ferramentas de Orquestração Compose

FerramentaRootlessDaemonIntegração systemdCompose SpecExportação Kubernetes
Docker ComposeNão (rootful)Sim (dockerd)Apenas externoCompletoNão
podman-composeSimNãoVia Quadletv2/v3Não
podman composeSimNãoVia Quadletv2/v3Não
Nerdctl + containerdParcialSim (containerd)LimitadoCompletoNão
Podman QuadletSimNãoNativoDeclarativoVia podman kube generate
Kubernetes (k3s)ParcialSimExternoVia KomposeSim (nativo)

Migrando do Docker Compose

# Passo 1 — Alias docker para podman
alias docker=podman
alias docker-compose=podman-compose

echo "alias docker=podman" >> ~/.bashrc
echo "alias docker-compose=podman-compose" >> ~/.bashrc

Atualize as referências de imagem:

# Antes (Docker)
image: postgres:16-alpine

# Depois (melhor prática Podman)
image: docker.io/library/postgres:16-alpine

Adicione rótulos de volume SELinux em sistemas RHEL/Fedora e remova privileged: true onde possível.

Casos Especiais e Advertências

Diferenças de rede: O modo rootless do Podman usa pasta/slirp4netns em vez de redes bridge do kernel. Redes macvlan e ipvlan requerem modo root.

Portas abaixo de 1024: Contêineres rootless não podem vincular portas de host abaixo de 1024 por padrão. Configure net.ipv4.ip_unprivileged_port_start=80 ou use um proxy reverso.

Compatibilidade com docker.sock: Ferramentas como Portainer requerem o socket Docker. O Podman fornece um socket compatível via podman system service. Inicie com systemctl --user start podman.socket.

Negações do SELinux: Se uma montagem de volume falhar no RHEL/Fedora, adicione o rótulo :Z. Nunca desabilite o SELinux.

Solução de Problemas

Erros de “short-name resolution”: O Podman requer nomes de imagem totalmente qualificados. Adicione unqualified-search-registries = ["docker.io"] ao /etc/containers/registries.conf.

“newuidmap/newgidmap not found”: Instale o pacote uidmap (sudo apt install uidmap).

Contêiner não acessa a internet: Instale slirp4netns (sudo apt install slirp4netns) ou passt no Ubuntu 24.04 (sudo apt install passt).

Resumo

  • O Podman é um motor de contêineres sem daemon e rootless por padrão, compatível com OCI e o CLI do Docker
  • O podman-compose suporta Compose Spec v2/v3 e executa stacks de múltiplos serviços sem privilégios root
  • Configure /etc/subuid e /etc/subgid para mapeamento de UID rootless antes de executar cargas de trabalho com múltiplos contêineres
  • Sempre use referências de imagem totalmente qualificadas e adicione rótulos de volume :Z em sistemas com SELinux
  • O Quadlet fornece integração nativa com systemd para início automático e registro de journal de serviços em contêineres
  • Para cargas de trabalho em produção, prefira o Quadlet ao podman generate systemd para definições de serviços declarativas e manuteníveis

Artigos Relacionados