Back

Docker vs Podman em 2026: O guia completo de migração que ninguém pediu (mas todo mundo precisa)

Algo estranho tá rolando no mundo dos containers. Docker — a ferramenta que literalmente inventou containerização — tá perdendo espaço de mansinho. E não pra uma startup badalada, mas pra um projeto open-source que a maioria dos devs nem testou ainda: Podman.

Os números são claros. As estrelas do Podman no GitHub passaram de 30.000 no início de 2026. Red Hat, SUSE e Canonical incluem ele de fábrica nas distros. Kubernetes tirou o Docker como runtime na versão 1.24, e desde então muitos times começaram a se perguntar "será que nossa stack de containers tá boa assim?". Pra completar, as mudanças de licenciamento do Docker Desktop transformaram "a ferramenta grátis que todo mundo usa" em "algo que custa 24/me^s/usuaˊrioseaempresatemmaisde250funcionaˊriosoufaturamaisde24/mês/usuário se a empresa tem mais de 250 funcionários ou fatura mais de 10M."

Mas a maioria dos artigos de comparação erra o alvo: não se trata de Podman ser "melhor" que Docker. Se trata de entender se o seu workflow, tamanho do time, requisitos de segurança e target de deploy fazem um ser concretamente melhor que o outro pro seu caso.

Nesse guia a gente mergulha nas diferenças de arquitetura, percorre cenários reais de migração, mede o que realmente importa e monta um framework de decisão concreto. Sem enrolação e sem "depende" genérico. Bora.

Arquitetura: A divisão fundamental

Antes de mais nada, precisa entender a maior diferença de design entre Docker e Podman. Todo o resto vem daí.

Docker: tem um daemon rodando o tempo todo

Docker funciona com uma arquitetura cliente-servidor onde um daemon persistente (dockerd) fica sempre em background:

┌─────────────┐     ┌──────────────┐     ┌───────────────┐
│ docker CLI  │────▶│   dockerd    │────▶│  containerd   │
│  (cliente)  │     │   (daemon)   │     │   (runtime)   │
└─────────────┘     └──────────────┘     └───────────────┘
                          │
                    Roda como root
                    Sempre escutando
                    Gerencia todos os containers

Quando você roda docker run nginx, o CLI manda um request pro daemon, que baixa a imagem, cria o container e gerencia o ciclo de vida inteiro. Roda como root por padrão e gerencia todos os containers do sistema a partir de um único processo.

As vantagens são reais:

  • Gerenciamento central: um processo tem visibilidade de todo o estado
  • Background transparente: containers continuam vivos mesmo se você fechar o terminal
  • Ecossistema depende dele: Docker Compose, Swarm e milhares de ferramentas esperam o socket do daemon

Os custos também:

  • Superfície de ataque grande: daemon roda como root. Se for comprometido, atacante ganha root no host
  • Ponto único de falha: dockerd caiu, todos os containers caem junto
  • Recursos em idle: daemon consome memória e CPU mesmo quando tá parado

Podman: sem daemon

Podman resolve de outro jeito. Não tem daemon nenhum.

┌─────────────┐     ┌───────────────┐
│ podman CLI  │────▶│    conmon     │
│  (direto)   │     │ (monitor por  │
└─────────────┘     │  container)   │
                    └───────────────┘
                          │
                    Roda como usuário
                    Modelo fork-exec
                    Cada container independente

Quando você roda podman run nginx, Podman forkeia diretamente o processo do container usando conmon (um monitor leve). Sem daemon. Cada container roda como processo independente na sua conta de usuário.

O que você ganha com isso?

  • Sem root: containers rodam com seu UID por padrão
  • Sem ponto único de falha: um container caindo não afeta os outros
  • Zero overhead em idle: nada roda quando você não tá usando containers
  • Integração com systemd: containers viram serviços systemd normais

