Trabajando con almacenamiento en contenedores rootless
- La manera de trabajar con el almacenamiento en contenedores rootless es similar a la vista anteriormente con contenedores rootful.
- Cuando trabajamos con volúmenes con un usuario no privilegiado el directorio donde se crean los volúmenes es
$HOME/.local/share/containers/storage/volumes/
. - De manera similar cuando se utilice un bind mount con un directorio que no es accesible por el contenedor por la configuración SELinux, tendremos que usar las opciones adecuadas para configurar el directorio y hacerlo accesible.
Uso de volúmenes con contenedores rootless con procesos en el contenedor ejecutándose como root
Si creamos un volumen y lo montamos en un contenedor rootless cuyos procesos se están ejecutando con el usuario root
, vamos los usuarios propietarios de los ficheros:
$ podman volume create vol1
$ podman run -dit -v vol1:/destino --name alpine1 alpine
$ podman exec alpine1 ls -ld /destino
drwxr-xr-x 1 root root 0 Jan 26 17:53 /destino
Cómo cabría esperar, comprobamos que el directorio que hemos montado pertenece al usuario root
.
Podemos inspeccionar el volumen y obtenemos el directorio donde se ha creado en el host:
$ podman volume inspect vol1
[
{
"Name": "vol1",
"Driver": "local",
"Mountpoint": "/home/usuario/.local/share/containers/storage/volumes/vol1/_data",
"CreatedAt": "2024-04-02T08:11:05.344065435Z",
"Labels": {},
"Scope": "local",
"Options": {},
"MountCount": 0,
"NeedsCopyUp": true,
"LockNumber": 0
}
]
Estamos utilizando un usuario sin privilegios en el host con UID = 1000. Veamos el propietario del directorio donde se almacenan los ficheros del volumen en el host:
$ id
uid=1000(usuario) gid=1000(usuario) groups=1000(usuario),4(adm),10(wheel),190(systemd-journal) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
$ ls -ld .local/share/containers/storage/volumes/vol1/_data/
drwxr-xr-x. 1 usuario usuario 0 Jan 26 17:53 .local/share/containers/storage/volumes/vol1/_data/
Comprobamos que en el host el propietario es nuestro usuario sin privilegios. Si creamos un fichero en el volumen desde el host o desde el contenedor:
$ touch .local/share/containers/storage/volumes/vol1/_data/fichero1
$ podman exec alpine1 touch /destino/fichero2
Comprobamos que dentro del contenedor pertenecen a root
:
$ podman exec alpine1 ash -c "ls -l /destino"
total 0
-rw-r--r-- 1 root root 0 Apr 2 08:14 fichero1
-rw-r--r-- 1 root root 0 Apr 2 08:15 fichero2
Y que en el host pertenecen al usuario usuario
:
$ ls -l .local/share/containers/storage/volumes/vol1/_data/
total 0
-rw-r--r--. 1 usuario usuario 0 Apr 2 08:14 fichero1
-rw-r--r--. 1 usuario usuario 0 Apr 2 08:15 fichero2
Uso de bind mount con contenedores rootless con procesos en el contenedor ejecutándose como root
En este caso el uso de bind mount no tiene ninguna dificultad, ya que los usuarios del host y del contenedor están relacionados: el directorio que queremos montar pertenece al usuario usuario
en el host y pertenece al usuario root
en el contenedor.
Si tenemos activo SELinux tendremos que usar la opción :z
o :Z
según nos interese. El el directorio web
tenemos un fichero index.html
:
$ ls -l web
total 4
-rw-r--r--. 1 usuario usuario 15 Apr 2 07:53 index.html
Creamos el contenedor y comprobamos el propietario del fichero:
$ podman run -dit -v ${PWD}/web:/destino:Z --name alpine2 alpine
$ podman exec -it alpine2 ls -l /destino
total 4
-rw-r--r-- 1 root root 15 Apr 2 07:53 index.html
En resumen, el uso de volúmenes o bind mount en contenedores rootless cuando se ejecutan los procesos como root
es muy similar a hacerlo con contenedores rootful. Simplemente tenemos que tener en cuenta que el directorio donde se crean los volúmenes se encuentra en el home del usuario: $HOME/.local/share/containers/storage/volumes/
.
Uso de volúmenes con contenedores rootless con procesos en el contenedor ejecutándose con usuario sin privilegios
El volumen lo crea el usuario del host, pero dentro del contenedor es propiedad del usuario del contenedor. Por lo tanto desde contenedor se puede escribir, pero desde fuera no se pueda escribir.
$ podman volume create vol2
$ podman run -dit -u 123:123 -v vol2:/destino --name alpine3 alpine
$ podman exec alpine3 touch /destino/fichero1
$ touch .local/share/containers/storage/volumes/vol2/_data/fichero2
touch: cannot touch '.local/share/containers/storage/volumes/vol2/_data/fichero2': Permission denied
Podemos ver el propietario del directorio: dentro del contenedor pertenece al usuario que hemos indicado, en este caso es ntp
que tiene UID y GID igual a 123; fuera del contenedor el directorio donde se guarda la información del volumen pertenece al usuario con UID 524410, que corresponde al UID que se ha mapeado fuera del contenedor.
$ podman exec -it alpine3 ls -ld destino
drwxr-xr-x 1 ntp ntp 16 Apr 2 11:30 destino
$ ls -l .local/share/containers/storage/volumes/vol2
total 0
drwxr-xr-x. 1 524410 524410 16 Apr 2 11:30 _data
Uso de bind mount con contenedores rootless con procesos en el contenedor ejecutándose con usuario sin privilegios
Creamos un directorio con un fichero que pertenecen al usuario sin privilegios, en nuestro caso usuario
:
$ mkdir origen
$ touch origen/fichero1
Creamos un contador y montamos el directorio origen
con la opción :Z
para configurar de forma adecuada SELinux y sea accesible desde el contenedor. Comprobamos que al pertenecer el directorio origen
a nuestro usuario usuario
, el directorio destino
será propiedad del root
(mapeo de usuario
) y por lo tanto el usuario con UID 123 no podrá acceder al directorio:
$ podman run -dit -u 123:123 -v ./origen:/destino:Z --name alpine4 alpine
$ podman exec -it alpine4 ls -ld destino
drwxr-xr-x 1 root root 16 Apr 2 14:28 destino
$ podman exec alpine4 touch /destino/fichero2
touch: /destino/fichero2: Permission denied
Para que el usuario con UID 123 pueda acceder al directorio tenemos que asegurarnos que el directorio destino
le pertenece. Para conseguir esto lo podemos hacer de dos formas distintas:
-
A la hora de montar el directorio utilizar la opción
:U
que cambia el usuario y grupo de forma recursiva al directorio montado dentro del contenedor con el usuario y grupo que se esté ejecutando dentro del contenedor. En nuestro caso, creamos un nuevo contenedor con dicha opción:$ podman run -dit -u 123:123 -v ./origen:/destino:Z,U --name alpine4 alpine $ podman exec -it alpine4 ls -ld destino drwxr-xr-x 1 ntp ntp 16 Apr 2 14:28 destino $ podman exec alpine4 touch /destino/fichero2
-
Otra opción sería cambiar el propietario del directorio
origen
en el host con el UID y GID del usuario que se ejecuta dentro del contenedor. Para ello es necesario que esa instrucción la ejecutemos en el espacio de nombres de usuario del contenedor, para ello usaremos la instrucciónpodman unshare
:$ podman unshare chown -R 123:123 origen
Comprobamos que fuera del contenedor el UID que se asigna es el correspondiente al mapeo de UID realizado:
$ ls -ld origen drwxr-xr-x. 1 524410 524410 32 Apr 2 14:39 origen
Creamos un nuevo contenedor y comprobamos que dentro del contenedor el cambio de propietario se refleja de forma y correcta (pertenece al usuario
ntp:ntp
, que corresponde con el UID y GID 123) y ahora si podemos acceder al directorio:$ podman run -dit -u 123:123 -v ./origen:/destino:Z --name alpine5 alpine $ podman exec -it alpine5 ls -ld destino drwxr-xr-x 1 ntp ntp 32 Apr 2 14:39 destino $ podman exec -it alpine5 ls -l destino total 0 -rw-r--r-- 1 ntp ntp 0 Apr 2 14:28 fichero1 -rw-r--r-- 1 ntp ntp 0 Apr 2 14:39 fichero2 $ podman exec -it alpine5 touch destino/fichero3