Moby: Agregue la capacidad de montar el volumen como usuario que no sea root

Creado en 17 oct. 2013  ·  157Comentarios  ·  Fuente: moby/moby

Caso de uso: monte un volumen del host al contenedor para que apache lo use como usuario www.
El problema es que actualmente todos los montajes están montados como root dentro del contenedor.
Por ejemplo, este comando
ventana acoplable ejecutar -v /tmp:/var/www ubuntu stat -c "%U %G" /var/www
imprimirá "raíz raíz"

Necesito montarlo como usuario www dentro del contenedor.

areapi arekernel arevolumes exexpert kinenhancement

Comentario más útil

¿Puedo decir que no? Obligando a los usuarios a agregar un script de ayuda que sí

#!/bin/sh
chown -R redis:redis /var/lib/redis
exec sudo -u redis /usr/bin/redis-server

(gracias @bfirsh por tu ejemplo)

es bastante terrible

Significa que el contenedor debe iniciarse como raíz, en lugar de ejecutarse como el usuario redis previsto. (como aludió @aldanor )

y significa que un usuario no puede hacer algo como:

docker run -v /home/user/.app_cfg/ -u user application_container application :(

Todos 157 comentarios

Si chown el volumen (en el lado del host) antes de montarlo, funcionará.
En ese caso, podrías hacer:

mkdir /tmp/www
chown 101:101 /tmp/www
docker run -v /tmp/www:/var/www ubuntu stat -c "%U %G" /var/www

(Suponiendo que 101:101 es el UID:GID del usuario www-data en su contenedor).

Otra posibilidad es hacer el montaje de enlace, luego chown dentro del contenedor.

@mingfang ¿Chown no funcionará para ti?

Sería útil tener un atajo para esto. A menudo me encuentro escribiendo run scripts que solo establecen los permisos en un volumen:

https://github.com/orchardup/docker-redis/blob/07b65befbd69d9118e6c089e8616d48fe76232fd/run

¿Qué sucede si no tiene los derechos para chown ?

¿Un script de ayuda que chown el volumen resolvería este problema? Este scirpt puede ser el ENTRYPOINT de su Dockerfile.

¿Puedo decir que no? Obligando a los usuarios a agregar un script de ayuda que sí

#!/bin/sh
chown -R redis:redis /var/lib/redis
exec sudo -u redis /usr/bin/redis-server

(gracias @bfirsh por tu ejemplo)

es bastante terrible

Significa que el contenedor debe iniciarse como raíz, en lugar de ejecutarse como el usuario redis previsto. (como aludió @aldanor )

y significa que un usuario no puede hacer algo como:

docker run -v /home/user/.app_cfg/ -u user application_container application :(

Hay _una_ manera de hacer que funcione, pero debe prepararse con anticipación dentro de su Dockrfile.

RUN mkdir -p /var/lib/redis ; chown -R redis:redis /var/lib/redis
VOLUME ["/var/lib/redis"]
ENTRYPOINT ["usr/bin/redis-server"]
USER redis

(No probé este ejemplo, estoy trabajando en un contenedor de cromo que luego se muestra en un contenedor _separado_ X11 que ...)

Y, por supuesto, ese método solo funciona para nuevos volúmenes directos, no vinculantes.
montado o volúmenes-desde volúmenes. ;)

Además, varios contenedores que usan volumes-from tendrán diferentes uid/gid para el mismo usuario, lo que también complica las cosas.

@SvenDowideit @tianon ese método tampoco funciona. Ejemplo completo:

FROM ubuntu
RUN groupadd -r redis    -g 433 && \
useradd -u 431 -r -g redis -d /app -s /sbin/nologin -c "Docker image user" redis 
RUN mkdir -p /var/lib/redis
RUN echo "thing" > /var/lib/redis/thing.txt
RUN chown -R redis:redis /var/lib/redis
VOLUME ["/var/lib/redis"]
USER redis
CMD /bin/ls -lah /var/lib/redis

Dos ejecuciones, con y sin un volumen -v:

bash-3.2$ docker run -v `pwd`:/var/lib/redis voltest 
total 8.0K
drwxr-xr-x  1 root root  102 Aug  7 21:30 .
drwxr-xr-x 28 root root 4.0K Aug  7 21:26 ..
-rw-r--r--  1 root root  312 Aug  7 21:30 Dockerfile
bash-3.2$ docker run  voltest 
total 12K
drwxr-xr-x  2 redis redis 4.0K Aug  7 21:30 .
drwxr-xr-x 28 root  root  4.0K Aug  7 21:26 ..
-rw-r--r--  1 redis redis    6 Aug  7 21:26 thing.txt
bash-3.2$ 

Estamos llegando a un problema que se resolvería con esto (creo). Tenemos un recurso compartido de NFS para los directorios de inicio de nuestro desarrollador. Los desarrolladores quieren montar /home/dev/git/project en Docker pero no pueden porque tenemos habilitado Root Squash.

Esto prohíbe que la raíz acceda a /home/dev/git/project por lo que cuando intento ejecutar el montaje de la ventana acoplable /home/dev/git/project aparece un error lstat permission denied .

@frankamp Esto se debe a que la preferencia actual de Docker es no modificar las cosas del host que no están bajo el control de Docker.

Su definición de "VOLUMEN" está siendo sobrescrita por su -v pwd`:/var/lib/reds`.
Pero en su segunda ejecución, está usando un volumen controlado por ventana acoplable, que se crea en /var/lib/docker. Cuando se inicia el contenedor, la ventana acoplable copia los datos de la imagen en el volumen y, a continuación, corta el volumen con el uid:gid del directorio para el que se especificó el volumen.

No estoy seguro de que se pueda hacer mucho aquí y, lamentablemente, los montajes de enlace no admiten (hasta donde puedo decir) el montaje como un uid/gid diferente.

Mi solución a esto fue hacer lo que SvenDowideit hizo anteriormente (crear un nuevo usuario y agregarlo por adelantado en dockerfile), pero luego, en lugar de montar el volumen del host, usar un contenedor solo de datos y copiar el volumen del host que quería montar en el contenedor con tar cf - . | docker run -i --volumes-from app_data app tar xvf - -C /data . Esto será un poco más fácil una vez que se fusione https://github.com/docker/docker/pull/13171 (y docker cp funciona en ambos sentidos), pero tal vez podría convertirse en una alternativa a -v host_dir:container_dir , es decir. tal vez -vc host_dir:container_dir , (vc para copia de volumen), donde el contenido de host_dir se copiaría en el contenedor de datos. Aunque no puedo decir que entiendo por qué/cómo los archivos copiados heredan los permisos del usuario del contenedor, por lo que puedo decir que hacen, y esta es la única solución razonable que he logrado encontrar que no destruye la portabilidad.

¿Qué pasa con ACL?

¿Hay alguna solución o solución? Me encuentro con el mismo problema con OpenShift, la carpeta montada es propiedad de root:root y las imágenes creadas previamente no funcionarán.

Estoy buscando una solución también. Si todos los volúmenes montados son propiedad de root , es imposible ejecutar sus contenedores Docker con cualquier usuario que no sea root .

Bueno, puedes probar s6-overlay . Incluye características que están específicamente dirigidas a ayudar a solucionar este tipo de problemas.

@dreamcat4 : Gracias por la indicación. La propiedad y los permisos de corrección parecen una solución interesante, pero ¿no tendría que ejecutar mi contenedor Docker como raíz para que funcione?

@ brikis98 Sí, eso es cierto. Sin embargo, s6-overlay también tiene otra función, que le permite volver a eliminar los permisos al iniciar sus servidores/demonios.

@dreamcat4 Ah, lo tengo, gracias.

Tengo el mismo uid/gid dentro y fuera de un contenedor y esto es lo que obtengo:

nonroot$ ls -l .dotfiles/
ls: cannot access .dotfiles/byobu: Permission denied
ls: cannot access .dotfiles/config: Permission denied
ls: cannot access .dotfiles/docker: Permission denied
ls: cannot access .dotfiles/vim: Permission denied
ls: cannot access .dotfiles/bashrc: Permission denied
ls: cannot access .dotfiles/muse.yml: Permission denied
ls: cannot access .dotfiles/my.cnf: Permission denied
ls: cannot access .dotfiles/profile: Permission denied
total 0
-????????? ? ? ? ?            ? bashrc
d????????? ? ? ? ?            ? byobu
d????????? ? ? ? ?            ? config
d????????? ? ? ? ?            ? docker
-????????? ? ? ? ?            ? muse.yml
-????????? ? ? ? ?            ? my.cnf
-????????? ? ? ? ?            ? profile
d????????? ? ? ? ?            ? vim
nonroot$ ls -l .ssh
ls: cannot access .ssh/authorized_keys: Permission denied
total 0
-????????? ? ? ? ?            ? authorized_keys
nonroot$

@darkermatter , ¿podría abrir un problema separado?

no es un problema, pero ¿no es esto relevante aquí?

@darkermatter esta es una solicitud de función, no un informe de error, mezclar su caso con otros casos hace que sea difícil seguir la discusión, además, es posible que su problema no esté directamente relacionado

@thaJeztah bueno, como lo han hecho @frankamp y otros, simplemente estaba demostrando lo que sucede después de ejecutar chmod, etc. dentro del Dockerfile. Lo archivaré como un informe de error, pero es relevante para esta discusión.

similar a lo que propuso @ebuchman , sin copiar un volumen de host, podría crear primero un contenedor solo de datos, que hace un
chown 1000:1000 /volume-mount como root cuando se inició.
Por ejemplo, en la sintaxis de docker compose v2

version: '2'
services:
  my-beautiful-service:
    ...
    depends_on:
      - data-container
    volumes_from:
      - data-container

  data-container:
    image: same_base_OS_as_my-beautiful-service
    volumes:
      - /volume-mount
    command: "chown 1000:1000 /volume-mount"

De esta manera, su contenedor puede ejecutarse como usuario no root. El contenedor de solo datos solo se ejecuta una vez.
Suponiendo que conoce el uid y el gid que usa my-beautiful-service de antemano. Suele ser 1000,1000.

Dado que puede (en 1.11) especificar opciones de montaje para un volumen para usar en su docker volume create , diría que esto parece bastante cerca de estar listo para cerrar.

No puede simplemente especificar uid/gid directamente porque esto no es compatible con los montajes de enlace, pero muchos sistemas de archivos que puede usar con las nuevas opciones de montaje pueden funcionar con uid/gid opts.

Creo que el problema aún se resuelve en los casos en los que desea montar una unidad CIFS dentro de su contenedor, sin embargo, ¿tal vez ese debería ser otro boleto?

@ michaeljs1990 Puede hacer esto, pero no por contenedor (a menos que cree volúmenes separados para cada combinación de uid/gid que desee).

@ cpuguy83 , ¿podría aclarar cómo se debe usar docker volume create para evitar este problema?

Acabo de encontrarme con este problema hoy con la ventana acoplable 1.11 y tuve que hacer algunos ajustes dolorosos para convencer a la imagen de la ventana acoplable de que me permitiera escribir en archivos en una unidad montada. Sería muy bueno si nunca más tuviera que hacer eso y mucho menos tratar de explicárselo a alguien más.

No se si es esto lo que preguntas pero...

FROM busybox
RUN mkdir /hello && echo hello > /hello/world && chown -R 1000:1000 /hello

Construya la imagen de arriba nombrada como "prueba"

$ docker volume create --name hello
$ docker run -v hello:/hello test ls -lh /hello

Tanto /hello como /hello/world en el ejemplo anterior serían propiedad de 1000:1000

Veo. Entonces, hice algo similar pero un poco diferente, lo que puede hacer que valga la pena compartirlo. Básicamente, agregué un usuario al Dockerfile que compartió mi UID, GID, nombre de usuario y grupo para el usuario fuera del contenedor. Todos <...> son cosas reemplazadas por valores relevantes.

FROM <some_image>
RUN groupadd -g <my_gid> <my_group> && \
    useradd -u <my_uid> -g <my_gid> <my_user>

Después de esto, uno puede cambiar usando USER o usando su en algún momento posterior (por ejemplo, script de punto de entrada o cuando se usa un shell). Esto me permitió escribir en el volumen montado ya que era el mismo usuario que lo creó. Además, se podría usar chown dentro del contenedor para asegurarse de tener permisos sobre cosas relevantes. Además, instalar sudo es generalmente una decisión inteligente al hacer esto también.

Si bien resuelve el problema, no sé si me encanta, ya que esto debería hacerse para cualquier usuario. Además, codifiqué cosas (¡qué asco!), pero tal vez se podrían usar plantillas para hacer esto un poco más fluido. Me pregunto si esta cuña podría ser absorbida por docker run alguna manera. Si ya hay una mejor manera de hacer esto, estaría muy interesado en saber cuál es.

Hay una opción para mapear los uids/gids de los usuarios del host con los uids/gids de los usuarios del contenedor con --userns-remap . Personalmente no lo he probado. Vea una buena discusión sobre este tema http://stackoverflow.com/questions/35291520/docker-and-userns-remap-how-to-manage-volume-permissions-to-share-data-betwee .

@cpuguy83 :

No puede simplemente especificar uid/gid directamente porque esto no es compatible con los montajes de enlace, pero muchos sistemas de archivos que puede usar con las nuevas opciones de montaje pueden funcionar con uid/gid opts.

¿En qué sistemas de archivos está pensando que pueden aceptar argumentos uid/gid? Sé que FAT puede, pero eso se siente tan extraño como cualquier otra cosa que se proponga en este hilo.

En mi opinión, Docker tiene dos opciones:

  1. Soporte oficial para montar volúmenes como un usuario/grupo específico (usando el nombre de usuario/grupo definido dentro del contenedor, sin requerir que el anfitrión tenga este conocimiento de las partes internas del contenedor).
  2. O... deshacerse de la directiva USER (y las banderas de tiempo de ejecución asociadas).

Ser capaz de ejecutarse como un usuario no root y solo poder montar volúmenes propiedad de root es una característica incorrecta. El uso compartido de uid/gid entre el host y el contenedor es otra característica incorrecta.

Los volúmenes de @mehaase toman posesión de lo que ya está en la ruta del contenedor. Si la ubicación en el contenedor es propiedad de root, entonces el volumen será root. Si la ubicación en el contenedor es propiedad de otra persona, el volumen obtendrá eso.

Algún tipo de solución para esto sería genial. A menos que el contenedor lo espere específicamente, hace que sea _muy_ difícil agregar volúmenes a contenedores estándar como elasticsearch, redis, couchDB y muchos otros sin escribir un Dockerfile personalizado que establezca los permisos. Esto hace que el comando docker run -v o la directiva volume: en docker-compose sean inútiles.

@chrisfosterelli ¿por qué inútil? No creo que sea fuera de lo común establecer la propiedad de los archivos/directorios que espera usar.

@ cpuguy83 Porque no parece ser posible establecer la propiedad sin usar un Dockerfile personalizado que establezca permisos y volúmenes, por lo que creo que no son útiles para definir volúmenes. No estoy vinculando contenedores a mi sistema de archivos host, si eso es relevante.

@chrisfosterelli Pero todos estos Dockerfiles estándar deberían tener los permisos ya establecidos.

Creo que lo que @chrisfosterelli está tratando de decir, @cpuguy83 , (y corríjame si me equivoco @chrisfosterelli) es que ha quedado claro que estas variables (UID, GID, etc.) son dinámicas y deben establecerse en tiempo de ejecución (particularmente wrt a archivos de propiedad interna y de volúmenes montados), pero actualmente no tenemos una forma de hacerlo. La respuesta hasta ahora parece ser que no deberían estar determinados por el tiempo de ejecución, pero eso es ignorar el problema fundamental de usabilidad presentado por tal sugerencia. Nuevamente, si estoy malinterpretando algo de esto, no dude en corregirme.

@jakirkham No debo entender cuál es el problema de usabilidad.
Los archivos están en la imagen, deben tener la propiedad y los permisos necesarios para que se ejecute la aplicación. No tiene nada que ver con el volumen en sí. El volumen solo toma lo que estaba configurado en la imagen.

@ cpuguy83 Investigué un poco más y lo aislé en esto: Digamos que tengo un contenedor de búsqueda elástica que creará un directorio /data al iniciar (si no hay datos presentes), luego use docker run -v /data elasticsearch . El directorio /data pasa a ser propiedad de root:root y el daemon que se ejecuta como elasticsearch dentro del contenedor ahora no podrá iniciarse porque no puede escribir en /data .

Sería ideal si pudiera configurar este volumen para que sea propiedad de elasticsearch sin necesidad de un Dockerfile personalizado... aunque supongo que podría argumentar que este tipo de problema debería resolverse en la imagen ascendente.

@chrisfosterelli se habla en las listas de correo del núcleo de tener un controlador superpuesto que puede cambiar de propietario, pero no hay mucho que podamos hacer sin algo así. Tengo curiosidad, ¿puedes simplemente hacer que todos los archivos en tu mundo de volumen lean y escriban y establezcan umasks apropiadamente para que los archivos nuevos también lo sean? (Aún no lo he probado).

@justincormack Creo que sí, pero creo que eso no funciona cuando espero que el contenedor cree los datos en el volumen (en lugar del host). Entiendo que este es un problema extraño, por lo que actualmente lo estoy solucionando arreglándolo en el propio Dockerfile ascendente en mkdir -p && chmod el directorio.

@chrisfosterelli es por eso que dije configurar el umask, si su umask es 000 (en el contenedor) todos los archivos nuevos se crearán con permisos de 666 o 777 , y si el el punto de montaje es 777 para empezar, ¿eso debería estar bien? Si los permisos son siempre de lectura y escritura mundiales, ¿uid y gid no deberían importar?

@justincormack Sí, eso suena correcto... ¿cómo puedo hacer eso mientras creo un contenedor docker con un volumen no montado en el host?

@chrisfosterelli hmm, esa es una buena pregunta. Me parece que los permisos en un nuevo volumen son los que daría el umask predeterminado, por lo que podría intentar ejecutar el demonio docker con un umask 000 y ver si el volumen se puede escribir en todo el mundo. Tal vez deberíamos tener algunas opciones de permisos en docker volume create .

(podría arreglarlo con un contenedor raíz que hizo chmod y salió también, pero eso es feo)

En crear no es bueno. El problema es que si el contenedor no tiene la ruta, la ruta se crea con la raíz. Podría decirse que esto podría hacerse como cualquiera que sea el usuario pasado.

@ cpuguy83 Creo que tendría más sentido crearlo cuando el usuario pasara con -u, ya que probablemente sería el usuario el que intentaría escribir el volumen de todos modos desde el interior del contenedor, ¿no?

Pude montar como el usuario de mi elección siguiendo los pasos a continuación:

  • Cree el usuario dentro de Docker con el mismo UID/GID que el usuario propietario de los archivos en el host.
  • Cree los puntos de montaje por adelantado y colóquelos para el usuario objetivo en el contenedor

Cita @chrisfosterelli :

Investigué un poco más y lo aislé a esto: supongamos que tengo un contenedor de búsqueda elástica que creará un directorio/datos al iniciar (si no hay datos presentes), luego use docker run -v /data elasticsearch. El directorio /data pasa a ser propiedad de root:root y el daemon que se ejecuta como elasticsearch dentro del contenedor ahora no podrá iniciarse porque no puede escribir en /data.

¡Este es un gran ejemplo! Tengo un ejemplo similar con la imagen de Solr. Solr necesita uno o más "núcleos", cada uno de los cuales es una colección de archivos de configuración relacionados y fragmentos de índice. Cada núcleo se coloca dentro de un directorio con un nombre especificado por el usuario. Por ejemplo, si quiero crear un núcleo llamado products , la ruta sería /opt/solr/server/solr/products . Yo elijo el nombre del núcleo, por lo que el mantenedor de imágenes de Solr no puede crear previamente este directorio en la imagen.

Quiero que se guarden mis datos de índice para poder actualizar mi imagen a un Solr más nuevo sin necesidad de volver a indexar todos mis documentos, pero si monto un volumen en /opt/solr/server/solr/products , entonces es propiedad de root y Solr (ejecutándose como solr ) en realidad no pueden escribir nada en él. El directorio principal /opt/solr/server/solr contiene otros archivos, por lo que tampoco puedo montar un volumen allí. (En la jerga más reciente de Docker, creo que mis volúmenes se denominan "volúmenes con nombre", es decir, volúmenes que no están montados en una ruta específica en el host, pero Docker los administra por completo).

He hablado de esto con el mantenedor de imágenes de Solr y existen algunas soluciones (y él ha realizado algunos cambios en la imagen para ayudar), pero todo es bastante complicado y requiere cambios caso por caso en la imagen ascendente. Tener la característica discutida en este hilo haría que _todas las imágenes_ fueran más extensibles sin necesidad de crear un nuevo Dockerfile.

@ctindel tal vez... si el directorio aún no existe.

@ cpuguy83 Eso es cierto, estoy de acuerdo. Ese fue definitivamente mi caso de uso. No parece tener sentido crear el directorio como raíz si no existe cuando se ha especificado explícitamente una identificación de usuario para ejecutar el contenedor.

@ cpuguy83 solo funciona para el volumen con nombre.

@kamechen ¿Qué funciona?

@ cpuguy83 Cuando usa un volumen con nombre, los archivos se montan bajo el usuario que necesita

@eciuca Bueno.... depende. Si el volumen con nombre estaba vacío, o los datos en el volumen con nombre fueron creados por el mismo usuario que necesitaba.

¿Hubo alguna vez una solución al problema planteado por @andrewmichaelsmith?

Estamos llegando a un problema que se resolvería con esto (creo). Tenemos un recurso compartido de NFS para los directorios de inicio de nuestro desarrollador. Los desarrolladores quieren montar /home/dev/git/project en Docker pero no pueden porque tenemos habilitado Root Squash.

Esto prohíbe que la raíz acceda a /home/dev/git/project, por lo que cuando intento ejecutar el montaje de la ventana acoplable /home/dev/git/project, aparece un error de permiso de lstat denegado.

Creo que es posible solucionar esto usando bindfs .
Usando -v ... de docker para montar el volumen en una ubicación temporal y luego bindfs para montarlo donde sea necesario como otro usuario.

@piccaso , la forma en que entendí @andrewmichaelsmith es que el problema es que el montaje de enlace en el lado del host falla debido a rootquash. Pero bindfs aún podría usarse como una solución alternativa, pero esta vez en el lado del host. Primero, en el host, monta el recurso compartido nfs en una ubicación temporal como un usuario no root usando FUSE, y luego monta esa carpeta temporal en la ventana acoplable con -v ... .

Tenga en cuenta que bindfs (al menos con FUSE) tiene bastante sobrecarga de CPU.

Sí, bindfs es muy indeseable. Es más lento incluso que los sistemas de archivos CoW.
Se está trabajando en el kernel para permitir el cambio de uid/gid en el montaje que puede ayudar.

Se está trabajando en el kernel para permitir el cambio de uid/gid en el montaje que puede ayudar.

Esto probablemente solo ayudará a abordar el caso de uso en el que quiero volver a mapear uid/gid dentro del contenedor. El montaje en sí, tal como lo ejecuta el demonio docker, aún se ejecutaría como root en el host. Tengo entendido que con los montajes de vinculación de Kernel solo se pueden crear como root. No estoy seguro de si hay trabajo para cambiar eso para permitir que los usuarios no root realicen montajes (sé muy poco sobre la forma en que Linux maneja los montajes para juzgar si incluso tiene sentido).

@NikolausDemmel Dudo que eso cambie. La llamada al sistema mount requiere CAP_SYS_ADMIN, que no es algo que se le da a un usuario no root, o incluso algo que le damos al usuario root de un contenedor.

@ cpuguy83 Gracias por la aclaración. Eso significa que montar volúmenes de la ventana acoplable en carpetas de host que son montajes NFS con root-squash no funcionará en el futuro previsible (debido a las limitaciones de la llamada al sistema de montaje como usted dice), excepto por el uso de soluciones como FUSE con bindfs .

Lo sentimos, esto fue un poco OT, ya que OP preguntaba sobre cambiar UID/GID dentro del contenedor. Pero es una especie de la otra cara de la moneda y surgió en la discusión anterior. Solo quería aclarar esa distinción.

Estoy ejecutando Docker para Mac y he montado un volumen, pero parece que no puedo obtener los permisos establecidos para que el servicio web acceda a los archivos. ¿Cómo arreglaría esto? Intenté cambiar las permanentes y establecer el grupo en personal, pero parece que Alpine no tiene un grupo de personal.

Lo siento si este no es el mejor lugar para ponerlo, he estado luchando durante días y no podía pensar en un lugar mejor.

@NikolausDemmel : Estamos tratando de usar Docker para algunos trabajos de bioinformática. Tenemos múltiples sistemas de archivos enormes montados con raíz aplastada a través de NFS. Leemos datos de secuencia enorme (fastq) y luego escribimos un archivo BAM algo más pequeño con las lecturas genómicas alineadas con el almacén de datos. Actualmente, podemos usar la ventana acoplable haciendo la imagen personalizada para crear un usuario dentro del contenedor y usar USUARIO al final para que funcione, pero esto es problemático por un par de razones:

  1. Si queremos usar la imagen de Docker de otra persona, tenemos que reconstruir con un Dockerfile personalizado
  2. O necesitamos crear una imagen acoplable personalizada para cada usuario local, o usamos una única cuenta de "servicio" y no podremos distinguir entre las actividades del usuario en el FS.

¿Pueden Bindfs o userNS dejarnos solucionar esto?

Creo que me encuentro con el mismo problema, mi caso de uso es:
Las imágenes de Docker contienen nuestras herramientas de compilación portátiles para un proyecto determinado, utilizamos el montaje de volumen con rutas relativas, ya sea con algo como docker run -v ./:/src/ image o el equivalente en un archivo docker-compose. Se inicia automáticamente una compilación y se generan nuevos archivos en una subcarpeta en el volumen vinculado.
A veces nos gusta usar esos archivos creados desde el host, pero el hecho de que todavía sean propiedad del usuario en docker, en lugar del usuario del host que ejecutó docker, tiende a complicar las cosas.

¿Estoy haciendo algo particularmente mal aquí?

@labrecque vea mi publicación anterior sobre hacer coincidir la identificación del usuario de la ventana acoplable con la del host. Usé este enfoque y funciona muy bien para nosotros. Básicamente, ejecute HOST_UID=$(id -u) y HOST_GID=$(id -g) y genere un Dockerfile que expanda $HOST_GID y $HOST_UID en los dos comandos siguientes:

RUN groupadd -g $HOST_GID mygroup
RUN useradd -l -u $HOST_UID -g mygroup myuser

Utilice el Dockerfile generado con los ID rellenados para crear su imagen.

@haridsv He hecho algo similar y funciona muy bien en Linux. Pero eso no parece funcionar para mí en Windows: los archivos dentro del montaje aún pertenecen a la raíz.

Resolví esto usando inotifywait . Deberá instalar inotify-tools para ejecutarlo dentro de su imagen acoplable. En cambio, es posible ejecutarlo en su sistema host, pero quería una solución portátil.

RUN export DEBIAN_FRONTEND=noninteractive \
  && apt -y update \
  && apt -y install inotify-tools \
  && inotifywait -m -r /mount -e create --format '%w%f' \
    | while read f; do chown $(stat -c '%u' /mount):$(stat -c '%g' /mount) $f; done

Esto funciona al indicarle a inotifywait que busque cualquier archivo o directorio nuevo creado en el directorio /mount. Cuando nota uno, cambia la propiedad al mismo usuario y grupo que la carpeta /mount. Usé la representación entera de ambos, en caso de que el usuario/grupo host no exista en el contenedor. Dentro del contenedor no importa a quién pertenezca, porque todo se ejecuta como root. Fuera del contenedor, el sistema de archivos del host muestra la misma propiedad que el directorio que se montó en /mount.

Lo diseñé deliberadamente para establecer solo la propiedad de los archivos y directorios recién creados, a fin de preservar la propiedad de los archivos y directorios preexistentes. Es más seguro que arruinar todo eso con una instrucción chown -R cada vez que se monta el sistema de archivos. Si los permisos uniformes funcionan para su proyecto y desea una solución más simple que se ejecute de manera más eficiente, consulte inotify-hookable .

Advertencia: dado que se establecerá una vigilancia de inotify por subdirectorio, es posible que se alcance la cantidad máxima de vigilancias de inotify por usuario. El máximo predeterminado es 8192; se puede aumentar escribiendo en /proc/sys/fs/inotify/max_user_watches.

Hemos utilizado un script del lado del host para chown el volumen que se montó, lo que evita la necesidad de reconstruir la imagen:

#!/bin/bash
set -e

DOCKER_IMAGE=<docker_image>
COMMAND=<internal_command>

DOCKER_USER=docker-user
DOCKER_GROUP=docker-group

HOME_DIR=/work
WORK_DIR="$HOME_DIR/$(basename $PWD)"

PARAMS="$PARAMS -it --rm"
PARAMS="$PARAMS -v $PWD:$WORK_DIR"
PARAMS="$PARAMS -w $WORK_DIR"

USER_ID=$(id -u)
GROUP_ID=$(id -g)

run_docker()
{
  echo \
    groupadd -f -g $GROUP_ID $DOCKER_GROUP '&&' \
    useradd -u $USER_ID -g $DOCKER_GROUP $DOCKER_USER '&&' \
    chown $DOCKER_USER:$DOCKER_GROUP $WORK_DIR '&&' \
    sudo -u $DOCKER_USER HOME=$HOME_DIR $COMMAND
}

if [ -z "$DOCKER_HOST" ]; then
    docker run $PARAMS $DOCKER_IMAGE "$(run_docker) $*"
else
    docker run $PARAMS $DOCKER_IMAGE $COMMAND "$*"
fi

¿Qué pasa con el uso de ACL del sistema de archivos en el directorio del host? De esa manera, puede decirle al sistema de archivos que aplique permisos específicos a los archivos recién creados dentro del directorio. Si configura la ACL a nivel de host, si modifica los datos del contenedor, también sucederá.

@thaJeztah @justincormack @cpuguy83

@kamechen parece tener razón en que los volúmenes con nombre "simplemente funcionan". En el caso de los volúmenes con nombre, los permisos existentes son "contraproducentes" y cambian los permisos de volumen, y yo, personalmente, considero que se trata de un error (n.º 28041).

@thegecko , ¿por qué no lleva más lejos este enfoque y no crea usuarios dentro de un punto de entrada?

Aquí está mi ejemplo, detecta un propietario del directorio montado, crea un usuario con el mismo UID y ejecuta el comando como en este usuario:

Dockerfile

FROM ubuntu

RUN mkdir /project
VOLUME /project

ENV GOSU_VERSION 1.9
RUN set -x \
    && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \
    && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
    && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
    && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
    && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true \
    && apt-get purge -y --auto-remove ca-certificates wget

ADD entrypoint.sh /

ENTRYPOINT ["/entrypoint.sh"]

CMD /project/run.sh

punto de entrada.sh

#!/bin/sh

USER=dockeruser
VOLUME=/project
UID="$(stat -c '%u' $VOLUME)" && \
useradd --uid "$UID" "$USER" && \
ls -l "$VOLUME" && \
exec gosu "$USER" "$@"

correr.sh

#!/bin/sh

echo "Running as \"$(id -nu)\""

Cuando ejecuto sudo docker build -t test . && sudo docker run --rm -v /tmp/docker-test/:/project test:latest sale:

total 12
-rw-r--r-- 1 dockeruser dockeruser 990 Dec 12 10:55 Dockerfile
-rwxr-xr-x 1 dockeruser dockeruser 156 Dec 12 11:03 entrypoint.sh
-rwxr-xr-x 1 dockeruser dockeruser  31 Dec 12 11:01 run.sh
Running as "dockeruser"

¿Alguien ha considerado este tema? Asegurarse de que sus volúmenes tengan el mismo gid y uid que sus contenedores hace que sea más difícil administrar sus contenedores para no usar la raíz. Las mejores prácticas de Docker recomiendan no ejecutar servicios con root si es posible, pero ¿no tiene que configurar el gid y el uid en el host, así como los contenedores, de alguna manera anula la facilidad de uso que hizo popular a Docker?

@AndreasBackx El uso de volúmenes solo funciona suponiendo que la imagen tenga datos en la ruta a la que se monta.
El uso de enlaces utiliza el UID/GID de la ruta del host.

Actualmente no hay forma (ya que no hay soporte del kernel) para asignar o cambiar el UID/GID de un archivo/directorio a otra cosa sin cambiar el original a menos que se use algo como FUSE, que es terriblemente lento.

Pero demos un paso atrás por un momento.
Docker realmente no está haciendo las cosas más difíciles aquí.
UID/GID en el contenedor es lo mismo que UID/GID en el host... incluso si los nombres de usuario/grupo no coinciden, lo que importa aquí es UID/GID.
Al igual que sin la ventana acoplable, debe crear un uid/gid que desee usar para su (s) servicio (s) y usarlo fuera de lo convencional.
Recuerde, no es necesario que exista un uid/gid en /etc/passwd o /etc/group para que se establezca la propiedad del archivo.

@ cpuguy83 gracias por la explicación.

Me encontré con este problema hoy mientras creaba una canalización node , mi UID de usuario del host es 1000 y la imagen node crea un usuario personalizado con ese UID específico , incluso hay un problema al respecto

Usaría el usuario del nodo y seguiría adelante, pero se siente un poco sucio. Realmente comparto lo que escribió @ cpuguy83 sobre "retrocedamos un momento", pero a veces puede convertirse en un problema difícil de resolver.

Acabo de descubrir la opción -o en usermod para permitir IDS duplicados, parece una opción legítima.

RUN usermod -o -u 1000 <user>

No estoy seguro de por qué esto no se ha solucionado de manera razonable.

docker run -it -u 1000:4211 -v /home/web/production/nginx_socks:/app/socks -e SOCKS_PATH=/app/socks --name time_master  time_master

inicia sesión para ver:

drwxr-xr-x    8 geodocr_ geodocr       4096 Jun  4 18:51 .
drwxr-xr-x   57 root     root          4096 Jun  6 21:17 ..
-rwxrwx---    1 geodocr_ geodocr        140 Jun  4 18:49 .env
-rwxrwx--x    1 geodocr_ geodocr         78 Jun  4 18:49 entrypoint.sh
drwxrwxr-x    2 geodocr_ geodocr       4096 Jun  4 18:51 handlers
-rwxrwx---    1 geodocr_ geodocr        242 Jun  4 18:49 requirements.txt
-rwxrwx---    1 geodocr_ geodocr       1270 Jun  4 18:49 server.py
drwxr-xr-x    2 root     root          4096 Jun  6 21:00 socks
drwxr-xr-x   10 geodocr_ geodocr       4096 Jun  4 18:51 utils

El dokefile hace específicamente

RUN adduser  -D -u 1000 $USER 
#
RUN addgroup $GROUP -g 4211 
#
RUN addgroup $USER $GROUP 
RUN mkdir /app/socks
USER $USER  
#

No tiene ningún sentido que este volumen se monte como raíz, cuando no se selecciona el usuario en el contenedor, ni el usuario que ejecuta el comando seleccionado. Podría entender si el comando EJECUTAR se montó como el usuario que ejecuta el comando, o el usuario que posee el directorio, o incluso el usuario que se especifica en el Dockerfile.

Ninguno de estos es root, por lo que montar como root parece ser un error.

También acabo de verificar, crear un volumen y luego montarlo funciona. Así que sigue siendo un error.

@disarticulate Si desea que la ruta del host sea diferente a la raíz, debe cambiar la ruta del host.

No creo que esto se haya mencionado antes, pero este error es particularmente molesto cuando confía en Docker para crear el volumen de host por usted. Docker parece crear siempre el volumen de host con la raíz, incluso cuando el directorio sobre el que se está montando tiene un propietario diferente.

Parecería que lo correcto aquí sería crear el volumen con permisos de propiedad pertenecientes a USER de la imagen.

@jalaziz , ¿qué debería hacer cuando el usuario del contenedor no existe en el host? Uno de los principales beneficios de los contenedores es que no tiene que exponer sus dependencias (incluidos los usuarios) al host.

@taybin Espero que Docker simplemente cree la carpeta con el uid: gid del usuario del contenedor O, si la carpeta existe dentro del contenedor, crearía la carpeta de host con el mismo uid: gid y máscara.

NOTA: No espero que Docker cambie los permisos si la carpeta ya existe en el host.

@taybin Exactamente como lo describió @frol . Solo debe usar el uid:gid del contenedor.

Sin embargo, esto revela mi problema general con el enfoque actual. Tengo que saber el uid que usa el contenedor para permitir escrituras y establecer permisos en los directorios del host en función de ese uid: gid. Si un autor anterior alguna vez cambia el uid, los permisos se romperán. Todo parece muy frágil.

En mi caso, no necesariamente tenía un control explícito sobre qué imagen acoplable se estaba utilizando (no podía simplemente editar un Dockerfile a mi gusto).

Entonces, probé esto:

docker run -it -u $(id -u $USER):$(id -g $USER) -v $(pwd):/src -w /src node:latest npm run build

Lo que crea una carpeta llamada ./built-app . Sin embargo, el propietario todavía era root con permisos estrictos.

Mi solución fue esta:

docker run -it -v $(pwd):/src -w /src node:latest /bin/bash -c "npm run build; chmod -R 777 ./built-app"

Que todavía tiene root propietario, pero permisos relajados. Luego, mi sistema operativo anfitrión (Ubuntu) pudo acceder a ./built-app sin privilegios de sudo.

@ rms1000watt , ¿ha probado el siguiente comando?

docker run -it -v $(pwd):/src -w /src node:latest /bin/bash -c "npm run build; chown -R ${UID}:${GID} ./built-app"

Eso debería funcionar ya que usaría los UID y GID su host directamente en los archivos mismos. Usar chmod -R 777 es generalmente una mala práctica.

@saada ¡Vaya! Buena llamada. Le daré una oportunidad.

Podría lograr mi enfoque leyendo esto y entendiendo cómo funcionan _UID y GID en contenedores Docker_
https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf

Básicamente, hay un solo kernel y un solo grupo compartido de uids y gids, lo que significa que la raíz de su máquina local es la misma que la raíz de su contenedor, ambos comparten el mismo UID


Tengo un servidor apache y quiero compartir mis archivos de aplicaciones web con el contenedor de apache para modificarlo en el host (desarrollo, cambiarlos usando un editor de texto) y ver los resultados mediante un proceso que se ejecuta en el contenedor. A veces, ese proceso, escribo nuevos archivos y, si no cambio el comportamiento predeterminado con los privilegios, el usuario root genera los archivos y mi usuario local ya no puede modificarlos.

Lo que hice fue generar una imagen personalizada agregando esto en mi dockerfile:

RUN adduser -D -u 1002 dianjuar -G www-data
USER dianjuar

Tal vez para hacer que mi docker-compose.yml sea ​​portátil para que cualquiera pueda usarlo es poner algunos parámetros en el proceso de compilación.

Aquí hay un patrón de contenedor para asignar el ID de usuario / ID de grupo en tiempo de ejecución de una manera que sea fácilmente portátil. https://github.com/Graham42/mapped-uid-docker

El camino que seguí:

1- crear el directorio en el servidor host
2- cambie sus permisos al usuario que tiene ID de usuario y ID de grupo = 1000
3- ejecutar docker-compose up
Revisé el contenedor y todo está bien.

Nota: estaba usando un usuario raíz en el servidor host y asumo que si estuviera usando un usuario no raíz que tiene uid = 1000, podría montar el volumen sin preocuparme por el permiso, pero aún no lo he probado. ¿Hay alguien que haya seguido un camino similar?

Problema típico:

  • enjambre docker, por lo que CAPP_ADD no está disponible, bind-mount no es una solución
  • dos contenedores de dos imágenes diferentes comparten el mismo volumen, por lo que diferentes bases de datos de usuarios/grupos en ambos
  • por ejemplo, uno debe tener derechos de acceso www-data (es decir, encriptemos el descargador de certificados)
  • el otro también usa www-data (es decir, nginx)
  • pero un tercero requiere acceso del usuario openldap (es decir, servidor openldap)
  • tan simple chmod ist tampoco es una solución

Eso significa que tengo un servidor web que obtiene certificados SSL para sus dominios de let's encrpt y un servidor OpenLDAP para el mismo dominio, donde quiero reutilizar los certificados.

Hay otras combinaciones que se encuentran exactamente con el mismo problema.

¿Alguna idea de como resolver esto?

¿Cómo resolverías esto sin Docker? Esto no es un Docker específico
problema.

El viernes 12 de enero de 2018 a las 10:24, Marc Wäckerlin [email protected]
escribió:

Problema típico:

  • docker swarm, por lo que CAPP_ADD no está disponible, bind-mount no es un
    solución
  • dos contenedores de dos imágenes diferentes comparten el mismo volumen, entonces
    diferentes bases de datos de usuarios/grupos en ambos
  • por ejemplo, uno debe tener derechos de acceso www-data (es decir, vamos a cifrar
    descargador de certificados)
  • el otro también usa www-data (es decir, nginx)
  • pero un tercero requiere acceso del usuario openldap (es decir, openldap
    servidor)
  • tan simple chmod ist tampoco es una solución

Eso significa que tengo un servidor web que obtiene certificados SSL para sus dominios
de let's encrpt y un servidor OpenLDAP para el mismo dominio, donde quiero
para reutilizar los certificados.

Hay otras combinaciones que se encuentran exactamente con el mismo problema.

¿Alguna idea de como resolver esto?


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/2259#issuecomment-357267193 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AAwxZgyvdCwGGVkUqCxK9nDFw1zxSKjUks5tJ3kXgaJpZM4BGxv9
.

--

  • Brian Goff

Incluso sin enjambre, podría resolverlo en docker: bind-mount.

Es un problema específico de docker-swarm, porque no hay CAP_ADD.

Los montajes de enlace de @mwaeckerlin no se pueden asignar a diferentes ID de usuario.
Pero incluso con swarm puedes enlazar el montaje... ¿por qué se necesita CAP_ADD?

Sin CAP_ADD, el montaje dentro de la ventana acoplable falla.

Pero al escribir mi comentario, acabo de obtener una posible solución, pero desafortunadamente eso requiere cambiar el Dockerfile en ambas imágenes, por lo que no funcionará para la biblioteca u otras imágenes de terceros:

  • cree un grupo con una identificación de grupo común dada explícitamente en todos los Dockerfiles
  • dar derechos al grupo

@mwaeckerlin ¿Por qué necesita montar dentro del contenedor?

Porque no puedo especificar un usuario/grupo con la opción acoplable -v .

La idea especificada anteriormente fue: unir-montar dentro del contenedor, luego chown en el objetivo no debería cambiar la fuente.

@mwaeckerlin Si lo cambia, cambia en todas partes. Este es el quid de la cuestión en este número.
Chowning/Chmoding un archivo/directorio montado en enlace cambia ambos lugares.

Además, no es necesario poder montarlo dentro del contenedor, puede --mount type=bind,source=/foo,target=/bar

Sí, acabo de probarlo fuera de la ventana acoplable, por lo que la idea anterior es incorrecta.

El problema principal, que he visto a menudo en la ventana acoplable, es que los usuarios, los grupos no son idénticos en diferentes imágenes, incluso cuando existe el mismo nombre de usuario o nombre de grupo en ambos, a menudo tienen identificaciones diferentes.

Aquí, algo como esto al menos ayudaría en algunos casos: --mount type=bind,source=/foo,target=/bar,user=me,group=mine

¿Alguna recomendación o mejores prácticas con respecto a este tema: usuario de volumen compartido por diferentes usuarios en diferentes imágenes en Docker Swarm?

  1. No compartir volúmenes
  2. Sincroniza tu uid/gids
  3. Asegúrese de que los permisos sean lo suficientemente permisivos para todos los que comparten
  4. Use montajes de fusibles en el host para vincular diferentes uid/gid para cada contenedor

¿Puedes ampliar el punto 4?
¿Quizás un ejemplo práctico sobre cómo hacerlo?

El viernes 12 de enero de 2018 a las 17:27, Brian Goff, [email protected] escribió:

>

  1. No compartir volúmenes
  2. Sincroniza tu uid/gids
  3. Asegúrese de que los permisos sean lo suficientemente permisivos para todos los que comparten
  4. Use montajes de fusibles en el host para vincular a diferentes uid/gid para cada
    envase


Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/2259#issuecomment-357282169 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AHSjvgjb0BFbJhZ1VWM-pLGfa7tRBvDNks5tJ4VPgaJpZM4BGxv9
.

Usando algo como https://bindfs.org/ , incluso hay al menos un complemento de volumen de Docker que ya lo implementa (https://github.com/lebokus/docker-volume-bindfs es el primer resultado que encontré a través de Google) .

No puedo cambiar el permiso después de montar el volumen, ¿alguien entiende esto?

una solución:
Agregar esto a Dockerfile
RUN echo "if [ -e container_volume_path ]; then sudo chown user_name container_volume_path; fi" >> /home/user_name/.bashrc
La propiedad de container_volume_path se cambia después de montar el volumen.

Ser capaz de mapear uid y gid parece un elemento misterioso que falta en el manejo del volumen de la ventana acoplable. El camino de la menor sorpresa sería incluirlo y las correcciones sugeridas son torpes y más difíciles de descubrir, mientras que no brindan el beneficio de las mejores prácticas:

Re:
1) No compartir volúmenes

  • Bueno, pero irrelevante para la discusión sobre el mapeo de uid/gid
    2) Sincronice su uid/gids
  • Eso es lo que pretende hacer la funcionalidad, pero sin forzar un chown en un Dockerfile
    3) Asegúrese de que los permisos sean lo suficientemente permisivos para todos los que comparten
  • Esto nuevamente se basa en el comportamiento definido en un Dockerfile, cuando podría ser un mapeo simple
    4) Use soportes de fusibles en el host para vincular diferentes uid/gid para cada contenedor
  • Buen consejo, eso también parece un afeitado de yak.