O que perde?

  • Sem estado centralizado: gerenciamento por sessão (o banco do Podman cuida da persistência)
  • Background precisa de setup: pra container sobreviver ao logout precisa de podman generate systemd ou flags --restart
  • Ferramentas que esperam Docker: as que dependem de /var/run/docker.sock precisam de adaptação

Segurança: Por que isso realmente importa

"Containers rootless" parece buzzword até você entender o que concretamente isso previne.

O problema do root no Docker

O daemon do Docker roda como root por padrão. Quando você monta um volume com -v /host/path:/container/path, o processo do container pode ler e escrever esses arquivos como root no host. Docker tem mitigações (user namespaces, seccomp, AppArmor), mas são opt-in e a maioria dos times não ativa.

Pra dimensionar o risco:

# Escape de container com daemon root docker run -v /:/host --privileged alpine chroot /host # → acesso root completo ao filesystem do host

O modo rootless do Docker (disponível desde 20.10) resolve, mas precisa de configuração explícita:

# Habilitar rootless dockerd-rootless-setuptool.sh install # Verificar docker info | grep "Root Dir" # Deve mostrar algo em ~/.local/share/docker

Na prática, a maioria das instalações continua rodando o daemon como root. É o padrão e a maioria dos tutoriais nem menciona rootless.

Podman: rootless de fábrica

Podman roda rootless sem configurar nada. Sai assim da caixa:

# Funciona direto, sem root, sem daemon, sem setup podman run -d nginx # Verificar que roda com seu usuário podman top -l user # Mostra seu UID, não root

Por baixo dos panos, Podman usa Linux user namespaces pra mapear UIDs do container pra UIDs não-privilegiados do host:

# Dentro do container, nginx acha que é root (UID 0) # Mas no host, tá rodando como seu usuário (ex: UID 1000) podman unshare cat /proc/self/uid_map # Output: # 0 1000 1 # 1 100000 65536

Se alguém escapar do container, obtém apenas os permissões do seu usuário não-privilegiado. Root fica fora de alcance.

Segurança: a comparação

FeatureDocker (padrão)Docker (rootless)Podman
Daemon roda comorootusuárioSem daemon
UID do container no hostrootmapeadomapeado
Socket privilegiado/var/run/docker.sock (root)$XDG_RUNTIME_DIR/docker.sockNenhum
Capabilities padrãoAmplasReduzidasMínimas
SELinux/AppArmorOpcionalOpcionalHabilitado por padrão
Perfil SeccompPerfil padrãoPerfil padrãoPadrão mais restritivo
Se daemon comprometidoAcesso root completoAcesso de usuárioN/A

Pra times com requisitos de compliance (SOC 2, PCI-DSS, HIPAA), a postura de segurança do Podman simplifica muito a auditoria.

Compatibilidade CLI: A realidade do "alias docker=podman"

Uma das decisões mais inteligentes do Podman foi fazer a CLI praticamente 100% compatível com Docker:

# Adiciona no .bashrc/.zshrc alias docker=podman # E tudo isso funciona normalmente: docker pull nginx docker run -d -p 8080:80 nginx docker ps docker build -t myapp . docker push myregistry/myapp

O que funciona direto

  • docker run / build / pull / push
  • docker ps / logs / exec
  • docker images / rmi
  • docker network create/ls/rm
  • docker volume create/ls/rm

O que não funciona

Docker Compose — Podman oferece podman-compose e suporta Docker Compose v2 via socket de compatibilidade:

# Opção 1: podman-compose (Python, mais simples) pip install podman-compose podman-compose up -d # Opção 2: socket compatível → Docker Compose v2 systemctl --user enable --now podman.socket export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock docker compose up -d

Docker Swarm — Podman não suporta. Se você usa Swarm (cada vez mais raro), é blocker total.

Docker-in-Docker (DinD) — Comum em CI/CD, mas no Podman é diferente:

# Docker: precisa de privileged docker run --privileged -v /var/run/docker.sock:/var/run/docker.sock docker # Podman: rootless, sem privileged podman run --security-opt label=disable \ -v $XDG_RUNTIME_DIR/podman/podman.sock:/var/run/docker.sock \ docker

Features do Docker Desktop — GUI, Kubernetes integrado, Extensions e Dev Environments não têm equivalente direto no Podman. Podman Desktop cobre parte, mas não é a mesma coisa.

Kubernetes: A vantagem real do Podman

Aqui o Podman tem algo que Docker não consegue replicar por design.

Suporte nativo a Pods

Podman trabalha com pods — grupos de containers que compartilham network namespace, igual ao Kubernetes — como cidadãos de primeira classe:

# Criar um pod podman pod create --name webapp -p 8080:80 # Adicionar containers podman run -d --pod webapp --name frontend nginx podman run -d --pod webapp --name api node:20-slim # Ambos compartilham localhost # frontend acessa a API em localhost:3000

Isso é exatamente como o Kubernetes organiza containers. Docker não tem esse conceito — cada container vive no seu próprio network namespace.

Gerar YAML do Kubernetes

Dá pra exportar um pod rodando diretamente pra YAML compatível com Kubernetes:

# Gerar YAML de um pod em execução podman generate kube webapp > webapp.yaml cat webapp.yaml
# Gerado pelo Podman apiVersion: v1 kind: Pod metadata: name: webapp spec: containers: - name: frontend image: docker.io/library/nginx:latest ports: - containerPort: 80 hostPort: 8080 - name: api image: docker.io/library/node:20-slim

E funciona na direção inversa:

# Rodar YAML Kubernetes localmente podman play kube webapp.yaml # Derrubar podman play kube webapp.yaml --down

Esse workflow de podman play kube tem usos muito concretos:

  • Desenvolvimento local que replica produção Kubernetes exatamente
  • Testar manifests sem levantar cluster
  • Migração gradual de Docker Compose pra Kubernetes

Docker e Kubernetes: a relação é indireta

A abordagem do Docker pro Kubernetes passa por ferramentas intermediárias:

# Docker Desktop inclui K8s single-node # Mas é um cluster K8s completo, não um conceito leve de pod # Converter Compose pra K8s precisa de ferramenta externa kompose convert -f docker-compose.yaml # → o output geralmente precisa de bastante edição manual

Docker Compose e Kubernetes são abstrações fundamentalmente diferentes. Compose define serviços, Kubernetes define workloads. A conversão sempre perde informação. O conceito de pod do Podman fecha essa lacuna nativamente.

Docker Compose vs Podman Compose: O que rola na prática

A maioria dos devs não roda container solto — orquestra vários containers com Compose. Aqui a migração fica interessante.

Docker Compose (v2)

Docker Compose v2 é maduro e com bastante rodagem em produção:

# docker-compose.yaml services: web: build: ./frontend ports: - "3000:3000" depends_on: - api - db environment: - API_URL=http://api:4000 api: build: ./backend ports: - "4000:4000" depends_on: db: condition: service_healthy environment: - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp db: image: postgres:16 volumes: - pgdata:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=secret healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 volumes: pgdata:
docker compose up -d docker compose logs -f docker compose down

As opções no Podman

Opção 1: podman-compose (Python, da comunidade):

pip install podman-compose podman-compose up -d

Simples e leve. Mas não cobre todas as features do Docker Compose v2 (healthcheck.condition, alguns modos de rede, profiles).

Opção 2: Docker Compose v2 via socket Podman (pra setups complexos):

# Levantar socket Docker-compatível do Podman systemctl --user start podman.socket # Apontar CLI pro Podman export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock # Docker Compose funciona normalmente docker compose up -d

Passando pela API compatível do Podman, a compatibilidade é total. É o caminho mais suave pra arquivos Compose complexos.

Opção 3: Quadlet (nativo do Podman, integrado com systemd):

