Cambiando permisos en volúmenes Docker

Actualizado el 24 de Marzo de 2021

A veces es necesario que tanto el contenedor como el host accedan a la misma carpeta ya sea local al host o una carpeta externa, esto se puede configurar a través de los volúmenes Docker, para que ambos puedan tener los mismos permisos es necesario que compartan el mismo id de usuario o de grupo, esto es importante porque el nombre de usuario no servirá.

Normalmente esto se soluciona creando un usuario o grupo en el contenedor con un id específico y usando ese id para establecer los permisos en el host. El problema es que a veces el usuario es creado automáticamente por un paquete, como un usuario de servicio, y no se puede conocer por anticipado.

Una solución sencilla es arrancar el contenedor y ejecutar dentro de este el comando id por ejemplo docker exec #contenedor id -u que devolverá el id de usuario que se está usando en el contenedor docker.

Puede ser que esta opción no sea viable porque el contenedor necesite acceder a esa carpeta para arrancar o simplemente no interesa esta acción manual al ejecutarse Docker en un entorno automatizado (DevOps).

Permisos Docker

Script

Una posible solución es usar este script basado en la imagen base de linuxserver.

#!/bin/sh
RA_SRVC=${RA_SRVC:-$(id -un)}

if [ "$RA_SRVC" = $(id -un) ]; then
  echo "Executing as self: $RA_SRVC"
  echo "You will need to be root or sudo"
  $@
else
  RA_SRVC=${RA_SRVC:-$(id -un)}
  uid=$(id -u $RA_SRVC)
  gid=$(id -g $RA_SRVC)
  RA_UUID=${RA_UUID:-$uid}
  RA_GUID=${RA_GUID:-$gid}
  RA_FLDR=${RA_FLDR:-$(pwd)}
  echo "  Starting $RA_SRVC uid=$(id -u $RA_SRVC) gid=$(id -g $RA_SRVC)
  Setting user id:  $RA_UUID $(gosu root usermod -o -u $RA_UUID $RA_SRVC)
  -------------------------------------
  User:     $RA_SRVC $(id -u $RA_SRVC)
  Folder:   $RA_FLDR
  -------------------------------------
  Setting permissions on $RA_FLDR $(gosu root chown -R $RA_UUID:$RA_GUID $RA_FLDR)
  Running $@
  "
  exec gosu $RA_SRVC $@
fi

Usamos las siguientes variables de entorno:

  • RA_SRVC: el usuario que ejecutará el contenedor Docker, si no se indica se supondrá el usuario actual del contenedor Docker.
  • RA_UUID: el nuevo id de usuario.
  • RA_GUID: el id de grupo que se usará para cambiar los permisos.
  • RA_FLDR: la carpeta en la que se establecerá el nuevo owner.

La idea del script es establecer un nuevo id de usuario (RA_UUID) al usuario que va a ejecutar Docker (RA_SRVC) estas variables de entorno se pueden pasar a Docker vía línea de comandos o a través de un fichero docker-compose, después se usa el comando chown para cambiar el propietario en la carpeta indicada (RA_FLDR) al usuario (RA_UUID) y grupo indicado (RA_GUID).

Si no se indica un usuario se entiende que es el establecido en Docker via comando USER o el indicado en docker-compose usando user. Este usuario (RA_SRVC) tiene que ser otro diferente al que arranca el contenedor ya que no se puede cambiar el id así mismo sin reiniciar.

La única opción si se intenta cambiar el id del usuario que está activo en Docker sería hacer un login para refrescar el id del usuario, por ejemplo a través del comando su, lo que implicaría pasar la contraseña al script para poder hacerlo o reiniciar el contenedor pero dado que Docker no conserva el estado no sería útil.

Se está usando gosu en lugar de sudo porque es la opción recomendada para contenedores Docker, para detalles del uso de gosu ver aquí, sino queremos usar gosu porque no se puede instalar la opción comentada también funcionaría sudo -u «$RA_SRVC» $

Hay que tener en cuenta que si el volumen a compartir es una unidad de red entonces en /etc/fstab se indica el usuario que se establecerá como owner al montar la carpeta.

Uso

Una forma típica de uso es usando el comando ENTRYPOINT de Docker, la diferencia con CMD es que ENTRYPOINT no se puede sobreescribir, por ejemplo:

ENTRYPOINT [«/bin/sh», «/entry_point.sh»]
CMD [«/usr/bin/transmission-daemon», «-f», «-x», «/tmp/trans.PID»]

Un ejemplo más completo aquí.

Mejoras

En la opción sudo es necesario que el usuario pueda ejecutar sudo para poder establecer los permisos y lanzar el comando que ejecutará el contenedor, esto se podría cambiar quitando sudo antes de lanzar el comando si el usuario puede lanzar el comando sin usar sudo, también se puede usar s6-setuidguid.

Si se ejecuta el contenedor con el usuario por defecto root se pueden establecer los permisos usando también root en el host aunque puede que no sea la opción más segura.

Notas al pie

Detalles sobre instrucciones bash aquí.
Monta tu propio logo en ascii-art.
El comando cat es para mostrar el logo.

Cambiando permisos en volúmenes Docker