tutorial hub community docker

hub - docker ubuntu



Docker y--userns-remap, ¿cómo administrar los permisos de volumen para compartir datos entre el host y el contenedor? (3)

En Docker, los archivos creados dentro de los contenedores tienden a tener una propiedad impredecible al inspeccionarlos desde el host. El propietario de los archivos en un volumen es root (uid 0) de forma predeterminada, pero tan pronto como las cuentas de usuario no root están involucradas en el contenedor y escriben en el sistema de archivos, los propietarios se vuelven más o menos aleatorios desde la perspectiva del host.

Es un problema cuando necesita acceder a datos de volumen desde el host utilizando la misma cuenta de usuario que está llamando a los comandos del acoplador.

Las soluciones típicas son

  • Obligar a los usuarios de UID en el momento de la creación en Dockerfiles (no portátil)
  • pasar el UID del usuario host al comando docker run como una variable de entorno y luego ejecutar algunos comandos chown en los volúmenes en un script de punto de entrada.

Ambas soluciones pueden dar cierto control sobre los permisos reales fuera del contenedor.

Esperaba que los espacios de nombres de usuario fueran la solución final a este problema. He realizado algunas pruebas con la versión 1.10 recientemente lanzada y --userns-remap configurada en mi cuenta de escritorio. Sin embargo, no estoy seguro de que pueda facilitar el manejo de la propiedad de archivos en volúmenes montados, me temo que podría ser todo lo contrario.

Supongamos que comienzo este contenedor básico

docker run -ti -v /data debian:jessie /bin/bash echo ''hello'' > /data/test.txt exit

Y luego inspeccione el contenido del host:

ls -lh /var/lib/docker/100000.100000/volumes/<some-id>/_data/ -rw-r--r-- 1 100000 100000 6 Feb 8 19:43 test.txt

Este número ''100000'' es un sub-UID de mi usuario host, pero como no corresponde al UID de mi usuario, todavía no puedo editar test.txt sin privilegios. Este subusuario no parece tener ninguna afinidad con mi usuario habitual fuera de Docker. No está mapeado de vuelta.

Las soluciones mencionadas anteriormente en esta publicación, que consistían en alinear los UID entre el host y el contenedor, ya no funcionan debido a la UID->sub-UID que ocurre en el espacio de nombres.

Entonces, ¿hay alguna manera de ejecutar Docker con el espacio de nombres de usuario habilitado (para mejorar la seguridad), y al mismo tiempo hacer posible que el usuario host que ejecuta Docker sea el propietario de los archivos generados en los volúmenes?


Puede evitar problemas de permisos utilizando el comando docker cp .

La propiedad se establece para el usuario y el grupo primario en el destino. Por ejemplo, los archivos copiados en un contenedor se crean con UID:GID del usuario raíz. Los archivos copiados en la máquina local se crean con el UID:GID del usuario que invocó el comando docker cp .

Aquí está su ejemplo cambiado para usar docker cp :

$ docker run -ti -v /data debian:jessie /bin/bash root@e33bb735a70f:/# echo ''hello'' > /data/test.txt root@e33bb735a70f:/# exit exit $ docker volume ls DRIVER VOLUME NAME local f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93 $ sudo ls -l /var/lib/docker/100000.100000/volumes/f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93/_data total 4 -rw-r--r-- 1 100000 100000 6 Oct 6 10:34 test.txt $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e33bb735a70f debian:jessie "/bin/bash" About a minute ago Exited (0) About a minute ago determined_hypatia $ docker cp determined_hypatia:/data/test.txt . $ ls -l test.txt -rw-r--r-- 1 don don 6 Oct 6 10:34 test.txt $ cat test.txt hello $

Sin embargo, si solo desea leer archivos de un contenedor, no necesita el volumen con nombre. Este ejemplo utiliza un contenedor con nombre en lugar de un volumen con nombre:

$ docker run -ti --name sandbox1 debian:jessie /bin/bash root@93d098233cf3:/# echo ''howdy'' > /tmp/test.txt root@93d098233cf3:/# exit exit $ docker cp sandbox1:/tmp/test.txt . $ ls -l test.txt -rw-r--r-- 1 don don 6 Oct 6 10:52 test.txt $ cat test.txt howdy $

Encuentro que los volúmenes con nombre son útiles cuando quiero copiar archivos en un contenedor, como se describe en esta pregunta .


Si puede preorganizar a los usuarios y grupos de antemano, entonces es posible asignar UID y GID de manera específica para que los usuarios host se correspondan con los usuarios con espacios de nombres dentro de los contenedores.

Aquí hay un ejemplo (Ubuntu 14.04, Docker 1.10):

  1. Cree algunos usuarios con ID numéricos fijos:

    useradd -u 5000 ns1 groupadd -g 500000 ns1-root groupadd -g 501000 ns1-user1 useradd -u 500000 -g ns1-root ns1-root useradd -u 501000 -g ns1-user1 ns1-user1 -m

  2. Edite manualmente los rangos de ID subordinados generados automáticamente en los archivos /etc/subuid y /etc/subgid :

    ns1:500000:65536

    (tenga en cuenta que no hay registros para ns1-root y ns1-user1 debido a los límites MAX_UID y MAX_GID en /etc/login.defs )

  3. Habilite los espacios de nombres de usuario en /etc/default/docker :

    DOCKER_OPTS="--userns-remap=ns1"

    Reinicie el service docker restart /var/lib/docker/500000.500000 service docker restart daemon, asegúrese de que se /var/lib/docker/500000.500000 creado el directorio /var/lib/docker/500000.500000 .

    Ahora, dentro de los contenedores tiene root y user1 , y en el host - ns1-root y ns1-user1 , con ID coincidentes

    ACTUALIZACIÓN: para garantizar que los usuarios no root tengan ID fijos en los contenedores (por ejemplo, user1 1000: 1000), créelos explícitamente durante la creación de la imagen.

Prueba de conducción:

  1. Prepare un directorio de volúmenes

    mkdir /vol1 chown ns1-root:ns1-root /vol1

  2. Pruébalo desde un contenedor

    docker run --rm -ti -v /vol1:/vol1 busybox sh echo "Hello from container" > /vol1/file exit

  3. Probar desde el anfitrión

    passwd ns1-root login ns1-root cat /vol1/file echo "can write" >> /vol1/file

No es portátil y parece un truco, pero funciona.


Una solución alternativa es asignar dinámicamente el uid del usuario en el tiempo de compilación para que coincida con el host.

Dockerfile ejemplo:

FROM ubuntu # Defines argument which can be passed during build time. ARG UID=1000 # Create a user with given UID. RUN useradd -d /home/ubuntu -ms /bin/bash -g root -G sudo -u $UID ubuntu # Switch to ubuntu user by default. USER ubuntu # Check the current uid of the user. RUN id # ...

Luego construir como:

docker build --build-arg UID=$UID -t mycontainer .

y correr como:

docker run mycontainer

Si tiene un contenedor existente, cree un contenedor contenedor con el siguiente Dockerfile :

FROM someexistingcontainer ARG UID=1000 USER root # This assumes you''ve the existing user ubuntu. RUN usermod -u $UID ubuntu USER ubuntu

Esto se puede envolver en docker-compose.yml como:

version: ''3.4'' services: myservice: command: id image: myservice build: context: . volumes: - /data:/data:rw

Luego compila y ejecuta como:

docker-compose build --build-arg UID=$UID myservice; docker-compose run myservice