@colbygk

cuando podría ser un simple mapeo

Ese es el problema, no es posible hacer un "mapeo simple" ya que no es compatible con la capa vfs.
Algunos sistemas de archivos brindan la capacidad de mapear la propiedad (por ejemplo, bindfs o nfs), pero actualmente no es posible implementar esto en el caso genérico.

Necesito volúmenes compartidos, por ejemplo, en la siguiente situación:

Certificados compartidos

  • el contenedor 1 es un proxy inverso que maneja let's encrypt para todos los dominios alojados
  • el contenedor 2 es un servidor ldap que también necesita proporcionar el certificado de su dominio

solución: el contenedor de imagen 2 hereda de la misma imagen que el contenedor 1, la imagen base común crea un grupo común, luego ambos contenedores tienen el mismo acceso de grupo

Dockerfile de base común :

RUN groupadd -g 500 ssl-cert

letsencrypt-config.sh en la imagen vamos a cifrar :

chgrp -R ssl-cert /etc/letsencrypt

Dockerfile de mwaeckerlin/reverse-proxy :

RUN usermod -a -G ssl-cert www-data

Dockerfile de mwaeckerlin/openldap :

RUN usermod -a -G ssl-cert openldap

Eso es.

Todo esto ilustra cómo cambiar los permisos de usuario durante el punto de entrada o durante el proceso de compilación para que toda la ventana acoplable se ejecute en un usuario diferente.

