Podman vs. Docker: Desplegando Contenedores de Forma Segura y Sin Root

Published:

En el ecosistema DevOps actual, la contenedorización es un pilar fundamental. Sin embargo, la conveniencia no debe comprometer la seguridad. Una práctica común, como añadir una cuenta de desarrollador al grupo docker, puede abrir una puerta inesperada: acceso a nivel de root al host subyacente. Esto se debe a que el demonio de Docker (dockerd) se ejecuta con privilegios de root y procesa las solicitudes a través de su socket. Un comando simple como docker run -v /:/host permite a un usuario modificar o acceder a archivos del sistema operativo, convirtiendo lo que parece un ajuste inofensivo en una vulnerabilidad crítica.

Docker Engine vs. Podman: Una Disparidad Arquitectónica en Seguridad

Ambos Docker Engine y Podman ejecutan las mismas imágenes de contenedor compatibles con OCI. La diferencia crucial radica en la arquitectura subyacente y cómo gestionan los privilegios.

Arquitectura de Docker Engine

Con Docker Engine, el comando docker actúa como un cliente que envía solicitudes API a través de /var/run/docker.sock al demonio dockerd, que posee y se ejecuta como root. Este demonio, a su vez, utiliza containerd y un tiempo de ejecución OCI (como runc) para crear y gestionar contenedores. Toda la ruta de control está inherentemente ligada a privilegios de root, lo que convierte el acceso al socket en una puerta de entrada al control completo del host.

Arquitectura Sin Demonio de Podman

Podman adopta un enfoque radicalmente diferente: elimina por completo el demonio central. En su lugar, el comando podman crea y arranca el contenedor directamente. Utiliza conmon (monitor de contenedor) para supervisar el proceso del contenedor y un tiempo de ejecución OCI (normalmente crun) para su creación. Esto significa que cada contenedor tiene su propio proceso de monitorización y, fundamentalmente, estos procesos se ejecutan bajo la cuenta del usuario que los inició, no a través de un servicio root.

Esta arquitectura sin demonio no solo mejora la seguridad al eliminar un punto único de falla con privilegios elevados, sino que también se integra de forma natural con systemd a través de Quadlet, permitiendo gestionar contenedores y pods como servicios de usuario o de sistema sin necesidad de un demonio de contenedor permanentemente en ejecución.

Instalación y Configuración de Podman Sin Privilegios

Para aprovechar la seguridad de Podman rootless, es fundamental comprender la configuración de los IDs de usuario subordinados en Linux, que son clave para el funcionamiento de los namespaces de usuario.

Configuración de IDs de Usuario Subordinados

Podman rootless utiliza namespaces de usuario de Linux para mapear el usuario root dentro del contenedor a un usuario sin privilegios en el host. Para que esto funcione, el usuario necesita rangos de UID y GID subordinados definidos en /etc/subuid y /etc/subgid.

Para verificar si su cuenta (ej. tecmint) ya tiene los rangos necesarios:

grep tecmint /etc/subuid /etc/subgid

Si no existen entradas, debe añadir un rango de UID y GID subordinados. Por ejemplo, para el usuario tecmint:

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

Después de modificar estos archivos, es crucial migrar el estado existente de Podman para que los nuevos mapeos de IDs entren en vigor:

podman system migrate

Demostraciones Prácticas de Podman Rootless

Propiedad de Procesos: La Diferencia Clave

La forma más clara de entender la ventaja de seguridad de Podman es comparando la propiedad de los procesos de contenedores en el host.

Inicie un contenedor Alpine con Podman como usuario regular (sin sudo):

podman run -d alpine sleep 1h

Ahora, verifique el propietario del proceso desde el host:

ps -ef | grep sleep | grep -v grep

Observará que el proceso pertenece a su usuario regular (ej. tecmint). Dentro del contenedor, el proceso se ve como root, pero gracias a los namespaces de usuario, este «root» no tiene privilegios de root en el host.

Para comparar, inicie la misma carga de trabajo a través del demonio de Docker (que es root-owned):

sudo docker run -d alpine sleep 1h

Verifique el propietario del proceso en el host:

ps -ef | grep sleep | grep -v grep

Aquí, el proceso del contenedor Docker aparece como propiedad de root en el host. Esta diferencia es fundamental: con Podman rootless, un compromiso o escape de contenedor no otorga automáticamente privilegios de root en el host, limitando el impacto inicial al nivel de privilegios del usuario que ejecuta el contenedor.

podman rm -f $(podman ps -aq)
sudo docker rm -f $(sudo docker ps -aq)

Gestión de Aplicaciones Multi-Contenedor con Pods y systemd

Podman no solo gestiona contenedores individuales de forma segura, sino que también ofrece un soporte robusto para aplicaciones multi-contenedor y su integración con systemd.

Los «pods» de Podman permiten agrupar contenedores relacionados que comparten un namespace de red, similar al modelo de Kubernetes:

podman pod create --name mywebapp-pod -p 8080:80
podman run -d --pod mywebapp-pod --name mariadb docker.io/library/mariadb
podman run -d --pod mywebapp-pod --name nginx docker.io/library/nginx

Esto crea un entorno donde MariaDB y Nginx pueden comunicarse entre sí a través de localhost.

Para ejecutar contenedores como servicios gestionados por systemd de forma persistente (incluso después de un reinicio del sistema o del usuario), Podman se integra con Quadlet. Un archivo .container en su directorio de usuario se convierte en una unidad de systemd. Por ejemplo, cree ~/.config/containers/systemd/webapp.container:

[Container]
Image=docker.io/library/nginx
ContainerName=systemd-webapp
PublishPort=8081:80
AutoUpdate=registry
Restart=always

[Unit]
Description=Servicio Nginx gestionado por Podman
WantedBy=default.target

Luego, habilite el lingering para su usuario y cargue/inicie la unidad:

loginctl enable-linger $(whoami)
systemctl --user daemon-reload
systemctl --user enable --now webapp.service

Esto permite que Podman gestione contenedores como servicios nativos de Linux, sin la necesidad de un demonio privilegiado.

¿Cuándo Elegir Podman o Docker Engine?

La elección entre Podman y Docker Engine a menudo depende del entorno y los requisitos específicos. Docker Engine sigue siendo conveniente para equipos que dependen de herramientas como Docker Desktop, Docker Swarm o funciones específicas de BuildKit, ya que estas herramientas están intrínsecamente ligadas al demonio de Docker.

Sin embargo, Podman es la opción superior en servidores compartidos, flotas basadas en RHEL y cualquier entorno donde la seguridad y la auditoría de privilegios sean primordiales. La ausencia de un demonio root, el uso de namespaces de usuario y la integración nativa con systemd lo convierten en una solución más robusta y segura. Para herramientas que esperan un socket de Docker (como los CI runners), Podman puede exponer su propio socket API a través de systemctl --user enable --now podman.socket.

Una limitación a considerar es que los contenedores rootless no pueden enlazar puertos por debajo de 1024 (puertos privilegiados). Para mitigar esto, puede publicar un puerto alto detrás de un proxy inverso o ajustar el límite del kernel con sudo sysctl net.ipv4.ip_unprivileged_port_start=80 y guardarlo en /etc/sysctl.d/.

Conclusión

Podman representa un avance significativo en la seguridad de la contenedorización al ofrecer una alternativa sin demonio, rootless y altamente integrada con el ecosistema Linux. Al eliminar el riesgo inherente del demonio de Docker ejecutándose como root y al implementar un mapeo de usuarios más seguro, Podman reduce drásticamente el impacto de posibles brechas de seguridad. Para entornos que priorizan la resiliencia y la mitigación de riesgos, adoptar Podman es una decisión estratégica que refuerza la postura de ciberseguridad sin sacrificar la eficiencia de la contenedorización.

¿Ha migrado sus cargas de trabajo de producción a Podman rootless o las arquitecturas existentes lo mantienen en Docker? Comparta sus experiencias o configuraciones de Quadlet en los comentarios.

- Advertisement -

Related articles