--- title: "Cómo configurar Docker en modo rootless en Ubuntu 24.04" description: "Ejecuta el demonio de Docker con un usuario sin privilegios en Ubuntu 24.04: instalación, perfil de AppArmor, arranque con systemd, límites y puertos bajos." category: "Docker Avanzado" language: es source: https://cubepath.com/es/docs/docker-avanzado/configuracion-del-modo-sin-root-de-docker updated: 2026-09-25 --- # Cómo configurar Docker en modo rootless en Ubuntu 24.04 En una instalación normal, el demonio de Docker se ejecuta como root y cualquier usuario con acceso a su socket puede obtener root en el servidor. En modo rootless, tanto el demonio como los contenedores se ejecutan con un usuario sin privilegios dentro de un espacio de nombres de usuario, de modo que un contenedor comprometido no obtiene más permisos que ese usuario. En este tutorial configurarás Docker rootless en Ubuntu 24.04, lo dejarás arrancando con systemd y resolverás las limitaciones habituales: puertos privilegiados y límites de CPU y memoria. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. - Docker Engine instalado desde el repositorio oficial de Docker (paquete `docker-ce`). El paquete `docker-ce-rootless-extras`, que incluye las herramientas rootless, se instala con él. - Un usuario no root con privilegios `sudo` (en esta guía `your_user`) que será quien ejecute Docker. Inicia sesión con él directamente por SSH: el modo rootless necesita una sesión de systemd de usuario, que no se crea con `su` ni con `sudo -i`. Comprueba que el paquete de extras está instalado: ```bash dpkg -l docker-ce-rootless-extras | grep ^ii ``` ```output ii docker-ce-rootless-extras 5:28.x.x-1~ubuntu.24.04~noble amd64 Rootless support for Docker. ``` ## Paso 1: Instalar dependencias y comprobar los rangos de UID Docker rootless mapea los UID de los contenedores a un rango de UID subordinados de tu usuario. Necesita las herramientas `newuidmap` y `newgidmap`, del paquete `uidmap`: ```bash sudo apt update sudo apt install uidmap ``` Comprueba que tu usuario tiene rangos asignados en `/etc/subuid` y `/etc/subgid`. Ubuntu los crea automáticamente al usar `adduser`: ```bash grep "^$USER:" /etc/subuid /etc/subgid ``` ```output /etc/subuid:your_user:100000:65536 /etc/subgid:your_user:100000:65536 ``` Si no aparece nada, asigna un rango libre de al menos 65.536 identificadores: ```bash sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 your_user ``` ## Paso 2: Desactivar el demonio de Docker del sistema Puedes tener ambos demonios a la vez, pero si el objetivo es que nadie use Docker como root, desactiva el del sistema y elimina su socket: ```bash sudo systemctl disable --now docker.service docker.socket sudo rm -f /var/run/docker.sock ``` Si tu usuario está en el grupo `docker`, sácalo; ya no lo necesita y ese grupo es el que da acceso al demonio con root: ```bash sudo gpasswd -d your_user docker ``` Cierra la sesión SSH y vuelve a entrar para que el cambio de grupo se aplique. ## Paso 3: Permitir espacios de nombres de usuario en AppArmor Ubuntu 24.04 restringe con AppArmor la creación de espacios de nombres de usuario por parte de procesos sin privilegios, y RootlessKit, el componente que prepara el entorno rootless, los necesita. Comprueba si la restricción está activa: ```bash sysctl kernel.apparmor_restrict_unprivileged_userns ``` ```output kernel.apparmor_restrict_unprivileged_userns = 1 ``` Con valor `1`, crea un perfil de AppArmor que permita a `rootlesskit` crear espacios de nombres de usuario. Primero comprueba si ya existe uno: ```bash ls /etc/apparmor.d/ | grep -i rootlesskit ``` Si no hay ninguno, crea el perfil: ```bash sudo nano /etc/apparmor.d/usr.bin.rootlesskit ``` ```text abi , include /usr/bin/rootlesskit flags=(unconfined) { userns, include if exists } ``` Carga el perfil reiniciando AppArmor: ```bash sudo systemctl restart apparmor.service ``` Verifica que el perfil está cargado: ```bash sudo aa-status | grep rootlesskit ``` ```output /usr/bin/rootlesskit ``` Este perfil solo concede el permiso `userns` a ese binario concreto. No desactives la restricción de forma global con el `sysctl`: afecta a todos los programas del sistema. ## Paso 4: Instalar el demonio rootless Ejecuta la herramienta de instalación con tu usuario, sin `sudo`: ```bash dockerd-rootless-setuptool.sh install ``` La herramienta crea el servicio de usuario `~/.config/systemd/user/docker.service`, lo arranca y crea un contexto de Docker llamado `rootless`. Al final muestra algo como esto: ```output [INFO] Creating /home/your_user/.config/systemd/user/docker.service [INFO] starting systemd service docker.service ... [INFO] Installed docker.service successfully. [INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service` [INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger your_user` [INFO] Creating CLI context "rootless" [INFO] Using CLI context "rootless" ``` Si la herramienta falla con un error de requisitos, lee su salida: indica qué falta (normalmente `uidmap` o el perfil de AppArmor) y el comando para resolverlo. Habilita *lingering* para que el demonio arranque con el servidor y siga funcionando cuando cierres la sesión SSH: ```bash sudo loginctl enable-linger "$USER" ``` Y asegúrate de que el servicio queda habilitado: ```bash systemctl --user enable docker.service ``` ## Paso 5: Verificar la instalación La CLI usa el contexto `rootless`, que apunta al socket de tu usuario en `$XDG_RUNTIME_DIR/docker.sock`. Compruébalo: ```bash docker context ls ``` ```output NAME DESCRIPTION DOCKER ENDPOINT ERROR default Current DOCKER_HOST based configuration unix:///var/run/docker.sock rootless * Rootless mode unix:///run/user/1000/docker.sock ``` Confirma que el demonio funciona en modo rootless: ```bash docker info --format '{{.SecurityOptions}}' ``` ```output [name=seccomp,profile=builtin name=rootless name=cgroupns] ``` Ejecuta un contenedor de prueba y mira quién es el propietario del proceso en el host: ```bash docker run -d --name test-nginx -p 8080:80 nginx:alpine ps -o user,pid,cmd -C nginx ``` ```output USER PID CMD your_user 5123 nginx: master process nginx -g daemon off; 100100 5160 nginx: worker process ``` El proceso que dentro del contenedor es root, en el host pertenece a tu usuario. Las imágenes, contenedores y volúmenes se guardan en `~/.local/share/docker`, no en `/var/lib/docker`. Elimina el contenedor de prueba: ```bash docker rm -f test-nginx ``` ## Paso 6: Publicar puertos por debajo de 1024 Un usuario sin privilegios no puede abrir puertos por debajo de 1024, así que `-p 80:80` falla en modo rootless. La forma más acotada de permitirlo es dar la capacidad `CAP_NET_BIND_SERVICE` al binario de RootlessKit: ```bash sudo setcap cap_net_bind_service=ep "$(command -v rootlesskit)" systemctl --user restart docker.service ``` Comprueba que ahora puedes publicar el puerto 80: ```bash docker run -d --name web -p 80:80 nginx:alpine curl -I http://localhost ``` ```output HTTP/1.1 200 OK Server: nginx/1.27.2 ``` Si UFW está activo, abre el puerto con `sudo ufw allow 80/tcp`. Ten en cuenta que la capacidad se pierde cuando una actualización del paquete reemplaza el binario, así que tendrás que repetir el `setcap` tras actualizar Docker. Elimina el contenedor: ```bash docker rm -f web ``` ## Paso 7: Habilitar límites de CPU y memoria Opciones como `--memory` o `--cpus` necesitan que systemd delegue esos controladores de cgroup v2 en la sesión de tu usuario. Ubuntu 24.04 usa cgroup v2, pero por defecto solo delega `memory` y `pids`. Compruébalo: ```bash cat "/sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers" ``` ```output memory pids ``` Crea un archivo de configuración para el servicio de usuario de systemd: ```bash sudo mkdir -p /etc/systemd/system/user@.service.d sudo nano /etc/systemd/system/user@.service.d/delegate.conf ``` ```ini [Service] Delegate=cpu cpuset io memory pids ``` Recarga systemd: ```bash sudo systemctl daemon-reload ``` La delegación se aplica al iniciar la sesión de usuario de systemd. Como el *lingering* la mantiene viva, reinicia el servidor con `sudo reboot` para aplicarla. Al volver, repite la comprobación: ```bash cat "/sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers" ``` ```output cpuset cpu io memory pids ``` Prueba un contenedor con límites: ```bash docker run --rm --memory 256m --cpus 0.5 alpine cat /sys/fs/cgroup/memory.max /sys/fs/cgroup/cpu.max ``` ```output 268435456 50000 100000 ``` ## Limitaciones del modo rootless Antes de usarlo en producción, ten en cuenta lo que cambia respecto a Docker con root: | Aspecto | Comportamiento en rootless | |---|---| | IP de origen | Con el controlador de puertos por defecto, los contenedores ven las conexiones como si llegaran desde la red interna, no con la IP real del cliente. Si la necesitas en los logs, usa un proxy inverso que añada `X-Forwarded-For` o ejecuta ese servicio con `--network host`. | | Rendimiento de red | Algo menor que con la red en modo bridge del Docker con root, porque el tráfico pasa por un espacio de nombres de red de usuario. | | Opciones no disponibles | `--privileged` no da acceso real al hardware del host; tampoco funcionan AppArmor por contenedor, checkpoint ni redes `macvlan` o `ipvlan`. | | Almacenamiento | Controlador `overlay2` en kernels 5.11 o posteriores, como el de Ubuntu 24.04. | | Volúmenes bind | Los archivos creados por root dentro del contenedor pertenecen a tu usuario en el host; los creados con otro UID del contenedor pertenecen a un UID subordinado (por ejemplo `100999`). | ## Solución de problemas **`[rootlesskit:parent] error: failed to start the child: fork/exec /proc/self/exe: operation not permitted`.** AppArmor está bloqueando los espacios de nombres de usuario. Revisa que el perfil del paso 3 existe y está cargado con `sudo aa-status`. **`Cannot connect to the Docker daemon at unix:///var/run/docker.sock`.** La CLI está usando el contexto `default`. Cambia al rootless con `docker context use rootless`, o define `export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock` en tu `~/.bashrc`. **`Failed to connect to bus: No medium found` al ejecutar `systemctl --user`.** La sesión no tiene un gestor de systemd de usuario, típico si has entrado con `su`. Conéctate por SSH directamente con ese usuario. **El demonio se detiene al cerrar SSH o no arranca tras reiniciar.** Falta `sudo loginctl enable-linger your_user` o el servicio no está habilitado con `systemctl --user enable docker.service`. **Los logs del demonio.** Consúltalos con `journalctl --user -u docker.service`. ## Conclusión Has configurado Docker en modo rootless en Ubuntu 24.04, con el perfil de AppArmor necesario, arranque automático mediante systemd, puertos privilegiados y límites de CPU y memoria funcionando. A partir de aquí puedes crear un usuario dedicado por proyecto o por cliente, cada uno con su propio demonio aislado, poner un proxy inverso delante para conservar la IP del cliente o comparar este enfoque con Podman, que funciona sin root y sin demonio de serie.