Se você trabalha com infraestrutura, sabe que a promessa do Podman de ser um substituto "drop-in" para o Docker é tentadora. Recentemente, em um dos meus servidores de desenvolvimento onde utilizo o aaPanel, passei por uma situação curiosa: ao instalar o Docker via painel, o sistema removeu o binário do Podman, mas deixou para trás uma "herança" de processos e arquivos que transformaram meu ambiente em um cenário de ghosting técnico.
Neste artigo, compartilho os erros que enfrentei e o passo a passo definitivo para limpar resíduos do Podman e deixar o Docker assumir o controle total.
O aaPanel é otimizado para o Docker Engine. Ao forçar a instalação do Docker, o Podman é desinstalado, mas seus containers rootless e camadas de storage (OverlayFS) podem continuar ativos no kernel.
1. O risco da limpeza sem backup#
Um dos maiores erros ao realizar uma migração de runtime ou executar limpezas de sistema é assumir que todos os containers e volumes no Podman são descartáveis. Antes de rodar comandos destrutivos de remoção de diretórios, você deve realizar o inventário e backup dos dados persistentes:
# 1. Listar todos os containers do Podman ativos e inativos
podman ps -a
# 2. Listar todos os volumes criados no Podman
podman volume ls
# 3. Exportar imagens customizadas importantes que não estão no registry público
podman save -o /root/podman-images-backup.tar $(podman images -q)
# 4. Fazer backup compactado completo do diretório de armazenamento local do usuário (Rootless)
tar czf /root/podman-user-storage-backup-$(date +%Y%m%d).tar.gz ~/.local/share/containers/ 2>/dev/null || true
# 5. Fazer backup compactado do diretório de armazenamento global do sistema (Root)
sudo tar czf /root/podman-system-storage-backup-$(date +%Y%m%d).tar.gz /var/lib/containers/ 2>/dev/null || true
2. Auditoria e parada de recursos ativos#
Se você executar o reset ou a limpeza física com containers ainda em execução, o kernel pode bloquear a remoção de caminhos do OverlayFS.
2.1 parada controlada de containers#
Antes de remover o armazenamento, pare ordenadamente os serviços ativos para que desmontagens de rede e de volumes ocorram de forma limpa:
# 1. Listar containers que ainda estão em execução
podman ps
# 2. Parar todos os containers ativos graciosamente
podman stop -a
# Ou forçando a parada de IDs caso o daemon não responda
# podman stop $(podman ps -aq)
2.2 verificação de volumes e dados relevantes#
Inspecione os pontos de montagem física dos volumes para garantir que dados de bancos de dados ou uploads persistentes não sejam deletados:
# Loop para listar cada volume do Podman, seu mountpoint e as primeiras linhas do conteúdo
for vol in $(podman volume ls -q); do
echo "=== Volume: $vol ==="
podman volume inspect $vol | grep Mountpoint
# Listar o conteúdo físico associado ao volume
sudo ls -la $(podman volume inspect $vol -f '{{.Mountpoint}}') 2>/dev/null | head -5
done
3. Resolvendo "device or resource busy" (overlayfs)#
O sintoma clássico do descompasso de migração ocorre quando você tenta excluir pastas antigas do Podman e o sistema retorna o erro:
rm: cannot remove '/var/lib/containers/storage/overlay/.../merged': Device or resource busy
3.1 por que o erro acontece?#
O Podman utiliza o driver de armazenamento OverlayFS para empilhar camadas de imagens e contêineres. Se o binário do Podman é removido abruptamente (como ocorre em scripts do aaPanel) enquanto caminhos de montagem ainda estão referenciados no kernel, esses pontos permanecem bloqueados. O utilitário rm -rf falha porque o diretório atua como um ponto de montagem ativo para o Linux.
3.2 o comando de desmontagem com lazy unmount#
A solução não é forçar a exclusão física com flags destrutivas, mas sim desvincular o sistema de arquivos no kernel usando o "lazy unmount":
cat /proc/mounts | grep /var/lib/containers | awk '{print $2}' | xargs -r sudo umount -l
Parâmetro -l (lazy unmount)#
A flag -l instrui o kernel a desvincular o sistema de arquivos da árvore de diretórios imediatamente, liberando todas as referências ao caminho assim que os processos que o utilizavam deixarem de estar ativos.
4. O mistério da porta HTTPS ocupada: rootlessport#
Mesmo após limpar o disco, é comum descobrir que a porta HTTPS (como 9443 ou 8443) continua respondendo na rede, mas o comando docker ps não mostra nenhum container escutando nela.
Ao investigar com a ferramenta de diagnóstico de rede:
sudo lsof -i :9443
O culpado costuma ser o processo rootlessport. Este binário é o componente auxiliar do Podman responsável por encaminhar tráfego de portas privilegiadas para a infraestrutura de rede rootless (sem privilégios de administrador). Ele sobrevive à remoção física do pacote principal.
4.1 encerrando processos de forma segura (escalação de sinais)#
Não utilize diretamente o comando kill -9 (SIGKILL). Matar processos abruptamente pode deixar sockets de rede em estado órfão e corromper recursos compartilhados. Adote um fluxo seguro de encerramento:
# 1. Investigar a árvore genealógica do processo (Process Tree) e consumo
ps -p <PID_DO_ROOTLESSPORT> -o pid,ppid,comm,%cpu,%mem
pstree -p <PID_DO_ROOTLESSPORT>
# 2. Enviar sinal SIGTERM (solicitação amigável de encerramento)
sudo kill -15 <PID_DO_ROOTLESSPORT>
# 3. Aguardar 3 segundos para finalização das conexões pendentes
sleep 3
# 4. Validar se o processo foi finalizado. Se ainda ativo, forçar com SIGKILL
sudo kill -0 <PID_DO_ROOTLESSPORT> 2>/dev/null && sudo kill -9 <PID_DO_ROOTLESSPORT>
5. Auditorias de segurança, SELinux e configurações residuais#
Para garantir a estabilidade do novo ambiente sobre o Docker Engine, você deve auditar as camadas de controle de acesso obrigatório (MAC), configurações locais e redes virtuais órfãs.
5.1 verificação do status do SELinux#
Em sistemas como RedHat, Rocky Linux ou AlmaLinux, o SELinux pode bloquear operações de escrita em diretórios remanescentes do contêiner ou gerar conflitos de permissões no socket do Docker:
# 1. Verificar o modo ativo do SELinux
getenforce
# 2. Consultar logs de negações (denials) recentes relacionados a contêineres ou podman
sudo ausearch -m avc -ts recent | grep -iE "container|podman" 2>/dev/null || echo "Nenhuma negação recente."
# 3. Se necessário, restaurar os contextos de segurança corretos dos arquivos do sistema
sudo restorecon -Rv /var/lib/containers 2>/dev/null || true
5.2 remoção de arquivos de configuração ocultos#
O Podman armazena definições de repositórios e storage em caminhos globais e locais do usuário. Remova-os para evitar conflitos de escopo:
# 1. Listar configurações locais do usuário
ls -la ~/.config/containers/ 2>/dev/null
# 2. Listar configurações globais de sistema
ls -la /etc/containers/ 2>/dev/null
# 3. Remover permanentemente estes arquivos residuais
rm -rf ~/.config/containers/
sudo rm -rf /etc/containers/
5.3 auditoria de rede e firewall (regras CNI e iptables)#
O Podman utiliza a arquitetura CNI (Container Network Interface) ou Netavark para roteamento. Seus filtros de IP podem continuar ativos no Netfilter do kernel:
# 1. Listar regras vigentes de IPTables associadas a contêineres ou podman
sudo iptables -L -n | grep -iE "containers|podman|cni"
# 2. Remover as configurações de redes virtuais CNI do diretório de sistema
sudo rm -rf /etc/cni/net.d/
# 3. Listar interfaces de rede remanescentes no kernel
ip link show | grep -iE "podman|cni|veth"
# Se houver interfaces órfãs ativas (ex: cni-podman0), remova-as:
# sudo ip link delete cni-podman0
6. Validação e saúde do ambiente Docker#
Com a máquina limpa de vestígios do Podman, valide o funcionamento correto do Docker Engine:
# 1. Verificar o status do serviço Docker no systemd
systemctl status docker
# 2. Testar acesso ao socket administrativo e obter informações do daemon
docker info | head -20
# 3. Validar se a rede de bridge padrão do Docker está saudável
docker network inspect bridge | head -20
# 4. Executar um container de testes descartável para validar download e execução de imagem
docker run --rm hello-world
# 5. Confirmar que não há mapeamentos ou portas conflitantes pendentes
docker ps -a
docker network ls
7. Verificação pós-limpeza (sanity checks)#
Execute estes comandos finais para garantir o estado ideal do sistema operacional:
# 1. Confirmar se não há mais pontos de montagem associados ao Podman
# Deve retornar 0
cat /proc/mounts | grep -c containers
# 2. Confirmar se não há processos zumbis do Podman em execução
# Deve retornar 1 (apenas a linha de grep ativa)
ps aux | grep -c podman
# 3. Verificar o espaço em disco liberado após o purge do storage
df -h
Checklist: migração Podman → Docker#
Siga este roteiro operacional para migrar ambientes de forma segura e limpa:
1. Fase de pré-migração#
- [ ] Inventário: Listou todos os contêineres e volumes ativos no Podman.
- [ ] Backup de Imagens: Exportou imagens customizadas com
podman save. - [ ] Backup de Dados: Salvou volumes importantes e fez cópia das pastas
/var/lib/containers. - [ ] Parada Controlada: Encerrou todos os contêineres em execução com
podman stop -a.
2. Fase de limpeza do Podman#
- [ ] System Reset: Executou a limpeza nativa
podman system reset --force. - [ ] Desmontar OverlayFS: Removeu os pontos de montagem órfãos com
umount -l. - [ ] Eliminar Processos: Encerrou processos
rootlessportusando a sequência amigável de sinais (SIGTERM -> SIGKILL). - [ ] Limpar Diretórios: Removeu
/var/lib/containers,~/.local/share/containerse/etc/cni/net.d. - [ ] Limpar Configurações: Deletou os diretórios residuais
/etc/containers/e~/.config/containers/.
3. Fase de rede e firewall#
- [ ] Redes Virtuais: Removeu interfaces de rede órfãs associadas à CNI.
- [ ] Regras de IPTables: Limpou regras residuais no firewall do kernel.
- [ ] Auditoria de Portas: Confirmou que as portas de rede críticas estão livres de processos órfãos (
lsof).
4. Fase de instalação e homologação Docker#
- [ ] Instalação: Instalou o Docker Engine estável.
- [ ] Permissões do Usuário: Adicionou o usuário local ao grupo
docker. - [ ] SELinux: Validou se o SELinux está em conformidade com as pastas de execução do Docker.
- [ ] Teste Prático: Executou com sucesso o container de testes
hello-world. - [ ] Sanity Checks: Validou mounts, espaço em disco e processos remanescentes.
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários