Podman es un motor de contenedores compatible con las imágenes OCI y con la mayoría de comandos de Docker, pero con dos diferencias de diseño importantes: no tiene un demonio central y puede ejecutar contenedores con un usuario normal, sin privilegios de root. En este tutorial instalarás Podman en Ubuntu 24.04, ejecutarás contenedores rootless, los agruparás en un pod y los convertirás en servicios de systemd con Quadlet para que arranquen solos con el servidor.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo. Inicia sesión con él directamente por SSH (no con su ni sudo -i), porque los contenedores rootless necesitan una sesión de usuario completa de systemd.
  • Si UFW está activo, permiso para abrir el puerto 8080/tcp.

No hace falta desinstalar Docker: ambos pueden convivir, porque Podman guarda imágenes y contenedores en sus propios directorios.

Podman frente a Docker

AspectoDockerPodman
ArquitecturaDemonio dockerd ejecutándose como rootSin demonio: cada contenedor es un proceso hijo de conmon
Contenedores sin rootModo rootless opcional, con configuración aparteFunciona sin root de serie
CLIdockerpodman, con los mismos subcomandos y opciones más comunes
PodsNoSí, varios contenedores comparten red, como en Kubernetes
Arranque automáticoPolítica --restart del demonioUnidades de systemd generadas con Quadlet
ComposePlugin docker composepodman-compose o la API compatible con Docker

La principal consecuencia práctica: con Docker, cualquier usuario del grupo docker es en la práctica root en el servidor. Con Podman rootless, un contenedor comprometido solo tiene los permisos de tu usuario.

Paso 1: Instalar Podman

Podman está en los repositorios oficiales de Ubuntu 24.04. Instálalo:

sudo apt update
sudo apt install podman

Comprueba la versión instalada:

podman version
Client:       Podman Engine
Version:      4.9.3
API Version:  4.9.3
Go Version:   go1.22.2
Built:        Thu Jan  1 00:00:00 1970
OS/Arch:      linux/amd64

Ubuntu 24.04 incluye Podman 4.9, que ya trae Quadlet, pods y el modo rootless completo.

Paso 2: Comprobar la configuración rootless

Podman rootless asigna a cada usuario un rango de UID y GID subordinados, que se mapean dentro del contenedor. En Ubuntu, adduser crea esos rangos automáticamente. Compruébalo:

grep "^$USER:" /etc/subuid /etc/subgid
/etc/subuid:your_user:100000:65536
/etc/subgid:your_user:100000:65536

Si no aparece ninguna línea (por ejemplo, porque el usuario se creó con useradd), asígnale un rango libre:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 your_user

Confirma que Podman funciona en modo rootless:

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

Paso 3: Ejecutar el primer contenedor

La configuración de Ubuntu no define registros de búsqueda por defecto, así que usa siempre nombres de imagen completos, con el registro incluido. Es además más seguro, porque evitas descargar por error una imagen de otro registro con el mismo nombre.

Arranca Nginx publicando el puerto 8080:

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

Los usuarios sin privilegios no pueden abrir puertos por debajo de 1024, por eso se usa el 8080 en el host. Comprueba que el contenedor está en marcha y responde:

podman ps
curl -I http://localhost:8080
CONTAINER ID  IMAGE                           COMMAND               CREATED        STATUS        PORTS                 NAMES
a1b2c3d4e5f6  docker.io/library/nginx:alpine  nginx -g daemon o...  5 seconds ago  Up 5 seconds  0.0.0.0:8080->80/tcp  web

HTTP/1.1 200 OK
Server: nginx/1.27.2

Fíjate en cómo se ve el proceso desde el host. Nginx se ejecuta como root dentro del contenedor, pero en el servidor es un proceso de tu usuario o de un UID subordinado:

podman top web user huser
USER        HUSER
root        1000
nginx       100100

Los comandos habituales funcionan igual que en Docker: podman logs web, podman exec -it web sh, podman stop web, podman images. Elimina el contenedor antes de seguir:

podman rm -f web

Si quieres seguir escribiendo docker, el paquete podman-docker instala un comando docker que llama a Podman. No lo instales si Docker ya está en el servidor, porque ambos usan el mismo nombre de comando.

Paso 4: Agrupar contenedores en un pod

Un pod es un grupo de contenedores que comparten el espacio de red: se comunican entre sí por localhost y los puertos se publican una sola vez, en el pod. Es el mismo concepto que un pod de Kubernetes.

Crea un pod que publique el puerto 8080:

podman pod create --name webapp -p 8080:80

Añade Nginx y un Redis al pod. Los contenedores no llevan -p, porque la red es la del pod:

podman run -d --pod webapp --name webapp-nginx docker.io/library/nginx:alpine
podman run -d --pod webapp --name webapp-redis docker.io/library/redis:7-alpine

Comprueba que Nginx puede llegar a Redis por localhost:

