--- title: "Cómo usar Podman como alternativa a Docker en Ubuntu 24.04" description: "Instala Podman en Ubuntu 24.04, ejecuta contenedores sin root y sin demonio, agrúpalos en pods y arráncalos con systemd usando Quadlet como sustituto de Docker." category: "Docker Avanzado" language: es source: https://cubepath.com/es/docs/docker-avanzado/podman-como-alternativa-a-docker updated: 2026-09-25 --- # Cómo usar Podman como alternativa a Docker en Ubuntu 24.04 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 | Aspecto | Docker | Podman | |---|---|---| | Arquitectura | Demonio `dockerd` ejecutándose como root | Sin demonio: cada contenedor es un proceso hijo de `conmon` | | Contenedores sin root | Modo rootless opcional, con configuración aparte | Funciona sin root de serie | | CLI | `docker` | `podman`, con los mismos subcomandos y opciones más comunes | | Pods | No | Sí, varios contenedores comparten red, como en Kubernetes | | Arranque automático | Política `--restart` del demonio | Unidades de systemd generadas con Quadlet | | Compose | Plugin `docker compose` | `podman-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: ```bash sudo apt update sudo apt install podman ``` Comprueba la versión instalada: ```bash podman version ``` ```output 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: ```bash grep "^$USER:" /etc/subuid /etc/subgid ``` ```output /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: ```bash sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 your_user ``` Confirma que Podman funciona en modo rootless: ```bash podman info --format '{{.Host.Security.Rootless}}' ``` ```output 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: ```bash 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: ```bash podman ps curl -I http://localhost:8080 ``` ```output 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: ```bash podman top web user huser ``` ```output 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: ```bash 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: ```bash 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: ```bash 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`: ```bash podman exec webapp-nginx sh -c 'printf "PING\r\n" | nc -w 1 127.0.0.1 6379' ``` ```output +PONG ``` Lista los pods y sus contenedores: ```bash podman pod ps ``` ```output 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: ```bash 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: ```bash 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: ```bash sudo loginctl enable-linger "$USER" ``` Crea el directorio donde Quadlet busca las definiciones de usuario: ```bash mkdir -p ~/.config/containers/systemd ``` Crea la definición del contenedor: ```bash nano ~/.config/containers/systemd/web.container ``` ```ini [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: ```bash 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: ```bash systemctl --user status web.service ``` ```output ● 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: ```bash 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: ```bash 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: ```bash sudo apt install podman-compose ``` Desde el directorio de un proyecto, los comandos son los mismos que con Docker Compose: ```bash 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.