# ~/.config/containers/systemd/webapp.container [Container] Image=docker.io/library/nginx:latest PublishPort=8080:80 Volume=webdata:/usr/share/nginx/html [Service] Restart=always [Install] WantedBy=default.target
systemctl --user daemon-reload systemctl --user start webapp.service

Quadlet define containers como unit files do systemd. Mais voltado pra produção que Compose, mas precisa reescrever a orquestração.

CI/CD: Integração em pipelines

CI/CD é a parte mais chatinha da migração, porque quase toda infra CI foi construída pensando em Docker.

GitHub Actions

Docker (padrão):

jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build image run: docker build -t myapp:${{ github.sha }} . - name: Push to registry run: | echo ${{ secrets.REGISTRY_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin docker push ghcr.io/${{ github.repository }}/myapp:${{ github.sha }}

Podman (substituição direta):

jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build image run: podman build -t myapp:${{ github.sha }} . - name: Push to registry run: | podman login ghcr.io -u ${{ github.actor }} -p ${{ secrets.REGISTRY_TOKEN }} podman push ghcr.io/${{ github.repository }}/myapp:${{ github.sha }}

Podman vem pré-instalado nos runners ubuntu-latest do GitHub. Literalmente troca o nome do comando e pronto.

GitLab CI

GitLab CI tradicionalmente usa DinD (Docker-in-Docker), que precisa de modo privilegiado:

Docker (precisa de privileged):

build: image: docker:latest services: - docker:dind variables: DOCKER_TLS_CERTDIR: "/certs" script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

Podman (sem privileged):

build: image: quay.io/podman/stable script: - podman build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - podman push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

Não precisar de --privileged elimina uma superfície de ataque importante no CI. Mudança silenciosa mas de peso.

Buildah: builds especializados

O ecossistema do Podman inclui o Buildah, ferramenta dedicada a construir imagens com capacidades que docker build não tem:

# Build from scratch: sem imagem base, superfície de ataque mínima container=$(buildah from scratch) buildah copy $container ./static-binary /app buildah config --entrypoint '["/app"]' $container buildah commit $container myapp:minimal # → imagem sem pacotes, sem shell, só o binário
# Controle no nível de cada camada buildah run $container -- pip install -r requirements.txt buildah run $container -- pip cache purge buildah commit $container myapp:optimized

Buildah é especialmente útil em ambientes com segurança rigorosa, porque nunca levanta daemon e consegue buildar imagens sem runtime de container nenhum.

Benchmarks: Os números que importam

Vamos ao que realmente faz diferença no dia a dia:

Startup

Início de container (nginx, Alpine, SSD):

Docker:  ~0.8-1.2s  (daemon já rodando)
Podman:  ~0.5-0.9s  (fork-exec, sem daemon)

Primeiro container depois do boot:
Docker:  ~2-4s  (tem que esperar o daemon)
Podman:  ~0.5-0.9s  (não tem daemon pra esperar)

Podman ganha no cold-start. Em servidores long-running onde o daemon já tá de pé, a diferença é irrelevante.

Build

Build de imagem (Node.js multi-stage, cache frio):

Docker BuildKit:  ~45-60s
Podman (Buildah): ~48-65s

Cache quente:
Docker BuildKit:  ~3-5s
Podman (Buildah): ~3-5s

Praticamente igual. BuildKit tem leves vantagens em cache pra builds multi-stage complexos, mas a diferença raramente passa dos 10%.

Memória

Consumo idle:

Docker daemon:     ~50-100MB (sempre rodando)
Podman:            ~0MB (nada roda em idle)

Por container:
Docker:            ~5-10MB (conmon + shim)
Podman:            ~3-8MB (só conmon)

Custo zero em idle pesa em máquinas de dev e runners CI. Num servidor de produção com 50+ containers, o overhead por container é quase idêntico.

Pull de imagens

nginx:latest (comprimido ~70MB):
Docker:   ~4-6s
Podman:   ~4-6s

Imagem ML grande (~5GB):
Docker:   ~45-90s
Podman:   ~45-90s

Sem diferença relevante. Mesmo protocolo OCI, mesma velocidade.

Docker Desktop vs Podman Desktop

Pra devs em macOS e Windows, a experiência desktop importa:

Docker Desktop

  • Custo: grátis pra uso pessoal, educação e empresas <250 funcionários com faturamento <10M.10M. 24/mês/usuário pro resto (Business tier)
  • Kubernetes: cluster single-node integrado
  • Extensions: marketplace com 100+ extensões
  • Dev Environments: ambientes remotos estilo Codespaces
  • VM: gerenciamento automático de VM Linux em macOS/Windows
  • Recursos: GUI pra limites de CPU/memória
  • Volumes: GUI pra inspeção e gerenciamento

Podman Desktop

  • Custo: grátis, open-source (Apache 2.0)
  • Kubernetes: integração Kind/Minikube (não integrado)
  • Extensions: sistema de plugins crescendo
  • VM: gerenciamento automático via podman machine
  • Recursos: controles básicos de CPU/memória
  • Pods: UI de primeira classe pra criar e gerenciar pods

Pra devs solo e times pequenos, Podman Desktop compete bem. Pra times maiores que dependem das Extensions, Dev Environments ou features enterprise do Docker Desktop (SSO, gestão de acesso a imagens, Hardened Desktop), Docker ainda leva vantagem.

Playbook de migração: De Docker pra Podman

Se decidiu migrar, essa é a ordem que funciona melhor:

Fase 1: Desenvolvimento local (Semana 1-2)

# 1. Instalar # macOS: brew install podman podman machine init podman machine start # Linux (Ubuntu/Debian): sudo apt install podman # 2. Alias (não quebra nada, Docker continua funcionando) echo 'alias docker=podman' >> ~/.zshrc source ~/.zshrc # 3. Testar workflows existentes docker pull your-registry/your-app:latest docker run -d -p 3000:3000 your-registry/your-app:latest # 4. Testar compatibilidade Compose systemctl --user start podman.socket export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock docker compose up -d

Fase 2: Pipeline CI/CD (Semana 3-4)

# Job paralelo ao build Docker existente pra validar sem quebrar nada build-podman: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build with Podman run: | podman build -t myapp:${{ github.sha }} . podman push ghcr.io/${{ github.repository }}/myapp:${{ github.sha }}

Fase 3: Produção (Semana 5+)

# Gerar serviços systemd dos containers podman generate systemd --new --files --name webapp # Instalar e ativar cp container-webapp.service ~/.config/systemd/user/ systemctl --user enable --now container-webapp.service # Ou use Quadlet (veja a seção acima)

Pegadinhas da migração

  1. Permissões de volume: modo rootless mapeia UIDs diferente. Pode precisar de podman unshare chown pra volumes montados
  2. Bind de porta: rootless não consegue bindar portas abaixo de 1024 sem sysctl net.ipv4.ip_unprivileged_port_start=0
  3. Modos de rede: --network=host funciona diferente em rootless
  4. Mount do socket: ferramentas que montam /var/run/docker.sock precisam apontar pro socket do Podman

Framework de decisão: Docker vs Podman em 2026

Sem enrolação, concreto:

Fica com Docker se:

  • Teu time tem menos de 250 pessoas (faturamento <$10M) e Docker Desktop é grátis. O ecossistema pesa
  • Depende de Docker Swarm. Podman não tem alternativa
  • Teus pipelines usam features Docker-específicas (cache mounts avançados do BuildKit, Compose completo em testes, DinD) e trocar tem custo alto
  • Usa Extensions do Docker Desktop no dia a dia (scan de vulnerabilidades, explorador de logs, ferramentas de DB)
  • Time trabalha em macOS/Windows e precisa da experiência polida do Docker Desktop

Muda pro Podman se:

  • Compliance de segurança é prioridade. Rootless por padrão, sem daemon privilegiado, capabilities mínimas — postura significativamente mais forte
  • Tá pagando Docker Desktop com time grande. 24/seat/me^s×100pessoas=24/seat/mês × 100 pessoas = 28.800/ano. Podman Desktop é grátis
  • Mira em Kubernetes e quer desenvolvimento local refletindo produção. O conceito de pod e podman play kube são ferramentas genuinamente úteis
  • Roda em servidores Linux e quer gerenciamento nativo com systemd (Quadlet)
  • Precisa de builds rootless no CI. Buildar sem privileged é melhoria real de segurança
  • Eficiência de recursos importa (runners compartilhados, laptops de dev). Zero overhead de daemon idle soma

Abordagem híbrida (o mais comum)

A realidade: a maioria dos times não migra da noite pro dia.

  1. Podman nos servidores Linux — rootless, systemd, sem licensing
  2. Docker Desktop nas máquinas de dev — UX polida, extensions, onboarding fácil
  3. Podman no CI/CD — sem containers privilegiados, pré-instalado nos runners GitHub

O padrão OCI garante imagens 100% intercambiáveis, então esse mix funciona sem atrito.

Olhando pra frente: 2026 e além

O ecossistema de containers converge em padrões e diverge em implementação.

Padronização OCI tá pronta. Imagens, runtimes e specs de distribuição são maduros. Docker e Podman buildam e rodam as mesmas imagens. A era "funciona no Docker, quebra no Podman" ficou pra trás.

Containers WebAssembly (Wasm) tão aparecendo como tecnologia complementar. Docker (via runwasi) e Podman (via crun-wasm) conseguem rodar workloads Wasm junto com containers Linux tradicionais. Iniciam em milissegundos, usam fração da memória e oferecem sandboxing mais forte. Não vão substituir containers Linux, mas vão pegar uma fatia crescente de workloads leves.

Rootless como padrão tá virando norma na indústria. Docker vem melhorando o modo rootless a cada release. A filosofia do Podman — rootless e sem daemon por padrão — tá ganhando o argumento arquitetural, independente de qual ferramenta você usa.

Dev Containers e ambientes de desenvolvimento baseados em containers continuam amadurecendo. Docker (via spec Dev Containers) e Podman (via Podman Desktop) suportam esse padrão. Se o futuro do desenvolvimento é containers do começo ao fim, a escolha do runtime fica ainda mais importante.

Conclusão

A resposta honesta: depende do que você tá otimizando, mas tá menos ambíguo do que dois anos atrás.

Se segurança, custo e alinhamento com Kubernetes são prioridade, Podman é a escolha mais forte em 2026. Rootless por padrão, zero overhead de daemon, suporte nativo a pods — são vantagens técnicas genuínas que Docker vem correndo atrás.

Se maturidade do ecossistema, experiência desktop em macOS/Windows e inércia do tooling pesam mais, Docker segue como padrão pragmático. O ecossistema é maior, o desktop mais polido, e tem mais tutoriais, respostas no Stack Overflow e templates CI que assumem Docker.

A boa notícia: como as duas seguem OCI, não tem lock-in. Dá pra começar com Docker, usar Podman no CI, botar Podman em produção e manter Docker Desktop pro dev local. Imagens, registries e Dockerfiles (sim, Podman builda Dockerfiles) são os mesmos.

O mundo dos containers se dividiu não por incompatibilidade, mas por filosofia: daemon centralizado vs daemonless, root por padrão vs rootless por padrão, produto comercial vs projeto comunitário. Em 2026, as duas filosofias entregam resultados de nível produção. Sua escolha deveria refletir suas restrições e prioridades, não qual ferramenta tem mais torcida no Twitter.

Escolhe um, bota containers pra rodar, e foca no que realmente é difícil: o código dentro deles.

DockerPodmancontainersDevOpsKubernetesCI/CDsecurityLinux

Explore ferramentas relacionadas

Experimente estas ferramentas gratuitas do Pockit