ARQUITECTURA SIN DEMONIO DE PODMAN Sistema Operativo Linux (Kernel: namespaces + cgroups) Sin Demonio — fork/exec directo vía conmon Contenedor 1 Sin root UID mapeado Contenedor 2 Sin root UID mapeado Pod (namespace de red compartido) Contenedor 3 App :8080 Contenedor 4 BD :5432 Cada contenedor es un proceso hijo — no se requiere demonio central

Podman (Pod Manager) es un motor de contenedores de código abierto y sin demonio, desarrollado por Red Hat, que proporciona una CLI compatible con Docker para construir, ejecutar y gestionar contenedores y pods OCI. A diferencia de Docker, Podman no requiere un demonio en segundo plano con privilegios de root, lo que lo hace inherentemente más seguro tanto para estaciones de trabajo de desarrollo como para servidores de producción. Si has estado usando Docker y buscas una alternativa más segura, compatible con systemd y que ejecute contenedores como tu usuario regular, Podman es la herramienta a adoptar.

Esta guía cubre todo lo necesario para comenzar con Podman en Ubuntu: instalación, ejecución de contenedores sin root, gestión de imágenes, creación de pods, compatibilidad con Compose, integración con systemd, redes y una ruta de migración completa desde Docker.

Requisitos Previos

Antes de comenzar, asegúrate de tener:

  • Un sistema ejecutando Ubuntu 22.04 o 24.04 (edición escritorio o servidor)
  • Acceso a la terminal con privilegios sudo
  • Una conexión a internet estable
  • Familiaridad básica con contenedores y la línea de comandos de Linux
  • Al menos 2 GB de espacio libre en disco para imágenes

Nota: Podman funciona en cualquier distribución Linux moderna, pero esta guía se enfoca en Ubuntu. Si estás migrando desde Docker, no se requiere ninguna instalación de Docker — Podman lo reemplaza por completo.

¿Qué Es Podman?

Podman es una herramienta de gestión de contenedores que implementa la misma interfaz CLI que Docker pero con una arquitectura fundamentalmente diferente. El nombre viene de Pod Manager, reflejando su soporte nativo para pods estilo Kubernetes — grupos de contenedores que comparten namespaces de red e IPC.

Características clave de Podman:

  • Sin demonio: No hay servicio en segundo plano ejecutándose como root. Cada comando podman lanza contenedores directamente como procesos hijos vía conmon (el monitor de contenedores).
  • Sin root por defecto: Los contenedores se ejecutan bajo tu cuenta de usuario regular usando user namespaces de Linux, sin necesidad de privilegios root.
  • Compatible con OCI: Podman construye y ejecuta imágenes que cumplen con la especificación Open Container Initiative (OCI), garantizando total compatibilidad con imágenes y registros Docker.
  • Pods nativos: Podman puede agrupar contenedores en pods, reflejando la semántica de pods de Kubernetes para desarrollo y pruebas locales.
  • Integración con systemd: Podman genera archivos de unidad systemd a partir de contenedores en ejecución, facilitando la gestión del ciclo de vida de contenedores como servicios del sistema.

Podman vs Docker

Comprender las diferencias arquitectónicas entre Podman y Docker te ayuda a tomar una decisión informada y planificar tu migración.

CaracterísticaPodmanDocker
ArquitecturaSin demonio (fork/exec)Cliente-servidor (demonio dockerd)
Requisito de rootSin root por defectoRequiere demonio root (modo sin root opcional)
Runtime de contenedorescrun / runc vía conmoncontainerd + runc
Compatibilidad CLIReemplazo directo (podman = docker)CLI nativa
Soporte de podsNativo (estilo Kubernetes)No disponible
Soporte Composepodman-compose / podman composedocker compose (plugin integrado)
Integración systemdNativa (podman generate systemd)Requiere archivos de unidad manuales
Formato de imagenOCI / DockerOCI / Docker
Herramienta de construcciónBuildah (integrado)BuildKit
Modelo de seguridadSin demonio root, user namespacesDemonio root, sin root opcional
SocketOpcional (podman.socket)Requerido (docker.socket)

La diferencia más significativa es el demonio. Docker requiere que el demonio dockerd se ejecute en todo momento como root, creando un único punto de fallo y un vector potencial de escalación de privilegios. Podman elimina esto por completo — cuando ejecutas podman run, directamente crea un nuevo proceso para el contenedor usando conmon como monitor de contenedores. Si Podman mismo se cae, los contenedores en ejecución continúan operando.

Instalar Podman en Ubuntu

Podman está disponible en los repositorios oficiales de Ubuntu a partir de Ubuntu 22.04. Instálalo junto con sus herramientas de soporte:

sudo apt update
sudo apt install -y podman

Verifica la instalación:

podman --version

Salida esperada:

podman version 4.9.3

Verifica la información del sistema para confirmar que el modo sin root está disponible:

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

Esto debería devolver true cuando se ejecuta como usuario no root.

Para la última versión de Podman (si la versión del repositorio de Ubuntu es demasiado antigua), puedes agregar el repositorio oficial de 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 Contenedores

Por defecto, Podman requiere nombres de imagen completamente calificados (ej., docker.io/library/nginx). Para habilitar nombres cortos como nginx, configura los registros de búsqueda no calificados:

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

Alternativamente, edita /etc/containers/registries.conf y agrega los registros de búsqueda bajo la sección [registries.search].

Ejecutar Tu Primer Contenedor

Con Podman instalado, ejecuta un contenedor de prueba como tu usuario regular (no root):

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

Deberías ver el familiar mensaje “Hello from Docker!”, confirmando que Podman puede descargar y ejecutar imágenes OCI. Nota que no se requiere sudo.

Ejecuta un contenedor interactivo:

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

Dentro del contenedor, verifica el usuario:

whoami
# root (dentro del user namespace del contenedor)
id
# uid=0(root) gid=0(root) groups=0(root)

Aunque apareces como root dentro del contenedor, en realidad estás ejecutándote como tu usuario regular en el host. Este es el poder de los contenedores sin root con mapeo de user namespace.

Sal del contenedor con exit o Ctrl+D.

Contenedores sin Root

Los contenedores sin root son la característica definitoria de Podman. Entender cómo funcionan te ayuda a solucionar problemas de permisos y diseñar despliegues de contenedores seguros.

Cómo Funcionan los Contenedores sin Root

Cuando ejecutas un contenedor como usuario no root, Podman usa user namespaces de Linux para crear un entorno aislado donde:

  1. El proceso del contenedor se ve a sí mismo como root (UID 0) dentro del contenedor.
  2. En el host, el proceso se ejecuta como un UID subordinado mapeado desde el rango permitido de tu usuario.
  3. El mapeo se define en /etc/subuid y /etc/subgid.

Verifica los mapeos de UID/GID subordinados de tu usuario:

cat /etc/subuid
# jc:100000:65536

cat /etc/subgid
# jc:100000:65536

Esto significa que el usuario jc puede mapear UIDs 100000 a 165535 dentro de los contenedores. El UID 0 del contenedor se mapea al UID de tu usuario en el host, y los UIDs 1-65535 dentro del contenedor se mapean a los UIDs 100000-165535 del host.

Verificar la Operación sin Root

Ejecuta un contenedor y verifica el proceso desde el host:

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

Desde otra terminal en el host:

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

El proceso nginx se ejecuta como tu usuario (jc), no como root. Si el contenedor fuera comprometido, el atacante solo tendría los privilegios de tu usuario — no acceso root al host.

Configurar User Namespaces

Si /etc/subuid o /etc/subgid no contienen entradas para tu usuario, agrégalas:

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

Después de modificar estos archivos, reinicia el almacenamiento de Podman para aplicar los cambios:

podman system migrate

Trabajar con Imágenes

Podman usa el mismo formato de imagen que Docker y puede descargar desde cualquier registro compatible con OCI.

Descargar Imágenes

# Descargar desde Docker Hub
podman pull docker.io/library/nginx:alpine

# Descargar desde Quay.io
podman pull quay.io/podman/hello

# Descargar desde GitHub Container Registry
podman pull ghcr.io/actions/actions-runner:latest

Listar Imágenes

podman images

Salida:

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 Imágenes

Podman usa Containerfile (o Dockerfile — ambos son soportados) y 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"]

Construye la imagen:

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

Construir con un nombre de archivo específico:

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

Subir Imágenes a un Registro

Etiqueta y sube una imagen a un 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

Eliminar Imágenes

# Eliminar una imagen específica
podman rmi docker.io/library/nginx:alpine

# Eliminar todas las imágenes sin usar
podman image prune -a

Gestión de Pods

Los pods son un concepto tomado de Kubernetes. Un pod agrupa uno o más contenedores que comparten el mismo namespace de red, lo que significa que pueden comunicarse a través de localhost y compartir mapeos de puertos.

Crear un Pod

Crea un pod con mapeos de puertos definidos a nivel de pod:

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

Agregar Contenedores a un Pod

Agrega un contenedor nginx y un contenedor PostgreSQL al 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 contenedores ahora comparten el mismo namespace de red. El contenedor nginx puede conectarse a PostgreSQL en localhost:5432, y los clientes externos acceden a nginx vía host:8080.