podman exec webapp-nginx sh -c 'printf "PING\r\n" | nc -w 1 127.0.0.1 6379'
+PONG

Lista los pods y sus contenedores:

podman pod ps
POD ID        NAME        STATUS      CREATED         INFRA ID      # OF CONTAINERS
7e8f9a0b1c2d  webapp      Running     30 seconds ago  3d4e5f6a7b8c  3

Son tres contenedores porque cada pod tiene un contenedor infra que mantiene los espacios de nombres compartidos.

Podman puede exportar el pod como un manifiesto de Kubernetes, útil para migrar después a un clúster o recrearlo en otro servidor:

podman kube generate webapp > webapp.yaml

Para recrearlo a partir del archivo usarías podman kube play webapp.yaml. Elimina el pod antes del siguiente paso:

podman pod rm -f webapp

Paso 5: Arrancar contenedores con systemd usando Quadlet

Como no hay demonio, Podman no puede reiniciar contenedores al arrancar el servidor por sí solo. La solución es systemd: con Quadlet describes el contenedor en un archivo .container y systemd genera y gestiona el servicio.

Primero habilita lingering para tu usuario. Sin esto, los servicios de usuario de systemd se detienen al cerrar la sesión SSH y no arrancan hasta que vuelves a entrar:

sudo loginctl enable-linger "$USER"

Crea el directorio donde Quadlet busca las definiciones de usuario:

mkdir -p ~/.config/containers/systemd

Crea la definición del contenedor:

nano ~/.config/containers/systemd/web.container
[Unit]
Description=Nginx con Podman

[Container]
Image=docker.io/library/nginx:alpine
ContainerName=web
PublishPort=8080:80

[Service]
Restart=on-failure

[Install]
WantedBy=default.target

Recarga systemd para que Quadlet genere la unidad web.service y arráncala:

systemctl --user daemon-reload
systemctl --user start web.service

No uses systemctl --user enable con unidades de Quadlet: el arranque automático lo define la sección [Install] del archivo .container. Comprueba el servicio:

systemctl --user status web.service
● web.service - Nginx con Podman
     Loaded: loaded (/home/your_user/.config/containers/systemd/web.container; generated)
     Active: active (running) since Thu 2026-09-25 10:40:12 UTC; 6s ago

Los logs del contenedor van al journal:

journalctl --user -u web.service -n 20

Para probar el arranque automático, reinicia el servidor con sudo reboot, vuelve a conectarte y ejecuta curl -I http://localhost:8080. Si cambias el archivo .container, repite systemctl --user daemon-reload y systemctl --user restart web.service.

Para exponer el servicio desde fuera, abre el puerto en UFW:

sudo ufw allow 8080/tcp

Paso 6: Usar archivos de Docker Compose

Si ya tienes proyectos con compose.yaml, podman-compose los ejecuta con Podman. Está en los repositorios de Ubuntu:

sudo apt install podman-compose

Desde el directorio de un proyecto, los comandos son los mismos que con Docker Compose:

podman-compose up -d
podman-compose ps
podman-compose down

Recuerda escribir las imágenes con su nombre completo (docker.io/library/postgres:16) y no publicar puertos por debajo de 1024. podman-compose cubre los casos habituales, pero no todas las opciones de Compose; para servicios en producción, Quadlet es la opción más sólida.

Solución de problemas

Error: short-name "nginx" did not resolve to an alias. No hay registros de búsqueda configurados. Usa el nombre completo de la imagen, por ejemplo docker.io/library/nginx:alpine.

rootlessport cannot expose privileged port 80. Los usuarios sin privilegios no pueden abrir puertos por debajo de 1024. Publica en un puerto alto y pon delante un proxy inverso, o baja el límite con sudo sysctl net.ipv4.ip_unprivileged_port_start=80 (y hazlo permanente en /etc/sysctl.d/) si aceptas esa implicación de seguridad.

Failed to connect to bus al usar systemctl --user. La sesión no se abrió con login real, típico al cambiar de usuario con su. Conéctate por SSH directamente con ese usuario.

El contenedor se detiene al cerrar SSH. Falta sudo loginctl enable-linger your_user.

potentially insufficient UIDs or GIDs available in user namespace. El usuario no tiene rangos en /etc/subuid y /etc/subgid. Añádelos como en el paso 2 y ejecuta podman system migrate.

Conclusión

Has instalado Podman en Ubuntu 24.04, has ejecutado contenedores sin root y sin demonio, has agrupado servicios en un pod exportable a Kubernetes y has convertido un contenedor en un servicio de systemd con Quadlet. Como siguientes pasos, puedes definir redes y volúmenes con archivos .network y .volume de Quadlet, activar actualizaciones automáticas de imágenes con AutoUpdate=registry y podman-auto-update.timer, o poner Caddy o Nginx delante para servir tus contenedores con HTTPS.