# Consejos


## Uso avanzado

### Demonio

**Con systemd (Muy recomendado)**



El archivo de unidad de systemd se instala como `~/.config/systemd/user/docker.service`.

Utiliza `systemctl --user` para gestionar el ciclo de vida del demonio:

```console
$ systemctl --user start docker
```

Para iniciar el demonio en el arranque del sistema, habilita el servicio de systemd y el lingering (persistencia de sesión):

```console
$ systemctl --user enable docker
$ sudo loginctl enable-linger $(whoami)
```

No se admite iniciar Docker Rootless como un servicio de systemd a nivel de todo el sistema (`/etc/systemd/system/docker.service`), incluso con la directiva `User=`.

**Sin systemd**



Para ejecutar el demonio directamente sin systemd, debes ejecutar `dockerd-rootless.sh` en lugar de `dockerd`.

Se deben configurar las siguientes variables de entorno:
- `$HOME`: el directorio de inicio
- `$XDG_RUNTIME_DIR`: un directorio efímero al que solo puede acceder el usuario esperado, por ejemplo, `~/.docker/run`.
  El directorio se debe eliminar en cada apagado del anfitrión.
  El directorio puede estar en tmpfs, sin embargo, no debe estar bajo `/tmp`.
  Ubicar este directorio bajo `/tmp` podría ser vulnerable a ataques TOCTOU (Time-of-Check to Time-of-Use).



Es importante tener en cuenta que con las rutas de directorio:

- La ruta del socket se establece en `$XDG_RUNTIME_DIR/docker.sock` por defecto.
  `$XDG_RUNTIME_DIR` se configura normalmente como `/run/user/$UID`.
- El directorio de datos se establece en `~/.local/share/docker` por defecto.
  El directorio de datos no debe estar en NFS.
- El directorio de configuración del demonio se establece en `~/.config/docker` por defecto.
  Este directorio es diferente de `~/.docker`, que es utilizado por el cliente.

### Cliente

Desde Docker Engine v23.0, `dockerd-rootless-setuptool.sh install` configura automáticamente la CLI de `docker` para utilizar el contexto `rootless`.

Antes de Docker Engine v23.0, el usuario tenía que especificar de forma explícita la ruta del socket o el contexto de la CLI.

Para especificar la ruta del socket utilizando `$DOCKER_HOST`:

```console
$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
$ docker run -d -p 8080:80 nginx
```

Para especificar el contexto de la CLI utilizando `docker context`:

```console
$ docker context use rootless
rootless
Current context is now "rootless"
$ docker run -d -p 8080:80 nginx
```

## Buenas prácticas

### Docker Rootless en Docker

Para ejecutar Docker Rootless dentro de Docker "rootful" (con privilegios de root), utiliza la imagen `docker:<version>-dind-rootless` en lugar de `docker:<version>-dind`.

```console
$ docker run -d --name dind-rootless --privileged docker:25.0-dind-rootless
```

La imagen `docker:<version>-dind-rootless` se ejecuta como un usuario no root (UID 1000).
Sin embargo, se requiere `--privileged` para deshabilitar seccomp, AppArmor y las máscaras de montaje.

### Exponer el socket de la API de Docker a través de TCP

Para exponer el socket de la API de Docker a través de TCP, debes iniciar `dockerd-rootless.sh` con `DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="-p 0.0.0.0:2376:2376/tcp"`.

```console
$ DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="-p 0.0.0.0:2376:2376/tcp" \
  dockerd-rootless.sh \
  -H tcp://0.0.0.0:2376 \
  --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem
```

### Exponer el socket de la API de Docker a través de SSH

Para exponer el socket de la API de Docker a través de SSH, debes asegurarte de que `$DOCKER_HOST` esté configurada en el anfitrión remoto.

```console
$ ssh -l <REMOTEUSER> <REMOTEHOST> 'echo $DOCKER_HOST'
unix:///run/user/1001/docker.sock
$ docker -H ssh://<REMOTEUSER>@<REMOTEHOST> run ...
```

### Enrutar paquetes ping

En algunas distribuciones, `ping` no funciona por defecto.

Añade `net.ipv4.ping_group_range = 0   2147483647` a `/etc/sysctl.conf` (o a `/etc/sysctl.d`) y ejecuta `sudo sysctl --system` para permitir el uso de `ping`.

### Exponer puertos privilegiados

Para exponer puertos privilegiados (< 1024), establece `CAP_NET_BIND_SERVICE` en el binario `rootlesskit` y reinicia el demonio.

```console
$ sudo setcap cap_net_bind_service=ep $(which rootlesskit)
$ systemctl --user restart docker
```

O añade `net.ipv4.ip_unprivileged_port_start=0` a `/etc/sysctl.conf` (o a `/etc/sysctl.d`) y ejecuta `sudo sysctl --system`.

### Limitar recursos

Limitar recursos con banderas de `docker run` relacionadas con cgroup, como `--cpus`, `--memory` o `--pids-limit`, solo se admite cuando se ejecuta con cgroup v2 y systemd.
Consulta [Cambiar la versión de cgroup](/engine/containers/runmetrics/) para habilitar cgroup v2.

Si `docker info` muestra `none` como `Cgroup Driver`, no se cumplen las condiciones.
Cuando estas condiciones no se cumplen, el modo rootless ignora las banderas de `docker run` relacionadas con cgroup.
Consulta [Limitar recursos sin cgroup](#limiting-resources-without-cgroup) para conocer alternativas.

Si `docker info` muestra `systemd` as `Cgroup Driver`, se cumplen las condiciones.
Sin embargo, por lo general, solo los controladores `memory` y `pids` se delegan a usuarios no root por defecto.

```console
$ cat /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers
memory pids
```

Para permitir la delegación de todos los controladores, debes cambiar la configuración de systemd de la siguiente manera:

```console
# mkdir -p /etc/systemd/system/user@.service.d
# cat > /etc/systemd/system/user@.service.d/delegate.conf << EOF
[Service]
Delegate=cpu cpuset io memory pids
EOF
# systemctl daemon-reload
```

> [!NOTE]
>
> Delegar `cpuset` requiere systemd 244 o posterior.

#### Limitar recursos sin cgroup

Incluso cuando cgroup no está disponible, puedes seguir utilizando los tradicionales `ulimit` y [`cpulimit`](https://github.com/opsengine/cpulimit), aunque funcionan a nivel de granularidad de proceso en lugar de granularidad de contenedor, y el proceso del contenedor los puede deshabilitar de forma arbitraria.

Por ejemplo:

- Para limitar el uso de CPU a 0.5 núcleos (similar a `docker run --cpus 0.5`):
  `docker run <IMAGE> cpulimit --limit=50 --include-children <COMMAND>`
- Para limitar el VSZ máximo a 64MiB (similar a `docker run --memory 64m`):
  `docker run <IMAGE> sh -c "ulimit -v 65536; <COMMAND>"`
- Para limitar el número máximo de procesos a 100 por UID con espacio de nombres 2000 (similar a `docker run --pids-limit=100`):
  `docker run --user 2000 --ulimit nproc=100 <IMAGE> <COMMAND>`