Gestionar Pods

# Listar todos los pods
podman pod ls

# Ver detalles del pod
podman pod inspect my-web-pod

# Detener todos los contenedores en un pod
podman pod stop my-web-pod

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

# Eliminar un pod y sus contenedores
podman pod rm -f my-web-pod

Generar YAML de Kubernetes desde Pods

Una de las características únicas de Podman es generar manifiestos de Kubernetes a partir de pods en ejecución:

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

Esto crea un archivo YAML compatible con Kubernetes que puedes desplegar directamente en un clúster de Kubernetes con kubectl apply -f my-web-pod.yaml. Esto hace de Podman una excelente herramienta para desarrollo local cuando tu objetivo de producción es Kubernetes.

Podman Compose

Podman soporta archivos Docker Compose para stacks de aplicaciones multi-contenedor. Hay dos enfoques:

Usar podman-compose

Instala podman-compose (una reimplementación comunitaria en Python):

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

Úsalo igual que docker-compose:

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

Usar el Comando Integrado podman compose

Podman 4.7+ incluye un comando integrado podman compose que delega a un proveedor de compose externo (docker-compose o podman-compose):

podman compose up -d
podman compose down

Ejemplo de docker-compose.yml

Un archivo docker-compose.yml estándar funciona sin modificación:

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:

Ejecutar con Podman Compose:

podman-compose up -d

Generar Unidades systemd desde Contenedores

Podman se integra con systemd para gestionar contenedores como servicios del sistema. Esto es especialmente útil para servidores donde necesitas que los contenedores inicien en el arranque y se reinicien ante fallos.

Generar un Archivo de Unidad desde un Contenedor en Ejecución

Primero, inicia un contenedor:

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

Genera la unidad systemd:

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

La bandera --new asegura que el archivo de unidad cree un contenedor nuevo cada vez (en lugar de reiniciar uno existente), lo cual es la práctica recomendada.

Habilitar e Iniciar el Servicio

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

Habilitar Lingering para Sesiones sin Inicio de Sesión

Por defecto, los servicios systemd de usuario se detienen cuando el usuario cierra sesión. Habilita lingering para mantenerlos ejecutándose:

sudo loginctl enable-linger $USER

Verificar el Servicio

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

Quadlet (Podman 4.4+)

Para Podman 4.4 y posterior, Quadlet proporciona un formato declarativo más simple. Crea un archivo .container en ~/.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

Recarga systemd e inicia el servicio:

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

Migrar de Docker a Podman

Si actualmente usas Docker, la ruta de migración a Podman es directa.

Instalar el Paquete de Compatibilidad Docker

sudo apt install -y podman-docker

Esto instala un comando docker que es alias de podman y crea un socket de emulación /var/run/docker.sock. Los scripts existentes que llaman a docker usarán Podman en su lugar.

Migrar Imágenes Docker

Exporta imágenes desde Docker e impórtalas en Podman:

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

# En el sistema Podman
podman load -i my-app.tar

Convertir Archivos Docker Compose

La mayoría de los archivos docker-compose.yml funcionan sin modificación. Los principales ajustes a tener en cuenta:

  1. Calificar completamente los nombres de imagen: Reemplaza nginx:alpine con docker.io/library/nginx:alpine
  2. Modo de red: Algunos modos de red específicos de Docker pueden diferir
  3. Plugins de volumen: Los plugins de volumen de Docker no son soportados; usa los drivers de volumen nativos de Podman

Actualizar Pipelines CI/CD

Reemplaza comandos docker con podman en tus scripts de pipeline, o instala podman-docker para que el alias docker lo maneje:

# Ejemplo 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

El modelo de red de Podman difiere entre los modos con root y sin root.

Redes sin Root

En modo sin root, Podman usa slirp4netns o pasta (Podman 5.0+) para proporcionar conectividad de red sin privilegios de root:

  • slirp4netns: Crea un dispositivo TAP en un user namespace, proporcionando redes basadas en NAT. El reenvío de puertos por encima de 1024 funciona sin root.
  • pasta: Una alternativa más nueva y rápida que proporciona rendimiento mejorado y menor sobrecarga.

Mapear puertos en modo sin root:

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

Nota: Vincular a puertos por debajo de 1024 (ej., 80, 443) requiere privilegios de root o ajustar el inicio de puertos no privilegiados del sistema con sudo sysctl net.ipv4.ip_unprivileged_port_start=80.

CNI y Netavark