Pero tal vez me perdí un punto importante después de buscar en la web durante los últimos 3 días.
Ninguna de las recomendaciones y (soluciones alternativas) anteriores o vinculadas de otro modo funcionará de ninguna manera.

Todos los volúmenes montados en un contenedor siempre son propiedad de root:root dentro del contenedor. Independientemente de si cambio el propietario por adelantado en el host con UID/GID coincidente o no.

No puedo perder la sensación de que estoy siendo un estúpido tratando de hacer algo muy básico, desde mi punto de vista.

  • Windows 10 Pro 1803 (17134.112)
  • Docker para Windows 18.03.1-ce-win65 (17513)
  • Windows WSL con Hyper-V y Ubuntu

Intentando iniciar un contenedor apache2 simple donde la raíz del documento está montada en el host para que pueda desarrollar en el código fuente php mientras lo pruebo inmediatamente en el contenedor docker.

root<strong i="16">@win10</strong>:# docker run --rm -v /c/Users/<MyUser>/Development/www-data:/var/www/html -it httpd:2.4 /bin/bash

Dentro del contenedor docker, el directorio _/var/www/html_ siempre es propiedad de _ root:root_ , por lo que mi aplicación php nunca podrá abrir o escribir con ningún dato dentro de esa carpeta.
Nada funcionó todavía... :(

Para aquellos que buscan una solución razonablemente elegante, consulten lo que sugirió @elquimista aquí . He probado esto y está funcionando muy bien

Hemos estado usando https://github.com/boxboat/fixuid#specify -paths-and-behavior-across-devices con suerte. Además, configura un usuario dentro del contenedor para que coincida con un usuario en el host.

Aquí hay una configuración de ejemplo de la imagen:

$ cat /etc/fixuid/config.yml
user: lion
group: lion
paths:
  - /home/lion
  - /home/lion/.composer/cache
  - /tmp

y para ejecutar:

$ docker run --rm -it --init \
    -u 1000:1000 \
    -v `pwd`:/app \
    -v "$HOME/.composer/cache:/home/lion/.composer/cache" \
    --entrypoint='fixuid' \
    php:7.2-cli \
        /bin/bash

Tenga en cuenta que esto también es una molestia cuando se utilizan sistemas de almacenamiento que no son compatibles con los permisos y la propiedad de Unix. En ese caso, el montaje del almacenamiento debe realizarse de modo que obtenga el uid correcto para su uso dentro del contenedor porque cualquier intento de cortar los archivos simplemente falla. Si hubiera una manera de decirle a Docker que presente los archivos como propiedad de un uid en particular, independientemente de la propiedad fuera del contenedor, eso simplificaría las cosas.

@tlhonmey

Si hubiera una manera de decirle a Docker que presente los archivos como propiedad de un uid en particular

No lo hay, no sin un sistema de archivos personalizado (por ejemplo, como bindfs).

@tlhonmey Sí, pude solucionar el problema de los "sistemas de almacenamiento que no admiten permisos de Unix" con algunos enlaces simbólicos.

Básicamente, montando desde unidades NTFS, pondría las cosas en -v ./HostNtfsStuff:/data/ntfsMount y luego haría un enlace simbólico y chown ese ln -s -T /data/ntfsMount /var/lib/myApp && chown -Rh myApp:myApp /var/lib/myApp/

También puedes probar: su myApp -c 'echo foo > /var/lib/myApp/bar' && cat /data/ntfsMount/bar

Mi uso era que los desarrolladores de Windows pudieran ejecutar contenedores MySQL y persistir en volúmenes montados, pero se aplica a muchas aplicaciones.

Entonces, la solución es administrar manualmente un montón de pares uid:gid y esperar que no entren en conflicto en el host, o en una secuencia de comandos auxiliar, o:

Hay _una_ manera de hacer que funcione, pero debe prepararse con anticipación dentro de su Dockrfile.

RUN mkdir -p /var/lib/redis ; chown -R redis:redis /var/lib/redis
VOLUME ["/var/lib/redis"]
ENTRYPOINT ["usr/bin/redis-server"]
USER redis

(No probé este ejemplo, estoy trabajando en un contenedor de cromo que luego se muestra en un contenedor _separado_ X11 que ...)

Estuve usando la última técnica hasta hoy cuando traté de unir el volumen del contenedor y se rompió. Aparentemente no puedes hacer eso. El volumen se crea como root y luego la aplicación interna no puede escribir en él como usuario. La autocompletación descrita en la documentación de VOLUME tampoco parece funcionar con el montaje de enlace.

Vi esto leyendo Dockerfile Best Practices y el script auxiliar es lo que recomiendan:

#!/usr/bin/env bash
set -e

if [ "$1" = 'postgres' ]; then
    chown -R postgres "$PGDATA"

    if [ -z "$(ls -A "$PGDATA")" ]; then
        gosu postgres initdb
    fi

    exec gosu postgres "$@"
fi

exec "$@"

Entonces, un chown recursivo para asegurarse de que tiene la propiedad en cada inicio, luego ejecute su aplicación como usuario. exec también fuerza el PID 1 para que las señales funcionen. Y si quiero llenar el volumen con algo así como una secuencia de comandos de ayuda para usar fuera del contenedor en los datos resultantes, probablemente también tenga que ir en la secuencia de comandos de ayuda. Sin embargo, me pregunto si hay un impacto en el rendimiento del inicio del contenedor si su aplicación almacena toneladas de archivos en un volumen, especialmente si el almacenamiento no es local.

Parece que podría haber una solución mejor. Tal vez algo así como mapear el contenedor uid y gid al de un nombre de usuario y grupo específicos en el host. ¿Puede la ventana acoplable echar un vistazo al /etc del contenedor y resolver esto tal vez?

No puede mapear uids/gids en el nivel del sistema de archivos, al menos no sin fusible.

No puede mapear uids/gids en el nivel del sistema de archivos, al menos no sin fusible.

Un poco lo que estaba temiendo. ¿Alguna idea de cuál podría ser la penalización de rendimiento si Docker usara un fusible como este?

@mdegans

Entonces, un chown recursivo para asegurarse de tener la propiedad en cada inicio,

No necesita hacer un chown en cada inicio. En su lugar, verifique el propietario del directorio de datos y solo haga el recursivo chown si no es correcto. Como esto:

 [ $(stat -c %U "$PG_DATA") == "postgres" ] || chown -R postgres "$PG_DATA"

Entonces, idealmente, esto sucederá solo en el primer inicio.

Y tenga mucho cuidado al ejecutar un contenedor con un script de punto de entrada de este tipo; si monta (por ejemplo) su directorio de inicio en el contenedor, todos sus archivos se cambiarán a postgres

En un buen diseño de imagen acoplable, el usuario de tiempo de ejecución no es root y, por lo tanto, no puede chown archivos...!

En un buen diseño de imagen acoplable, el usuario de tiempo de ejecución no es root y, por lo tanto, no puede cortar archivos...!

Correcto, pero no debería haber nada que detenga un cambio hacia y desde root que a menudo se requiere... al igual que normalmente no debería estar ejecutando nada como root hasta que lo necesite, pero cuando lo hace, entonces puede hacer una o más de las siguientes:

  • sudo
  • su
  • USER root

Según: https://f1.holisticinfosecforwebdevelopers.com/chap03.html#vps -countermeasures-docker-the-default-user-is-root

En mi humilde opinión, depende del usuario de la imagen de Docker asegurarse de que establece correctamente el permiso en el volumen montado.

Es muy similar a lo que hacíamos tradicionalmente antes de que existieran los contenedores, por ejemplo, cuando quería ejecutar nginx y necesitaba asegurarme de que el usuario correcto poseía el directorio HTML estático. Para saber que necesitaría abrir mi archivo nginx.conf, verifique el usuario de los trabajadores y establezca los permisos correspondientes. En realidad, todo esto se describió en la documentación de nginx.

Esto es solo un problema de permisos de Unix, nada nuevo con Docker aquí. Entonces, quizás la solución a este problema sea una mejor documentación para cada imagen de Docker sobre cuál debería ser la propiedad de los volúmenes montados. No recuerdo el demonio de inicio de nginx asegurándose de que el directorio tuviera la propiedad correcta, simplemente fallaría si no estuviera configurado correctamente.

Sin embargo, esto es cierto porque ahora tenemos usuarios potencialmente definidos dentro del contenedor y no fuera, lo que hace que las cosas se vean diferentes (y no lo son). Pero el UID interno y externo son equivalentes, por lo que la barra de usuario con UID 2000 puede existir dentro de un contenedor y no afuera, pero el UID 2000 aún se puede configurar en archivos y directorios en el exterior. Tenemos que cambiar nuestra forma de pensar en términos de UID/GID en lugar de los nombres descriptivos humanos con los que solíamos tratar.
También hace que las cosas sean potencialmente más difíciles si necesita compartir un volumen entre 2 contenedores escritos por 2 autores diferentes. Es posible que establecer permisos usando el sistema Unix tradicional (de usuario, grupo y otros) no sea suficiente para resolver el problema (sin UID o GID comunes). Admito que desde que uso Docker, estoy haciendo muchos más usos de POSIX ACL. Por lo tanto, puedo asignar 3 permisos de usuarios diferentes al mismo archivo. por ejemplo, un escritor de contenedores con permiso rw, un lector de contenedores con permiso r y un usuario host con permiso r.

Una opción más: el GID común se puede aplicar usando el indicador setgid para directorios compartidos. La máscara de archivo se puede aplicar mediante ACL.

Antes de hacer nada en el contenedor Docker, ejecute:

```
máscara 0000
````

https://en.wikipedia.org/wiki/Umask

Llegué tarde a este hilo para reafirmar lo útil que sería esta función.

Para ser honesto, he estado implementando contenedores durante aproximadamente un año y veo que esto se está convirtiendo en un problema real en todas partes. Proporcionar una solución a este nivel, aquí, parece la única opción sensata.

Tal como está hoy, una cantidad considerable de imágenes de Docker optaron por seguir ejecutando sus puntos de entrada como root para poder arrancar los permisos de directorio y archivo solo para eliminar los privilegios antes de ejecutar el proceso de la aplicación.

Un verdadero problema aparece cuando te das cuenta de que no todo el mundo puede recurrir a esta práctica. Para algunas plataformas populares, como Kubernetes u OpenShift, algunos de estos entornos pueden configurarse para no permitir contenedores privilegiados... por... seguridad. En mi cabeza, no puedo ver cómo una gran institución financiera consideraría adoptar una plataforma de contenedores que procesa información confidencial sin este tipo de restricción.

Las preocupaciones de seguridad planteadas por la práctica _entrypoint-as-root_ han llevado a una gran cantidad de gráficos de timón de Kubernetes a proporcionar initContainers que pueden chown y chmod volúmenes antes de que se inicie el contenedor de la aplicación . Esto puede parecer una buena forma de evitarlo, pero créanme cuando digo esto: no lo es .

Los gráficos de Helm, en particular, están llenos de uids y gids codificados porque es necesario extraerlos en secreto del tiempo de ejecución de la aplicación. Esa información está oculta dentro del contenedor y no está disponible rápidamente durante la implementación.

Si bien hay varias formas de solucionar el problema, continúa plagando las configuraciones de implementación como un _truco para que las cosas funcionen_. El número de implementaciones afectadas por esto está aumentando rápidamente y las técnicas a las que recurren las personas son contrarias a todos los demás beneficios que los contenedores aportan.

Espero que haya una manera de implementar esto como parte de la especificación de OCI para que otras soluciones que dependen de Docker puedan usarlo para brindar una implementación completamente automatizada de manera elegante.

Entonces, la pregunta es: ¿dónde más en Internet desarrollan la especificación OCI común, dónde se debe llevar esta discusión? Suponiendo que esa no sea la mejor manera de incluir esta función en la ventana acoplable (eventualmente, a través de un requisito de cumplimiento para una futura adopción de estándares comúnmente acordada).

Dado que el problema definitivamente nunca va a desaparecer por sí solo, y la solución requiere algunos tipos de cambios muy fundamentales.

initContainers que pueden chown y chmod volúmenes antes de que se inicie el contenedor de la aplicación. Esto puede parecer una buena forma de evitarlo, pero créanme cuando digo esto: no lo es.

FWIW; esta función solo sería necesaria para situaciones en las que los archivos se comparten entre varios espacios de nombres (ya sean archivos (pre)existentes en "el host" o una ubicación de archivo común compartida entre varios contenedores que se ejecutan como diferentes usuarios). En situaciones en las que los archivos se crean previamente en el host, esto se puede mitigar asegurándose de que esos archivos tengan la propiedad y los permisos correctos antes de compartirlos con el contenedor. Efectivamente, eso no es diferente de (por ejemplo) ejecutar nginx en el host y asegurarse de que los archivos en la raíz web tengan los permisos correctos.

Al compartir entre contenedores que se ejecutan como un usuario diferente, ejecute ambos contenedores con el mismo uid (o gid ) y configure los permisos de grupo correctos, de forma similar a cómo funcionaría cuando se ejecutan dos procesos no contenerizados que necesitan tener acceso a los mismos recursos).

algunos de estos entornos pueden estar configurados para no permitir contenedores privilegiados... por... seguridad. En mi cabeza, no puedo ver cómo una gran institución financiera consideraría adoptar una plataforma de contenedores que procesa información confidencial sin este tipo de restricción.

Solo para evitar confusiones; un contenedor que se ejecuta como root no es lo mismo que un contenedor "privilegiado" ( --privileged u opciones, como --cap-add establecido). Los contenedores privilegiados ( --privileged ) son muy inseguros, mientras que un contenedor que se ejecuta como root está completamente contenido y no podrá romperse ; pasar archivos/directorios montados en enlace es perforar agujeros en eso, por lo que _le_ dará acceso a los archivos/directorios que pasa como un montaje de enlace.

Los gráficos de Helm, en particular, están llenos de uids y gids codificados porque es necesario extraerlos en secreto del tiempo de ejecución de la aplicación. Esa información está oculta dentro del contenedor y no está disponible rápidamente durante la implementación.

Me pregunto: si esos uids/gids no se conocen; ¿Cómo sería la UX? (ya que tendría que proporcionar un uid/gid de mapeo para usar para mapear un uid/gid de host a un contenedor-uid/gid (desconocido)?

Entonces, la pregunta es: ¿dónde más en Internet desarrollan la especificación OCI común, dónde se debe llevar esta discusión?

No creo (de un vistazo) que se necesite un cambio en la especificación OCI; esto se puede resolver fuera de la especificación OCI; el principal problema es que actualmente faltan mecanismos para mapear uids/gids en el núcleo (o existen (como shiftfs ), pero no están comúnmente disponibles)

Este es un pentágono clásico del traspaso de traspaso de responsabilidades / alguien más puede o debe resolver este problema. O es el:

  • Usuario
  • La implementación específica de la plataforma Docker/containerización
  • especificación OCI
  • Núcleo
  • sistema de archivos

El problema ya se planteó de manera efectiva: hacer que el usuario haga esto es torpe y menos seguro. Sin embargo, el efecto colateral de que los usuarios hagan hacks por imagen también es importante:

Lo cual es que no puede interoperar y compartir / mezclar imágenes tan fácilmente para trabajar juntas de diferentes usuarios. Así que:

  • Rompe el intercambio comunitario (bastante). Porque diferentes usuarios definen desde el mismo grupo de espacio de nombres global sus uids y gids para sus imágenes desarrolladas individualmente
  • Obliga a los usuarios a desarrollar su propio estándar ad-hoc y esperan que otros sigan una convención que ellos mismos han elegido.
  • Obliga a los usuarios a usar root para todo. Lo cual es ciertamente menos seguro. Porque está eliminando una capa adicional de protección de escalada privilegiada que de otro modo habría tenido. Y hace que las vulnerabilidades de ruptura del contenedor sean mucho más fáciles de explotar, ya que, para empezar, el usuario ya está root dentro del contenedor. Por no hablar de poder ejecutar otros servicios dentro del mismo contenedor, que también es otra forma de ir de lado, antes de subir.

Entonces es un intercambio. Los anteriores son las compensaciones actuales. Mientras que tendría un conjunto diferente de compensaciones para pasar la responsabilidad a otra parte, a una o más de las otras entidades enumeradas anteriormente.

Por cierto, en lo que respecta a echar un vistazo más de cerca a una solución basada en un sistema de archivos, he encontrado este comentario "potencialmente podría ser útil" de los enlaces de araña:

https://github.com/docker/compose/issues/3270#issuecomment-365644540

Que tiene varias referencias diferentes a esta misma característica general (a otros proyectos/lugares), incluido un sistema de archivos distribuido (conocido como 'Lustre') y otro problema relacionado con ZFS. Bueno, da la casualidad de que estoy usando ZFS aquí mismo.

Luego también encontré otra copia del mismo error en ubuntu / launchpad. Haciendo referencia al mismo problema ZOL #4177,

https://bugs.launchpad.net/ubuntu/+source/zfs-linux/+bug/1567558

Lo que dice que el error en cuestión se ha corregido en la versión 0.6.5.7+ SO de zfs. ¿Significa esto que potencialmente podemos usar zfs y ACL, como una especie de almacén de respaldo para reasignar uids y gids de alguna manera? Bueno, esto no es algo de lo que haya oído hablar antes.

Oh, tal vez esta solución solo funcione para contenedores LXC. Porque también decía en sus comentarios allí (el líder del proyecto LXC), "usamos ayudantes setuid (newuidmap y newgidmap)" que luego pueden "configurar un mapa uid y gid". Entonces, presumiblemente, también hay algún mecanismo necesario en LXC, de lo contrario, ¿no se puede utilizar la parte zfs acls? O tal vez me equivoque. No estoy completamente seguro de seguir esto hasta el final.

Otro enlace interesante, esta vez sobre shiftfs , y una discusión sobre la posibilidad de absorber sus funciones en superposiciones. Que, por supuesto, es un sistema de archivos subyacente que Docker ya usa.

Sin embargo, ¿qué sucede si la función de reasignación se implementa en overlayfs , pero quiero usar el controlador de almacenamiento zfs en su lugar para mi sistema de archivos subyacente? Entonces, ¿debo quedarme fuera de la capacidad de reasignar uids/gids, si se implementa por sistema de archivos? ¿O podemos tener ambos implementados por separado? Lo siento, no tengo claro si el demonio Docker debe estar al tanto de tales reasignaciones y proporcionar una API y banderas comunes (para pasar a la capa de controladores fs). O si, en cambio, realizáramos dicha reasignación manualmente nosotros mismos en el lado del host (en el sistema de archivos, fuera de la ventana acoplable). Ese aspecto también me queda un poco confuso.

[EDITAR] Vaya, ¡olvidé incluir el enlace! Aquí está

https://lists.linuxfoundation.org/pipermail/containers/2018-June/039172.html

Este problema se trata de volúmenes / montajes de enlace, por lo que se separa del sistema de archivos del contenedor

Lo usaríamos demasiado con un cambio de uid/gid para el montaje de enlace si la superposición incorporara características de shiftfs, pero tendríamos que recurrir a otra cosa (o nada) en sistemas no compatibles.

Podman es un reemplazo directo de Docker sin raíz https://www.youtube.com/watch?v=N0hSn5EwW8w https://podman.io/ . Con podman, la raíz no se usa, por lo que el permiso del usuario se maneja correctamente. Nuestro equipo cambió a Podman debido a este problema y funcionó muy bien.

Esto no tiene sentido.
Se aplican los mismos problemas.
Tenga en cuenta que docker también tiene un modo sin raíz.

Puede probar Podman con los siguientes comandos. Podman no tiene un demonio separado a diferencia de Docker, y todo se ejecuta bajo el usuario que ejecuta los comandos podman . Entonces, los archivos creados dentro de podman son propiedad del usuario que ejecutó el comando podman run ... .

kkimdev<strong i="8">@ubuntu</strong>:~$ mkdir podman_test
kkimdev<strong i="9">@ubuntu</strong>:~$ ls -agh podman_test
total 8.0K
drwxrwxr-x 2 kkimdev 4.0K Jun 27 04:23 .
drwxr-xr-x 8 kkimdev 4.0K Jun 27 04:23 ..

kkimdev<strong i="10">@ubuntu</strong>:~$ podman run --rm -it -v ~/podman_test:/podman_test alpine
/ # cd /podman_test/
/podman_test # touch test_file
/podman_test # ls -agh
total 8K
drwxrwxr-x    2 root        4.0K Jun 27 02:24 .
drwxr-xr-x   20 root        4.0K Jun 27 02:24 ..
-rw-r--r--    1 root           0 Jun 27 02:24 test_file

/podman_test #

kkimdev<strong i="11">@ubuntu</strong>:~$ ls -agh podman_test/
total 8.0K
drwxrwxr-x 2 kkimdev 4.0K Jun 27 04:24 .
drwxr-xr-x 8 kkimdev 4.0K Jun 27 04:23 ..
-rw-r--r-- 1 kkimdev    0 Jun 27 04:24 test_file

Este no es el lugar apropiado para anunciar podman . Si hay detalles técnicos específicos sobre cómo funciona que pueden ayudar a resolver este problema, sería relevante discutirlos, especialmente como posibles soluciones al problema que está buscando. estoy comentando actualmente. Hasta ahora, eso no es lo que ha sido, así que lleve esta discusión a otra parte.

El hecho de que podman tenga una arquitectura muy diferente a la de Docker, lo que hace que este problema sea menos grave/doloroso, no permite mágicamente que Docker cambie por completo la forma en que funciona solo para resolver este problema. Puedo asegurarles que hay muchas razones por las que Docker está estructurado de la forma en que lo está y, francamente, es de mala fe ignorar toda esa historia.

@tianon Sí, absolutamente, hay pros y contras para ambos enfoques. Mencioné podman solo porque ejecutar un contenedor con podman con el usuario de destino resuelve específicamente este problema técnico, que es, "montar volumen como usuario que no sea root".

Eche un vistazo al permiso de "test_file" creado en mi comentario anterior. Primero monta el directorio "~/podman_test" y escribe el archivo "test_file" dentro del contenedor podman. Luego, una vez que el usuario sale del contenedor, puede ver que el archivo es propiedad de "kkimdev", no de root.

El problema es que su sugerencia para solucionar un problema con Docker es que equivale a "no usar Docker", lo que no es muy constructivo en el rastreador de problemas para Docker.

Sí, podman está diseñado de manera diferente, lo que hace que este problema sea discutible para esa herramienta; eso está bien, pero está totalmente fuera de tema aquí. Rootless tiene diferentes compensaciones, algunas de las cuales están bien para algunas personas, otras no. Está mejorando con el tiempo (y en su mayoría mejoras del kernel), pero no es una solución genérica para todos aquí.

Esto requiere modificaciones del kernel o una corrección para una solución genérica como se explicó en detalle anteriormente (y como @cpuguy83 y otros han estado trabajando para tratar de ayudar a resolver este problema de una manera genérica).

Docker tenía este problema en particular abierto desde 2013 y casi seis años después, no hay una mejora fácil a la vista. Podman fue diseñado para obtener compatibilidad con Docker, pero también para resolver las fallas de diseño de Docker (incluida la ejecución como un usuario sin privilegios que no requerirá un demonio Docker de superusuario).

Si los usuarios pueden dar a otros un consejo sobre un problema de GitHub, no hay problema. Esta es una comunidad. Siéntete libre de recomendar cualquier cosa que pueda ser útil.

Puedo asegurarle que hay muchas razones por las que Docker está estructurado de la forma en que lo está.

También lo es grep . Pero si alguien necesita buscar más rápido, aún recomendaría ripgrep . Incluso en el rastreador de problemas grep . No debería importar de quién es el rastreador de problemas, siempre que resuelva el problema de los usuarios y los haga felices.

Si Podman no te funciona: ¡bien! Pero si ayuda a otros porque solo tienen que reemplazar docker con podman en su infraestructura: déjelos que lo hagan.

El principal argumento de Podman es que no ejecuta un demonio y ese es mi principal argumento en contra. ¿Cómo recupero mi contenedor después de un reinicio? No lo haré a mano y todo lo demás es solo un mal diseño. Además, no quiero que mi contenedor docker sea propiedad de un usuario sino del sistema y esto significa root.
Podman tiene sentido si eres la única persona que lo usa.

Y para solucionar su problema: ¡construya un contenedor con COPY --chown ...:... !

Además, Docker no tiene tales problemas y puede controlar de forma remota los servidores de Docker, lo que también es importante para mí.

También hay herramientas para generar pods a partir de contenedores en ejecución, que no recomendaré porque debe construirlos desde cero de una manera limpia.

Supongo que deberíamos volver al tema ahora: en mi humilde opinión, el primer consejo estuvo bien, pero todo lo demás simplemente hace estallar este problema y no resolverá nada.


@SuperSandro2000 , puede hacer clic aquí para ver la respuesta a sus declaraciones.

¿Cómo recupero mi contenedor después de un reinicio? No lo haré a mano y todo lo demás es solo un mal diseño.

Bueno, Podman tiene integración nativa con systemd (como _casi_ todo lo demás en casi todas las distribuciones GNU Linux modernas). Por lo tanto, no tiene que mantener 'dos' sistemas de arranque (como primero tener systemd para iniciar el demonio Docker que luego tiene que hacer otra ronda de inicio de contenedores en una configuración diferente). Entonces, con Podman puede controlar todo con systemd (es decir: el sistema que probablemente ya tenga instalado y funcionando de todos modos).

Además, no quiero que mi contenedor docker sea propiedad de un usuario sino del sistema y esto significa root.

Está totalmente bien si no lo quieres. Todavía puede ejecutar Podman como superusuario, pero ya no tiene que hacerlo. En general, se considera una mala idea y aumenta la superficie de ataque porque si alguien puede explotar su demonio Docker, tiene control sobre _todo_ en el sistema.

Podman tiene sentido si eres la única persona que lo usa.

Esta afirmación no tiene ningún sentido. Podman le permite distribuirse en un solo sistema, lo cual es una característica que tiene sentido especialmente si tiene muchas personas trabajando en el mismo sistema.

Y para solucionar su problema: ¡construya un contenedor con COPY --chown ...:... !

En mi humilde opinión, el problema aquí es _montar_ un volumen para un contenedor en _runtime_. Lo cual tiene poco que ver con la construcción de una imagen.

Además, Docker no tiene tales problemas y puede controlar de forma remota los servidores de Docker, lo que también es importante para mí.

Es gracioso que menciones exactamente el blog que tiene esta publicación . Sin embargo, no tengo mucha experiencia con los detalles de red de ambas implementaciones, pero según entendí, podman comienza con las reglas de red mínimas posibles y los usuarios sin privilegios no pueden configurar pares veth

Para que quede claro, debería poder obtener el mismo efecto con la ventana acoplable sin raíz que con el podman.
Esto se debe a que dockerd se ejecuta como su usuario y la raíz en el contenedor está asignada a su UID.

Esto tiene inconvenientes y, por supuesto, no funciona cuando se comparte un demonio con varios usuarios.
https://get.docker.com/rootless

El 27 de junio de 2019, a las 7:52 a. m., Alexander Adam [email protected] escribió:

Supongo que deberíamos volver al tema ahora: en mi humilde opinión, el primer consejo estuvo bien, pero todo lo demás simplemente hace estallar este problema y no resolverá nada.

@SuperSandro2000 https://github.com/SuperSandro2000 , sin embargo, puede hacer clic aquí para obtener la respuesta a sus declaraciones.
https://podman.io/blogs/2018/09/13/systemd.html https://osric.com/chris/accidental-developer/2018/12/docker-versus-podman-and-iptables/ https:/ /osric.com/chris/accidental-developer/2018/12/using-docker-to-get-root-access/

Estás recibiendo esto porque te mencionaron.
Responder a este correo electrónico directamente, visualizarla en GitHub https://github.com/moby/moby/issues/2259?email_source=notifications&email_token=AAGDCZXX2UQCG7LUVH57V6LP4TH2DA5CNFSM4AI3DP62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYXL2XI#issuecomment-506379613 , o silenciar el hilo https://github.com/notifications/ cancelar suscripción-auth/AAGDCZX437HJP4M6XG3SEY3P4TH2DANCNFSM4AI3DP6Q .

@alexanderadam

En mi humilde opinión, el problema aquí es montar un volumen para un contenedor en tiempo de ejecución. Lo cual tiene poco que ver con la construcción de una imagen.

Mi solución fue no montar el directorio, sino hornearlo en el contenedor si es posible.

Quiero decir, podman suena bien, pero no cambiaré porque por ahora no veo ninguna ventaja para mí. Gracias por la explicación de todos modos.

podman sufre el mismo problema si Apache dentro del contenedor se ejecuta con el usuario www . https://github.com/containers/libpod/issues/3990

La solución podría ser mapear el usuario www del contenedor al UID en el host si no hay un usuario root dentro del contenedor. No sé si eso es posible.

Si desea ejecutar con --read-only (para hacer lo mismo que la política de Kubernetes readOnlyRootFilesystem ), es posible hacer lo siguiente. Se basa en la solución alternativa que @jpetazzo estaba sugiriendo:

  • Mi imagen acoplable crea y usa un usuario con uid=1001 y gid=1001
  • Por separado, cree un volumen docker
  • Chow el uid: gid a 1001
  • Monte esa imagen cuando ejecute la aplicación.

archivo acoplable:

FROM ubuntu

RUN groupadd -g 1001 appgroup && \
    useradd -u 1001 -g appgroup appuser

USER appuser

Entonces:

$ docker build . -t test
$ docker volume create somedir
$ docker run -v somedir:/some_dir alpine chown -R 1001:1001 /some_dir

Ahora, al ejecutar la imagen de la ventana acoplable y montar el volumen, /some_dir pertenece al usuario que quiero.

$ docker run -it --read-only -v somedir:/some_dir test ls -lrt

...
dr-xr-xr-x  13 root    root        0 Nov  4 15:22 sys
drwxr-xr-x   2 appuser appgroup 4096 Nov  5 09:45 some_dir
drwxr-xr-x   1 root    root     4096 Nov  5 09:45 etc
...

$ docker run -it --read-only -v somedir:/some_dir test touch /some_dir/hello
$ docker run -it --read-only -v somedir:/some_dir test ls -lrt /some_dir

-rw-r--r-- 1 appuser appgroup 0 Nov  5 09:52 hello

Señalaré nuevamente, porque se pierde fácilmente en el hilo, que un enlace simbólico cortado probablemente funcionará para la mayoría de los escenarios. La desventaja es que necesita alguna forma de configurarlo, lo que a menudo significa reemplazar el punto de entrada con un script que luego ejecuta el comando original.

https://github.com/moby/moby/issues/2259#issuecomment-466094263

+1

Creo que este es hasta ahora el problema más molesto que tengo con la ventana acoplable y ver cuánto tiempo ya está abierto sugiere que este no es el caso para muchos otros.

No es un problema si conoce la solución. Mis casos:

  • El anfitrión es Linux

    • uid en el contenedor == uid deseado en el host; no se necesita ninguna solución alternativa
    • uid en el contenedor! = uid deseado en el host: simplemente ejecute un par de comandos setfacl y otorgue acceso a rw tanto para el usuario del host como para el usuario del contenedor
  • El host es MacOS: todo funciona de forma inmediata para la aplicación Docker oficial.

simplemente ejecute un par de comandos setfacl y otorgue acceso a rw tanto para el usuario del host como para el usuario del contenedor

Esto es un problema. No quiero ejecutar un par de comandos setfacl para cada imagen acoplable y detectar el sistema operativo.

En realidad, esto también es un gran problema de seguridad.

Escenario de ejemplo:

  • host1 tiene docker instalado
  • host1 tiene un servicio múltiple que se ejecuta en contenedores docker, todos los cuales son rutas locales de montaje en /docker/my-service-01|02|03|etc
  • cada contenedor fue construido por un proveedor diferente y cada uno sigue su propia política uid y guid , por lo que debe chown -R uid.gid /docker/my-service-01... consecuencia.

Resultado:

  • En algún momento, los usuarios normales o de servicio creados en host tendrán acceso completo a /docker/my-service-01|02|03|etc lo cual no es intencionado ni deseado.
  • Si desea montar un volumen como "solo lectura" en dos contenedores de diferentes proveedores, fallará ya que los uid.gid no coincidirán con los requeridos y no podrá chown porque cada contenedor tiene su propia política uid.gid y son diferentes :)

Sí, discutimos este problema en detalle anteriormente y el hecho clave que se comunicó (en ese momento) fue que el kernel de Linux no tenía un mecanismo de soporte subyacente para proporcionar uids y gids reasignables. Por lo tanto, sería necesario agregarlo al kernel para que este proyecto (moby / docker) implemente esta funcionalidad altamente deseable. De lo contrario, ya habríamos obtenido esta característica hace algún tiempo. Cuando se miró por primera vez.

Entonces, la forma más productiva de continuar esta discusión (hoy) sería: Ver si algo de esa situación ha cambiado desde entonces. Busque un comentario técnico de los desarrolladores de la línea principal del kernel de Linux en vger.org. Busque conjuntos de parches anteriores/solicitudes de combinación en el núcleo para esta característica faltante subyacente. etc

Con la esperanza de una mejor comprensión de lo que ha estado sucediendo en ese nivel inferior. ¿Cuál fue el escollo? ¿Fue un problema de rendimiento? ¿Fue una objeción en cuanto al modelo de seguridad/debilitamiento? ¿Todavía está sobre la mesa o en una hoja de ruta futura, pero solo tiene sentido después de que se puedan implementar otras características B y C? Todo este desarrollo del núcleo continúa en otros lugares. En otros canales.

@DXist El hecho de que esto funcione mágicamente en OSX y no en Linux es sorprendente y un problema en sí mismo.

Según el último comentario de @dreamcat4 , ¿alguien ha hecho un nuevo intento para ver cuál es el estado de esto? ¿Tenemos soporte en el Kernel para uids y gids reasignables ahora? ¿Cuál es el estado general aquí?

He usado espacios de nombres de usuario de Linux para resolver perfectamente este problema. Funciona exactamente igual (AFAICT) que las otras plataformas (el contenedor ve el volumen montado en enlace como raíz, el host lo ve como el usuario que ejecuta la ventana acoplable).

La guía está aquí: https://www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/

@patrobinson +1

¿Fue útil esta página
0 / 5 - 0 calificaciones