Podman soporta dos backends de red:

  • CNI (Container Network Interface): El backend legacy usando plugins CNI.
  • Netavark: La pila de red moderna basada en Rust (por defecto en Podman 4.0+).

Crear una red personalizada:

podman network create my-network

Ejecutar contenedores en la red 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

Los contenedores en la misma red pueden alcanzarse entre sí por nombre:

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

Inspeccionar Redes

# Listar redes
podman network ls

# Inspeccionar una red
podman network inspect my-network

# Eliminar una red
podman network rm my-network

Referencia de Comandos de Podman

La siguiente tabla lista los comandos de Podman más utilizados y sus equivalentes en Docker:

Comando PodmanEquivalente DockerDescripción
podman rundocker runCrear e iniciar un contenedor
podman psdocker psListar contenedores en ejecución
podman ps -adocker ps -aListar todos los contenedores
podman imagesdocker imagesListar imágenes locales
podman pulldocker pullDescargar una imagen de un registro
podman builddocker buildConstruir una imagen desde un Containerfile/Dockerfile
podman pushdocker pushSubir una imagen a un registro
podman execdocker execEjecutar un comando en un contenedor en ejecución
podman logsdocker logsVer logs del contenedor
podman stopdocker stopDetener un contenedor en ejecución
podman rmdocker rmEliminar un contenedor
podman rmidocker rmiEliminar una imagen
podman volume createdocker volume createCrear un volumen con nombre
podman network createdocker network createCrear una red
podman pod createN/ACrear un pod
podman pod lsN/AListar pods
podman generate systemdN/AGenerar archivos de unidad systemd
podman generate kubeN/AGenerar YAML de Kubernetes
podman system prunedocker system pruneEliminar datos sin usar
podman logindocker loginIniciar sesión en un registro de contenedores
podman inspectdocker inspectVer información detallada de contenedor/imagen

Solución de Problemas

Error: short-name resolution enforced

Problema: Podman se niega a descargar una imagen usando un nombre corto como nginx.

Solución: Usa el nombre de imagen completamente calificado o configura los registros de búsqueda:

# Usar nombre completamente calificado
podman pull docker.io/library/nginx:alpine

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

Error: cannot find UID/GID mapping

Problema: Los contenedores sin root fallan porque los mapeos de UID/GID subordinados no están configurados.

Solución: Agrega mapeos para tu usuario:

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

Error: permission denied on volume mount

Problema: Un contenedor sin root no puede acceder a un directorio montado por bind.

Solución: Agrega el sufijo de etiqueta SELinux :Z o :z, o asegúrate de que el directorio sea propiedad de tu usuario:

# Corregir propiedad
podman unshare chown -R 0:0 /path/to/volume

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

El Contenedor No Puede Vincular al Puerto 80

Problema: Podman sin root no puede vincular a puertos por debajo de 1024.

Solución: Reduce el valor de inicio de puertos no privilegiados:

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

Podman Compose Falla con Error de Red

Problema: podman-compose produce errores al crear redes.

Solución: Asegúrate de que el backend de red de Podman esté funcionando y reinicia si es necesario:

podman network ls
podman system reset --force
# Recrea tus contenedores después del reset

Los Contenedores No Inician Después del Reinicio

Problema: Los contenedores systemd a nivel de usuario no inician después de un reinicio.

Solución: Habilita lingering para tu usuario:

sudo loginctl enable-linger $USER

Descarga Lenta de Imágenes

Problema: La descarga de imágenes es lenta en modo sin root.

Solución: Habilita fuse-overlayfs para mejor rendimiento de almacenamiento:

sudo apt install -y fuse-overlayfs

Verifica que se esté usando:

podman info --format '{{.Store.GraphDriverName}}'
# Debería mostrar: overlay

Resumen

Podman es un motor de contenedores maduro, seguro y compatible con Docker que elimina la necesidad de un proceso demonio privilegiado. Su enfoque de sin root por defecto, soporte nativo de pods e integración con systemd lo convierten en una excelente opción tanto para entornos Linux de desarrollo como de producción. Para cualquier persona que ejecute contenedores en servidores Linux, Podman proporciona una clara ventaja de seguridad sin sacrificar compatibilidad con el ecosistema Docker.

En esta guía aprendiste cómo instalar Podman en Ubuntu, ejecutar contenedores sin root, gestionar imágenes y pods, usar Podman Compose con archivos docker-compose.yml existentes, generar unidades systemd para la gestión automática del ciclo de vida de contenedores, configurar redes y migrar desde Docker.

Para temas relacionados con contenedores, consulta nuestras guías sobre Cómo Instalar Docker en Ubuntu y Docker Compose: Guía Práctica para Administradores de Sistemas.