Moby: Hacer uid y gid configurables para volúmenes compartidos

Creado en 23 jul. 2014  ·  141Comentarios  ·  Fuente: moby/moby

Proporcione una opción para configurar la propiedad de los volúmenes compartidos.

Por ejemplo, mi caso de uso actual es tener logstash-forwarder ejecutándose dentro de un contenedor, que tiene / var / lib / docker compartido de solo lectura como volumen del host.

Dado que / var / lib / docker está configurado en 0700 root: root en el host, no puedo acceder al volumen como usuario no root.

Lo que me gustaría tener es algo parecido a NFS, donde uno puede mapear uid y gid desde el host a usuarios y grupos en el cliente.

Es decir, docker run -v / var / lib / docker: / var / lib / docker: ro : $ user: $ group haría que el volumen esté disponible en el contenedor como de solo lectura, perteneciente a $ user: $ group.

kinfeature

Comentario más útil

Realmente necesitamos una solución multiplataforma (no gosu) para mapear uid / gid. Este problema por sí solo causa enormes daños en la forma en que los novatos perciben la ventana acoplable.

Todos 141 comentarios

No sé _cómo_ implementaron esto, y si existe una característica comparable en Linux, pero en OS X, existe una característica para 'ignorar la propiedad' en un volumen. Efectivamente, esto hará que _cualquier_ usuario vea los archivos / directorios como si fuera el propietario.

Aunque esto no servirá en todos los casos, puede ser una buena adición

gh # 5910 maneja esto desde el lado de SELinux.

enlace: # 5910;)

El cambio de SELinux en realidad está cambiando las etiquetas del contenido. Potencialmente, podría hacer el cambio en el host. No conozco otra forma de hacer esto para UID / GID. Pero haciendo un chown -R $ UID: $ GID en el punto de montaje.

O puede agregar este tipo de acceso mediante ACL. Pero creo que deberá cambiar todos los INODE en el punto de montaje.

También necesito esta función.

Por ejemplo, quiero crear un contenedor web y adjuntarle volúmenes con sitios web y configuraciones, de modo que el contenedor sea completamente universal para cualquier número de sitios web.

Sin embargo, necesito acceso a git para enviar código al repositorio del sitio web. Como quiero que mis aplicaciones estén aisladas, quiero que cada directorio del sitio web sea propiedad de un usuario / grupo separado, y sería genial si los archivos escritos por el contenedor Docker en el volumen fueran propiedad de ese usuario / grupo separado.

+1 para esta función.
No entiendo cómo pueden funcionar los volúmenes de lectura / escritura sin él. Esperar que el guid / uid sea el mismo en la imagen y el host es un requisito estricto incompatible con los principios de aislamiento de Docker.

Personalmente estoy trabajando en esto con comandos useradd / groupadd feos y lentos para mis herramientas de desarrollo Dockerized: https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/bin-docker/nspire-docker

Podría estar completamente perdiendo el punto. Pero estaba luchando con un problema similar en el que quiero asegurarme de que el usuario http tenga permisos de escritura en / var / log, que es un volumen y probablemente provenga del host con root: root como propietario.

Lo resolví estableciendo un punto de entrada que garantiza que los directorios de registro se creen y tengan los permisos correctos. Supongo que esto funciona porque el script del punto de entrada se ejecuta como root.

(comentario eliminado - pestaña incorrecta, lo siento)

Pirateé esto en Ubuntu fuera de Docker. Instale el paquete bindfs y vincule el directorio con el contenido del volumen a otra ruta mientras asigna UID y GID a los que se usan dentro del contenedor:

sudo bindfs -u UID -g GID oldpath newpath

Luego use newpath como volumen de la ventana acoplable. Oldpath todavía muestra la propiedad correcta para el host, newpath para el invitado.

@jjv el problema es que bindfs es REALMENTE REALMENTE lento.

@ cpuguy83 sí, está lejos de ser óptimo, pero tal vez ayude a alguien en una situación similar. Esto fue para que todo funcionara dentro de una máquina virtual de desarrollo (vmhgfs no permite configurar UID / GID) mientras que en producción, el UID y GID aún deben coincidir entre el host y el invitado ...

En realidad, sería bueno si se usara un tipo de funcionalidad bindfs cuando Docker implementa esto, asumiendo que no causa demasiado impacto en el rendimiento. De esa manera, no tendrá que asegurarse de que el contenedor se esté ejecutando como el usuario correcto. También debería ser posible utilizar nombres lógicos en lugar del literal uid / gid.

@jsternberg Es un éxito de rendimiento

+1

para los casos de uso de desarrollo local, creo que Docker definitivamente necesita esta característica. Y en tal caso, quiero que esta función sea compatible con Windows y OSX.

Sin embargo, Vagrant parece apoyar esto al asignar el UID / PID del usuario del host al usuario vagabundo. Pero para el propósito de desarrollo, realmente quiero usar Docker en lugar de Vagrant, ya que es mucho más liviano que Vagrant para ejecutar aplicaciones de múltiples hosts.

Por favor, dígame qué me estoy perdiendo aquí (no tengo ninguna experiencia con Go), pero ¿la función Go Mount () no acepta banderas? ¿No podríamos permitir un comando como
-v host/folder:container/folder -mount-as user:group
¿No podría simplemente obtener el uid / gid con búsqueda (https://golang.org/src/os/user/lookup_unix.go)
y luego pasarlos (uid = 1, gid = 1) como banderas en Mount ()? (https://golang.org/src/syscall/syscall_linux.go?s=19154:19249#L754)

@krisgraham bind mounts no admite la configuración de uid / gid de esa manera.

Además, separar la opción -v de la opción --mount-as genera confusión cuando hay varias opciones -v

¿Cuál es una buena solución para esto? Me encantaría usar Docker para el desarrollo activo, y no tener un volumen montado de algún tipo no es realmente una opción, ya que tendría que reconstruir cada vez que hago un cambio en mi código.

La razón por la que quiero usar Docker para el desarrollo activo es para que sea coherente con mi entorno de producción.

@berfarah Uso
Rara vez ocurre el caso en el que necesito perder el tiempo con las permanentes.
Si está utilizando boot2docker en OSX, asegúrese de que su directorio de trabajo se encuentre dentro de / Users y debería estar bien.

@ cpuguy83 Gracias por la rápida respuesta. Tengo problemas de permisos con un entorno de rieles donde los registros no se pueden escribir y ocasionalmente hay puntos de falla debido a los permisos. Esto se debe a que mis servicios tienen un UID diferente al de los archivos.

@berfarah Mi solución es escribir mis archivos docker de modo que los usuarios / grupos de contenedores que poseen el código tengan el mismo UID / GUID que mi usuario de host. Por ejemplo, dado que mi UID de usuario de host es 1000:

RUN \
    groupadd code_executor_group && \
    useradd code_executor_user -g code_executor_group -u 1000

@berfarah ¿Tiene registros para stdout / stderr para RAILS_ENV = desarrollo?

@ cpuguy83 Este problema no afecta a OSX; thaJeztah comentó el 24 de julio de 2014:

en OS X, existe una función para 'ignorar la propiedad' en un volumen. Efectivamente, esto hará que cualquier usuario vea los archivos / directorios como si fuera el propietario.

@ncjones en realidad, lo mismo se aplica a OS X. Los "volúmenes" de los que estaba hablando allí, son los discos duros / particiones (volúmenes) usados ​​en OS X mismo. Dudo que eso marque la diferencia para trabajar con Boot2Docker, pero no estoy seguro.

Mi comentario estaba destinado a informar si algo _similar_ era posible en Linux (por lo tanto, dentro de la máquina virtual Boot2Docker)

Perdón por la confusión allí.

@ryneeverett Gracias, eso es útil. ¿Luego acaba modificando los permisos a 775 desde 755 y 664 desde 644 respectivamente donde lo necesita? editar: ¡Habilidades de lectura!

@ cpuguy83 ¡Gracias! Eso parece una solución más limitante que la solución de @ryneeverett , ya que no es algo que pueda simplemente llevar a cabo en todos los proyectos.

@berfarah Me alegro de que te haya resultado útil. Sí, solo me aseguro de que mis archivos de host tengan los permisos correctos y que Docker los conserve en los volúmenes.

+1

Esto es algo que sería extremadamente útil para volúmenes compartidos a través de la ventana acoplable y aborda un problema de seguridad que tengo:

  • Volúmenes compartidos donde el contenedor uid y gid se asignan accidentalmente a un usuario no root privilegiado en el host. (por ejemplo, los archivos creados por el contenedor en el host se asignan a un usuario que puede sudo sin passwd, acceder a contenido restringido, etc.)

Arreglar esto sería muy conveniente para las personas empresariales que ejecutan una tonelada de contenedores con Apache o algún middleware y comparten los volúmenes de registro y / o varios directorios de carga / contenido. Personalmente, también he tenido algunos dolores de cabeza con estos permisos al contener aplicaciones de usuario final en Linux (como syncomm / spotify). Muchas de las soluciones alternativas actuales son en sí mismas problemáticas. En última instancia, esto debe solucionarse dentro de la ventana acoplable. En especial, no me siento cómodo ejecutando scripts de shell raíz como punto de entrada, particularmente cuando este problema resalta cómo el uid / gid 0: 0 en el contenedor se asignará a la raíz en mi host. Me gusta la propuesta inicial "docker run -v / var / lib / docker: / var / lib / docker: ro : $ user: $ group".

@syncomm Tomaría el enfoque exactamente opuesto.
Docker no puede hacer suposiciones sobre la propiedad de sus datos.

El enfoque que resalta en la parte inferior de su comentario sería factible si mapeáramos automáticamente estos archivos reales a un fs basado en fusibles donde podemos cambiar uids / gids ... y esto incurriría en un impacto significativo en el rendimiento.

Y pronto uid 0 en el contenedor no será uid 0 en el host ... lo que también hace que la propiedad del archivo sea aún más complicada.

¿Es esto un duplicado de # 2259?

@ cpuguy83 Gracias por los comentarios, aunque no estoy seguro de qué quiere decir exactamente con el enfoque opuesto. ¿Nube, explicas? Estoy de acuerdo en que la propiedad de los datos no debería ser asumida por la ventana acoplable, pero creo que proporcionar un mapeo consistente desde el contenedor al host sin duda hace que el trabajo de vigilancia de estos datos sea mucho más fácil para los consumidores de la ventana acoplable.

Estoy de acuerdo en que, al igual que la solución alternativa de bindf, convertirlo en una envoltura de fusibles supondría una gran sobrecarga. Sin embargo, tiene que haber una salida a este enigma sin grandes penalizaciones. Esencialmente, el contenedor se está comportando correctamente (como si fuera una máquina única separada del host), y cuando montamos el directorio de un host como un volumen, está viendo (correctamente) el sistema de archivos POSIX allí, los permisos y todo. Desafortunadamente, eso hace que sea realmente difícil compartir datos entre los dos "hosts" de manera consistente. Cosas como nfs, cifs, etc. se utilizan para esto y son compatibles con el mapeo de uid y gid; creo que podría haber un paralelo aquí para resolver el problema. Honestamente, necesito profundizar más en el repositorio para averiguar dónde está sucediendo esto en el código y comprenderlo mejor.

¿Cuándo desaparecerán los cambios que mencionaste en la propiedad del archivo? El uid 0 NO es el mismo para el contenedor y el host en realidad me haría sentir mucho más cómodo haciendo un punto de entrada de un script de shell raíz. Entonces es solo una cuestión de realizar la solución sugerida de pasar el uid / gid correcto como un env y hacer un adduser al iniciar el contenedor.

@syncomm Desafortunadamente, no también de mi conocimiento, no sin envolverlos en algún otro tipo de sistema de archivos que se pueda montar con la configuración uid / gid.

En última instancia, esto parece algo que requiere soporte del kernel para la reasignación bidireccional completa de UID y GID, y ni siquiera parece fácil de administrar.

Para escenarios no sensibles al rendimiento, tal vez se pueda hacer algo usando FUSE.

Todavía +1 para casos de uso de desarrollo, ya que termino con archivos de propiedad raíz en mi hogar.

Para mi caso de uso, sería suficiente si la ventana acoplable pudiera simplemente aplicar la etiqueta uid / gid y selinux personalizada al volumen del host cuando lo crea, dejando el permiso y las etiquetas solo si el directorio ya existe. Actualmente soluciono eso al tener un punto de entrada separado para la imagen que se ejecuta como raíz solo para corregir el permiso de volumen.

@ibukanov no puede aplicar uid / gid, pero la etiqueta selinux está por llegar.

@ cpuguy83 ¿cuál es la razón técnica de la imposibilidad de aplicar un uid / gid personalizado al crear un directorio de volumen de host?

@ibukanov Véanse los comentarios anteriores.

@ cpuguy83 Simplemente no veo en los comentarios cuál es el problema. Para mi caso de usuario, no necesito ninguna reasignación de uid / gid. Actualmente dentro del contenedor cuando se ejecuta como root puedo chown uid:gid /host_volume && chmod 770 /host_volume . Lo que sería bueno si la ventana acoplable pudiera hacerlo por sí solo cuando crea el directorio en el host detrás de / host_volume. De esta manera, no necesitaría un truco para proporcionar un punto de entrada adicional en el contenedor solo para realizar la operación anterior como raíz del contenedor y siempre puedo ejecutar el código utilizando una cuenta que no sea root.

@ibukanov Ah, eso es algo diferente.
Docker no realiza cambios a propósito en los directorios del host.
Si hacemos # 9092, entonces si Docker creó el directorio, lo tratará como un volumen normal (es decir, copiar todo en la ruta del volumen en el contenedor en el host y chmod / chown como estaba en el contenedor).

@ cpuguy83 : bueno, la

@ cpuguy83 escribió:

Y pronto uid 0 en el contenedor no será uid 0 en el host ... lo que también hace que la propiedad del archivo sea aún más complicada.

¿Existe algún problema para realizar un seguimiento de esto? No pude encontrar uno.

¡Gracias!

¿Existe algún problema para realizar un seguimiento de esto? No pude encontrar uno.

@dato Busque "Espacio de nombres de usuario"; una implementación inicial se puede encontrar aquí: https://github.com/docker/docker/pull/12648 y aquí https://github.com/docker/docker/pull/11253

Pero hay varias discusiones / problemas anteriores a eso :)

+1

solo para saber que estoy en el mismo barco que todos:

Estoy usando la imagen nginx y montando un volumen en / usr / shared / nginx / html para el desarrollo local. Nginx se ejecuta como www-data , pero el volumen se monta como 1000:staff y así obtengo 403 forbidden .

@MrMMorris No creo que sea el mismo barco: este problema es cuando los archivos creados dentro de un contenedor (en un volumen montado) no se pueden leer fuera del contenedor sin acceso a sudo. Su usuario de www-data solo necesita acceso de lectura a los archivos montados, por lo que debería poder solo chmod a+r en sus archivos.

@ncjones chmod / chown parece no tener ningún efecto sobre los permisos en el contenedor

Estoy tan confundido porque juro que esto funcionó en múltiples puntos durante mi uso ...

Muy bien, esto es vergonzoso ...

Parece que después de actualizar para componer 1.3.0rc-1 (probablemente no) O eliminar todos mis contenedores / imágenes y ejecutar docker-compose up nuevamente ha solucionado todo ... No más 403 forbidden

Sabía que estaba funcionando antes de alguna manera, así que tomé el viejo enfoque rm -rf * ..

También necesito que este problema se resuelva de alguna manera. Tengo una imagen de la ventana acoplable que utilizo para ejecutar un trabajo de compilación pesado que debe aislarse. Entonces, el contenedor debe subir, recibir alguna entrada externa, procesar y producir los binarios (salida). Sin una gestión de permisos adecuada, ha sido una pesadilla intentar que esto funcione. Mis imágenes deben ser portátiles, por lo que no puedo asumir mucho sobre el anfitrión.

@alercunha En su caso, suena bien usar un solo usuario dentro del contenedor de la ventana acoplable, es decir, compilar como root

@alercunha
Hemos solucionado este problema en una configuración de compilación haciendo que el contenedor Docker elimine el resultado de la compilación. Nuestro Dockerfile contendrá algo como:

env USER_ID 1000
env GROUP_ID 1000
cmd bash -lc '\
  build.sh && \
  chown -R $USER_ID:$GROUP_ID build \
'

El uid / gid real del usuario del host de Docker se puede proporcionar al contenedor cuando se ejecuta. Por ejemplo, un comando de compilación de Jenkins usará algo como:

docker run \
  -e USER_ID=`id -u` \
  -e GROUP_ID=`id -g` \
  -v $basedir:/workspace

@motin Construir como root es algo que estoy tratando de evitar ya que estoy usando docker / buildroot para construir varios proyectos de terceros. La idea es tener algo de protección contra el código fuente que estropea mi entorno de compilación. Así que construir como root no parece una buena idea.

@ncjones ¡Gracias! Eso es realmente una buena idea, podría funcionar bien como solución en mi caso particular.

@alercunha En ese caso, podría valer la pena considerar el uso de imágenes / contenedores separados para cada proyecto de terceros. Eso también podría beneficiar mejor a la comunidad de código abierto, por ejemplo, si envía imágenes de docker oficiales para construir cada uno de esos proyectos de terceros.

Para otorgar todos los privilegios a www-data puede usar:

RUN usermod -u 1000 www-data

Se encontró un problema al ejecutar un trabajo en la ventana acoplable en un volumen montado. Los archivos resultantes eran propiedad de root y el usuario que ejecutaba el comando docker no podía administrarlos. La solución alternativa actual es ejecutar después del trabajo para corregir los permisos.

docker run -t --rm \
    -v $PWD:/usr/src/app \
    -w /usr/src/app \
    debian:wheezy chown -R $(id -u):$(id -g) ./

¿Es posible que Docker cambie el permiso de los volúmenes montados basados ​​en el host para que sean propiedad del usuario especificado en el comando USER del DockerFile? Claramente, los permisos tienen que ser configurables, pero podemos hacer que esto tenga el comportamiento predeterminado.

@ mig-foxbat
Para mis propósitos, sería suficiente si Docker simplemente establece la propiedad y el permiso en el directorio de host desde el punto de montaje en la imagen cuando se crea el directorio de host por primera vez. Si el directorio de host ya existe, la ventana acoplable podría dejarlo solo.

@ mig-foxbat & @ibukanov, el prerrequisito obligatorio para mí, al abrir este problema, era que los permisos en el sistema de archivos de los hosts no se cambiaran (como tener un mapeo de contenedores virtual similar a lo que se puede hacer con _NFS_).

Lo que está tratando de hacer se puede hacer fácilmente hoy ejecutando _chown_ en algún script de inicio dentro de su contenedor.

Me encanta la próxima arquitectura de plug-in de volumen, pero preferiría que el equipo de Docker agregue esta función. Docker funciona bien hasta que usa volúmenes con un usuario no root en su contenedor. Luego, cuando las cosas (por ejemplo, el registro) no funcionan, arroja su computadora portátil a través de la ventana de Starbucks o encuentra el elemento stackoverflow mencionado anteriormente.

+1 Me gustaría tener contenedores que ejecuten aplicaciones como usuario no root, lo que se vuelve complicado debido a este problema.

¿Por qué no implementar esta función utilizando la capacidad id_map de LXC?

Acabo de notar que la respuesta a "id_map" (también conocido como soporte del espacio de nombres de usuario) ya se mencionó anteriormente por @thaJeztah

Si bien se necesita un poco de trabajo adicional para establecer permisos, estamos ejecutando docenas de contenedores como no root y evitando los problemas de permisos. La mayoría de nuestros contenedores de datos comienzan con algo como:
Cónsul ENV CONTAINER_USER
ENV CONTAINER_UID 312312
EJECUTAR adduser -D $ CONTAINER_USER -u $ CONTAINER_UID
EJECUTAR mkdir -p / var / consul /
CMD chown $ CONTAINER_USER. $ CONTAINER_USER / var / consul /

Dado que el contenedor de ejecución real es similar en términos de configuración de la información de UID / useradd. Este es un trabajo duplicado (tener que configurar el UID tanto en el contenedor de datos como en el contenedor de ejecución), sin embargo, es bastante menor. Hacer que la ventana acoplable cambie los permisos o los permisos del mapa sobre la marcha agregaría una complejidad decente y los usuarios tendrían que ser más cuidadosos desde una perspectiva de seguridad. También estoy a favor de cualquier cosa que ayude a reducir la complejidad de la línea de comandos, por lo que si todo está contenido en el dockerfile, es un poco más sencillo lo que está sucediendo.

Ahora está la nota anterior sobre intentar acceder a archivos de host en un contenedor con algún tipo de mapeo. Creo que esta es sin duda una propuesta arriesgada. A menudo, intentar compartir archivos sin mapeo de host directo es probablemente la mejor solución, ya que de lo contrario está invirtiendo un poco la seguridad de la ventana acoplable. En lugar de que un contenedor tenga menos permisos de los que tendría de lo contrario, se está hablando de un contenedor que se ejecuta como no root y que tiene acceso de nivel de raíz (se supone que es un caso de uso frecuente) para alojar archivos. Permisos de grupo u otras soluciones que creo que deberían ganar en la mayoría de las situaciones.

Trabajé en torno a esto con un script de shell de punto de entrada que utiliza el directorio montado y ejecuta el subcomando a través de su.

Un ejemplo en un contenedor solr donde el directorio / data está montado como un volumen desde el host:

#!/bin/bash

chown -R $SOLR_USER:$SOLR_USER /data

su -c "$@" -m $SOLR_USER

_ ENCUESTA DE USUARIOS_

_La mejor manera de recibir una notificación cuando haya cambios en esta discusión es haciendo clic en el botón Suscribirse en la parte superior derecha.

Las personas que se enumeran a continuación han apreciado su discusión significativa con un +1 aleatorio:

@jcercurati
@iangelov
@scue
@razvanphp
@fantasma
@andrerocker
@anandnalya
@ddopson
@tiene en
@hadim
@iyn
@cgrantcharovtp
@sandytrinh
@gomex
@DrBenton
@tehmaspc
@segphault
@avaz
@edavismo
@ayeo
@stanislavb
@smebberson
@ tony-kerz
@msierks
@pdonorio
@ samsong8610
@ qm78
@joshughes
@roelvanduijnhoven
@vladimirbright
@ ava-dylang

Decir algo en estos hilos suscribe a un usuario automáticamente, por lo que sí, todas esas personas están suscritas a menos que, adicionalmente, se hayan dado de baja intencionalmente. (tampoco estoy seguro de a quién te refieres como your )

Definitivamente es imprescindible. Docker debe reasignar los UID correctamente. De lo contrario, todo lo creado desde el contenedor hasta el volumen del sistema operativo host es propiedad de root. La solución es terrible: cambiar de usuario dentro del contenedor, lo que conduce a todo tipo de complicaciones, tener que comer en todas partes, el Dockerfile crece con fealdad. ¡Y lo peor de todos los UID de codificación rígida hacen que los contenedores no sean portátiles!

+1 Esta función sería muy apreciada, ya que quiero evitar cambiar entre el contenedor de la ventana acoplable y mi sistema host, solo para evitar sobrescribir la identificación de los usuarios en los archivos.

Obtener la personalización de UID es posible en este momento, pero dentro de las siguientes restricciones:

  • La personalización de Uid es posible haciendo que el contenedor acepte los uid (s) que necesita a través de la variable de entorno. Esto le da al host un control total sobre los uid (s) que usa el contenedor, y tiene un beneficio adicional: se pueden establecer múltiples variables con el mismo valor de uid. La reasignación de UID no puede admitir la asignación de varios uids de contenedor a un único uid de host, ya que la asignación debe ser 1: 1. Por ejemplo, si el mapeo deseado era de hecho que la aplicación debería ejecutarse como uid = 0, podría hacerlo inyectando variables, pero no mediante el remapeo de uid. Vea la solución @ncjones y @mitchcapper arriba.
  • Sin embargo, la raíz uid = 0 no se puede cambiar a un valor diferente, excepto reasignando: # 12648.

Casi todos los marcos de desarrollo web modernos tienen una carpeta de registros y una carpeta de caché que se encuentra dentro del proyecto, definida en la configuración del proyecto y compartida a través del volumen montado. Usé vboxfs primero pero fue demasiado lento. Encontré docker-machine-nfs para crear montajes NFS y es rápido, pero ahora mis archivos web en contenedores son propiedad de 502: dialout y no pueden ser chmod o chown, por lo que mi aplicación web no se ejecutará. Probé docker vagrant box pero requiere vagrant con todas las diferentes configuraciones y vars env, y todavía no funciona con docker-machine. Incluso si es un proceso manual a corto plazo, ¿hay alguna solución para agregar el usuario 502 a www-data o algo así? ¡Eso es todo lo que necesito para estar en el negocio!

+1

Para los que siguen esto; Actualmente existe un PR para una función experimental que cambiará de forma recursiva la propiedad de los archivos montados en enlaces. Sin embargo, debe usarse con cuidado, porque esa función cambiará los archivos en el host (que puede no ser lo que desea en todos los casos); ver https://github.com/docker/docker/pull/14632 (y https://github.com/docker/docker/pull/16767)

+1

Por cierto, resolví este problema al usar ACL

@kvaps , ¿te importaría explicarlo?

@posita , mi apuesta es que @kvaps está hablando de ACL POSIX . Si tengo razón, eso no es lo mismo que la solicitud de OP.

@posita , @denydias , perdón por la respuesta larga. Sí, estoy hablando de esto.
Tengo muchos contenedores como owncloud, samba y minidlna. Todos trabajan con diferentes uid y gid.
Todos operan con los mismos archivos. Lo que todos pueden leer y escribir archivos, monté el sistema de archivos con la opción acl en la máquina host, y les di a todos los derechos uid y gid para estos archivos simplemente, como el comando chown :

# give access for owncloud (apache uid 33):
setfacl -R -m "u:33:rwx" /data
# give access for samba (uid 1000):
setfacl -R -m "u:1000:rwx" /data
# give access for minidlna (uid 997):
setfacl -R -m "u:997:r-x" /data
# preserve this permissions for new files and folders:
setfacl -R -d -m "u:33:rwx" /data
setfacl -R -d -m "u:1000:rwx" /data
setfacl -R -d -m "u:997:r-x" /data

@kvaps , el comando setfacl no funciona en Dockerfile . Ejemplo:

FROM nginx

ADD data/conf /etc/nginx

RUN mkdir -p /etc/nginx/sites-enabled

VOLUME /etc/nginx

RUN setfacl -dR -m u:1000:rwx /etc/nginx && setfacl -R -m u:1000:rwx /etc/nginx

Resultado:

root<strong i="12">@3975ac4fba98</strong>:/etc/nginx# getfacl sites-enabled/
# file: sites-enabled/
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

Las ACL funcionan solo después de montarlas en la máquina host y ejecutar setfacl . Versión de Docker:

Client version: 1.7.1
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 786b29d
OS/Arch (client): linux/amd64
Server version: 1.7.1
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 786b29d
OS/Arch (server): linux/amd64

Esto es muy sencillo de hacer bien y también muy sencillo de estropear. ¡Así que no lo arruines!
La forma correcta de hacer esto es: La primera vez que se ejecuta el contenedor, el host inyecta qué uids debe usar el contenedor (como ya se describió anteriormente).
La peor forma de hacer esto es: esperar que el contenedor imponga sus requisitos de uid en el host. Esto está mal, mal, mal. Por ejemplo, considere dos contenedores que comparten un montaje común: un contenedor escribe archivos para servir y otro contenedor ejecuta httpd para entregar los archivos. Ahora bien, si ambos contenedores tienen definiciones en competencia para el líquido, este sistema se romperá en el peor de los casos o, en el mejor de los casos, será deficiente. Las ACL que se establecen no tendrán ningún sentido para el host y probablemente serán más anchas de lo necesario, lo que significa que ahora es un problema de seguridad. ¡¡Por favor no hagas esto!! Hágalo de la manera correcta.

Acordado. Dejar el mapeo entre UID al contenedor es una solución suficientemente buena. Solo quería que la ventana acoplable lidere el camino con el ejemplo y admita tales asignaciones de UID / GID en las imágenes oficiales de la ventana acoplable.

Resuelto en tiempo de ejecución , sin tener que chown .

He usado algo parecido a la solución de chown porque no quiero que se modifiquen en el host. Entonces elegí cambiar el UID al inicio del contenedor.

Creo un usuario dedicado en mi Dockerfile :

RUN adduser --no-create-home --disabled-login --gecos "" username --uid 1000

Defino un script de inicio en mi Dockerfile :

CMD ["/run.sh"]

Tengo esta línea en mi script /run.sh :

usermod -u $USER_ID username

Ahora puedo elegir USER_ID cuando comience el contenedor:

docker run -e USER_ID=$(id -u)

Se las arregló para resolver esto usando el nuevo dockerfile args. No requiere hacer nada especial después de que se construye el contenedor, así que pensé en compartirlo. (Requiere Docker 1.9)

En el Dockerfile:

# Setup User to match Host User, and give superuser permissions
ARG USER_ID=0
RUN useradd code_executor -u ${USER_ID} -g sudo
RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER ${USER_ID} 

Luego para construir:

docker build --build-arg USER_ID=$(id -u)

Todo lo demás es normal :)

Editar:
Escribí esta publicación sobre el tema equivocado (era otro relacionado con boot2docker).
Perdón.

@ pa-de-solminihac usermod -u $USER_ID username cambiará la identificación de usuario de username y activará un cambio de propiedad de los archivos en el INICIO de username , pero todos los archivos anteriormente propiedad de username fuera de su INICIO probablemente se volverá ilegible / imposible de escribir ya que ahora pertenecen a un usuario diferente

@riquito Lo uso con un usuario dedicado, creado en el Dockerfile :

adduser --no-create-home --disabled-login --gecos "" username --uid 1000

Por lo tanto, no hay archivos que hayan sido propiedad de username . Entonces supongo que no hay problema;)

Para su información, setfacl _no_ funciona en volúmenes que se remontan a OS X:

root<strong i="7">@0da3c867240d</strong>:~# setfacl --default --recursive --modify u:500:rwx --modify g:500:rwx /opt/test
setfacl: /opt/test: Operation not supported

(En este caso, /opt/test se aloja desde OS X a través de la máquina Docker y Boot2Docker. Consulte también boot2docker / boot2docker # 581).

@posita ¿Estás usando virtualbox para alojar tu imagen de boottodocker? Si es así, eso puede ser una limitación con la forma en que virtualbox hace las carpetas compartidas. He tenido muchos problemas para realizar cualquier tipo de permeabilidad regular a través de la carpeta compartida de la caja virtual.

@ ava-dylang, ese es un buen punto. Lo anterior es a través de Docker Machine con el controlador Parallels , que usa la implementación nativa de carpetas compartidas de Parallels, que parece igualmente limitada. (Consulte también este https://github.com/docker/machine/issues/13#issuecomment-164320881 con respecto a una propuesta para esos tipos de entornos).

FWIW, estaba teniendo problemas con la propiedad de archivos en mi utilidad, Scuba .

Resolví el problema agregando un script "init" que crea un usuario en el contenedor con el mismo UID / GID que el usuario que invoca en el host. Ver JonathonReinhart / scuba # 11 y JonathonReinhart / scuba # 13.

Ahora, los archivos creados en el contenedor se ven exactamente como se habían creado en el host.

_Actualización: _ Eso causó problemas (JonathonReinhart / scuba # 22). En cambio, lo arreglé generando mis propios /etc/passwd y amigos, según el uid / gid del usuario host, y lo inyecté en el contenedor (ver JonathonReinhart / scuba # 24).

+1

Para hacerlo más fácil de mantener y seguro cuando el host se ejecuta en modo multiinquilino.

Tuve problemas de permisos con tales instalaciones de Wordpress, cuando compartes Wordpress completo desde el host al contenedor con un volumen.

En mi pila, tengo una imagen base, que es un debian con mis modificaciones básicas y todas las demás imágenes se construirán a partir de esta imagen.

En la imagen base, tengo esta parte:

### Start of Nginx WEBSERVER setup
RUN mkdir -p /var/www
# Modify www-data user and set UID, GID to 500
# https://muffinresearch.co.uk/linux-changing-uids-and-gids-for-user/
RUN groupmod -g 500 www-data \
    && usermod -u 500 www-data \
    #&& `find / -user 33 -exec chown -h 500 {} \;` \
    #&& `find / -group 33 -exec chgrp -h 500 {} \;` \
    && usermod -g 500 www-data \
    && chown -R www-data:www-data /var/www \
    && chmod g+s /var/www
### End of Nginx WEBSERVER setup

www-data no se crea mediante instalaciones de php o nginx. Es un usuario / grupo definido por defecto en Debian y tal vez en otras distribuciones. Algunas instalaciones de PHP, Nginx sugieren usar este usuario en sus archivos de configuración.

Si el UID / GID de su usuario de host es 500 (la mayoría de los UID / GID predeterminados del primer usuario no root de Linux es 500 o 1000), entonces este script cambia el UID / GID del usuario www-data a 500 de 33. De esta manera, si comparte cualquier cosa del host, Docker cree que esos archivos y carpetas son propiedad de www-data user!

En sus archivos de configuración PHP-FPM, configure el usuario y el grupo en www-data también.

En su nginx Dockerfile, también debe configurar esto:

# Allow Nginx to access /var/run/php-fpm/php-fpm.sock
RUN usermod -aG www-data nginx

De esta manera, el usuario nginx puede acceder a los archivos propiedad de www-data (puede definir el nombre de usuario de nginx en los archivos de configuración de nginx).

Después de este truco, ¡mi instalación de Wordpress no tiene NINGÚN problema de permisos! Todos los archivos residen en el host + ¡la actualización de Wordpress funciona perfectamente!

@DJviolin No estoy seguro de que un tema como este sea el lugar adecuado para un tutorial de Wordpress, y dudo en exponerlo aquí. Sin embargo, para los desafortunados novatos que de alguna manera podrían tropezar con esto:

  1. Lo que ha publicado hace muchas suposiciones sobre la instalación, es decir, valores UID / GID, nombres de usuarios y grupos, etc. No es muy portátil en todas las distribuciones.
  2. Más importante aún, otorgar acceso de escritura mundial (0777) a toda su instalación de Wordpress es extremadamente peligroso, y se recomienda explícitamente que no lo haga en la documentación oficial de WP. Además, con todo esto montado desde el host, acaba de permitir que las cargas arbitrarias de Internet escriban en el sistema de archivos _host_.

@jantman Lo siento, mi mal. Parece que el primer truco también resuelve los problemas de permisos. No es necesario cambiar ningún permiso predeterminado.

Obviamente, todos deben averiguar su UID de usuario de host

Hasta que Docker no dé una solución a este problema, las suposiciones se mantendrán.

Mi solución es la misma que las de @JonathonReinhart o @ pa-de-solminihac.

Puede hacer esto creando volúmenes locales, acaba de aterrizar en el maestro https://github.com/docker/docker/pull/20262.

Cerrando esto como fijo.

Hola, también tuve que hacer una solución en mi dockerfile:

...
COPY start.sh /root/start.sh
CMD /root/start.sh

y luego en start.sh

usermod -u $USER_ID www-data
exec php-fpm

Como se puede inyectar $ USER_ID como parámetro de entorno, es posible usar esa imagen de la ventana acoplable sin modificaciones.

De todos modos, creo que debería haber más funciones integradas para ese tipo de cosas y me pregunto cómo usar los volúmenes locales sugeridos por @calavera , ¿alguien puede dar un ejemplo?

@ keywan-ghadami También estaba desconcertado por los volúmenes locales. El problema es que primero debe crear el sistema de archivos (o usar tmpfs). Entonces no usa / var / lib / docker. De hecho, no puede usar un subdirectorio de _cualquier_ FS existente porque los montajes de enlace no admiten la opción uid . No sé para qué sirven los volúmenes locales; igualmente podría crear y montar el FS usted mismo y luego usar un volumen de host normal ( -v my-created-fs:container-mount-point ).

Llego bastante tarde a este hilo, pero ¿se ha resuelto este problema? No está 100% claro a partir de todos los diferentes problemas a los que se hace referencia aquí. @brthor parece tener la mejor solución por lo que puedo ver, pero involucra opciones de línea de comando que podrían agregarse más fácilmente al Dockerfile y hacerse detrás de escena.

Para mí, codificar UID y GID es una mala idea para la portabilidad entre entornos y no veo la necesidad de agregar argumentos de línea de comando cada vez que arranque un contenedor o construyo una imagen cuando podría ser una opción simple en el Dockerfile. ¿No podría haber una opción simple en Dockerfile o quizás a través de docker-compose.yml donde pueda especificar algún tipo de opción "map uid from host"?

Puede que ya exista una buena solución, pero realmente no puedo resolver esto a partir de la documentación o este hilo.

Gracias @alvinchevolleaux. Puedo confirmar que hemos estado usando la solución que publiqué anteriormente en el CI para https://github.com/dotnet/cli con éxito durante meses.

¡Lo recomiendo!

@brthor Sí, es con lo que me fui, agregué export USER_ID=$(id -u) a mi .bash_profile para que todo sea automático para mis diversos entornos. Muchas gracias.

Como se mencionó anteriormente, cuando comparta contenido de su carpeta de inicio en un contenedor, agregue una cuenta de usuario con el mismo UID que el suyo. Aquí hay un truco para hacer frente si su UID no es 1000. Supongo que cada usuario crea su propia imagen de la ventana acoplable a partir del Dockerfile.

Tu Dockerfile debe contener:

RUN useradd --uid 1000 -m vagrant
USER vagrant

La constante 1000 se sustituye por su UID real usando un _git filter_. Ejecute lo siguiente en su host:

git config filter.uidfix.smudge "sed s/1000/$UID/g"
git config filter.uidfix.clean "sed s/$UID/1000/g"

Finalmente, agregue un archivo .gitattributes para aplicar el filtro git:

Dockerfile filter=uidfix

Esto funciona reemplazando 1000 con su UID real cuando comprueba el Dockerfile _smudging_ el archivo. Git _limpiará_ el archivo (devolviendo 1000 ) cuando confirme. Todos los comandos que se ejecutan en el contenedor se ejecutan como vagrant usuario con el UID correcto.

Las costuras de este ticket deben reabrirse ya que todas las soluciones proporcionadas aquí son solo soluciones alternativas
Encontré una buena solución documentada y más completa en https://github.com/rocker-org/rocker/blob/master/rstudio/userconf.sh
Utiliza argumentos en tiempo de ejecución que hacen posible el uso de imágenes precompiladas, lo que no es posible con el filtro git.

@calavera no entiendo tu solución.

p.ej

$ mkdir /tmp/test
$ sudo docker volume create --name=test -d local --opt type=nfs --opt device=/tmp/test:/data --opt o=notime,nosuid,uid=11459,git=11459
$ sudo docker run -t -i -v test:/tmp fedora bash -i
[.. $] touch /tmp/foo.txt
[.. $] exit
$ ls -la /tmp/test

Cuando miro en el directorio / tmp / test, no hay archivos. No parece que la carpeta / tmp / test se esté montando en el contenedor ... Más bien, está creando un volumen de contenedor. Lo que realmente no es lo que quiero.

No puedo encontrar documentación que me diga cuáles son las opciones válidas --opt. Así que realmente estoy adivinando cómo se supone que funciona esto.

Vuelve a abrir este problema. El nuevo controlador local no parece abordar en absoluto el problema de montar directorios de host locales con identificaciones de usuario seleccionadas.

@calavera
¿Puede comentar cómo podemos resolver el problema de que los archivos se eliminen como root con volúmenes de host locales? He estado viendo que este problema surge con frecuencia, especialmente cuando se usa la ventana acoplable para escenarios de CI.

Al mirar el PR vinculado, no veo nada inmediatamente obvio, pero estoy seguro de que me estoy perdiendo algo 😄

He estado usando variaciones de esta solución en mis contenedores, como docbill / docker-force. Sin embargo, se me ocurre que una solución más limpia es un recipiente que solo se encarga de hacer la calabaza ...

Usar algo como bindfs para local debería ayudar. Puede ejecutarlo con -o map = $ (id -u) / root: @ $ (id -g) / @root (asumiendo que no hay espacio de nombre de usuario) y debería ver los archivos como suyos fuera del contenedor mientras son propiedad de raíz dentro de él.

@ktosiek Gracias, parece que tiene potencial. ¿Podrías publicar un ejemplo completo de docker run comando o sesión de consola?

¿Alguien podría publicar una actualización de estado sobre este problema: se cerró porque "no se solucionará" o se ha implementado realmente? El hilo es bastante largo, así que perdóname porque no puedo ver de un vistazo cuál es la resolución.

@quinncomendant ver https://github.com/docker/docker/issues/7198#issuecomment -191990887
Informe si no funciona.

Gracias @ LK4D4.

Para resumir, el problema se cerró con una solución que permite opciones de montaje para el controlador de volumen local .

Por lo que puedo decir, no hay opciones para configurar el usuario: grupo de un _host-directory montado como un volumen_ (corríjame si existe esa opción; es lo que vine a aprender aquí).

@quinncomendant correcto; al montar un enlace de un directorio de host, desea que el contenedor use los archivos que están allí como están, lo que incluye los permisos. Si desea cambiar esos permisos, debe hacerlo en el host, antes de enlazarlos.

@quinncomendant O en términos más simples, esto es un NO ARREGLO .... Ya que el
La solución proporcionada no hace nada para abordar el problema.
informó, ni hay un plan para resolver ese problema.

El 6 de julio de 2016 a las 17:20, Sebastiaan van Stijn [email protected]
escribió:

@quinncomendant https://github.com/quinncomendant correcto; cuando
enlazar-montar un directorio de host en el que desea que el contenedor use los archivos que
están ahí como están, lo que incluye permisos. Si quieres cambiar esos
permisos, debe hacerlo en el host, antes de enlazarlos

-
Estás recibiendo esto porque hiciste un comentario.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/docker/docker/issues/7198#issuecomment -230909967, o silenciar
la amenaza
https://github.com/notifications/unsubscribe/ADBcWLihVjI1FoSMLKu7DyhwFOpGX0KKks5qTBwMgaJpZM4CQMjR
.

Esto parece ser un problema que NO SE SOLUCIONA. Siempre parece que los aspectos del _desarrollo_ de la contenerización continúan siendo pasados ​​por alto y todavía nos obligan a escribir trucos.

Me encontré específicamente con este problema porque los desarrolladores a los que estoy apoyando están ejecutando comandos de generación de archivos de proyecto desde el interior de un contenedor y hacia el volumen montado en el host (la instalación de estas herramientas en el host anula por completo el propósito de usar un contenedor, ¿verdad?).

Quieren iterar rápidamente en estos archivos, sin embargo, como otros en este hilo han señalado, se escriben como el uid / gid con el que se ejecuta el contenedor, lo que requiere que se procesen correctamente en el host para manipularlos más (por un IDE por ejemplo).

Realmente es necesario que haya una forma _docker específica_ de ajustar un uid / gid temporal en este tipo de casos.

@boj Este es el escenario exacto con el que me encontré mientras desarrollaba Scuba . Mi solución actual crea, durante el inicio, un usuario en el contenedor con el mismo uid / gid que el usuario del host. No es la solución más simple, pero funciona bien.

@JonathonReinhart Gracias, me diste un poco de inspiración.

Terminé escribiendo un contenedor de script llamado desde el host de esta manera (usan django en este caso):

# bin/manage.py
#!/bin/sh

docker run -v $(pwd):/usr/local/prj -it --entrypoint="/usr/bin/python3.4" -w /usr/local/prj -u $(id -u):$(id -g) prj src/prj/manage.py $@

@boj El problema potencial con esa solución ( -u $(id -u):$(id -g) ) es que no hay una entrada en /etc/passwd o /etc/group para ese uid / gid en el contenedor: https: // github .com / JonathonReinhart / scuba / issues / 11

@JonathonReinhart señaló. En este caso particular, solo me preocupan los archivos escritos en el host del desarrollador y que tengan los mismos permisos que el usuario del host.

No se preocupe por lo que realmente sucede en tiempo de ejecución, esto era todo lo que realmente necesitaba.

@JonathonReinhart

Si el software en el contenedor necesita una entrada en / etc / passwd o / etc / group, haga que se puedan escribir en todo el mundo en la imagen y luego agregue las entradas necesarias allí al inicio.

Entonces, la solución mencionada por @JonathonReinhart (mapeo uid / gid) resuelve esto.

Parece que esto ya es compatible con runc (https://github.com/opencontainers/runc/blob/8c9db3a7a5145f6b26c8051af319eee6f72c9ca8/libcontainer/configs/config.go#L19-24). En Docker existe la configuración userns-remap para el demonio, aquí básicamente necesitaríamos tenerlo más detallado (nivel de contenedor en lugar de nivel de demonio), ¿hay algún interés / plan para respaldar esto?

Este docker-compose.yml no funciona:

version: '2'

services:
  app:
    build: ./app
    container_name: myapp
    volumes:
      #- "../app:/root/www/myapp:rw"
      - myapp:/root/www/myapp:rw

volumes:
  myapp:
    driver: local
    driver_opts:
      o: uid=500
      device: ../app

¿Alguien puede decirme por qué? Sigo las pautas oficiales: https://docs.docker.com/engine/reference/commandline/volume_create/#/driver -specific-options

¿Es posible adjuntar volúmenes con nombre desde el host? Con driver_opts puede definir uid (y tal vez gid ?).

+1

+1

@lazyuser @xiaods Por favor, deténgase con los +1. No logra nada más que enviar spam a todos esos ---> participantes.

@bamarni Sí, creo que la nueva función de espacio de nombres de usuario puede resolver esto, pero como dijiste, debería implementarse por contenedor. El resultado final sería: Un contenedor se está ejecutando como lo que cree que es "root", pero en realidad es el UID / GID pasado en la línea de comando docker run . Los archivos "saldrían" del contenedor propiedad del usuario apropiado en ese momento.

@lazyuser @xiaods @JonathonReinhart debería hacer clic en el botón +1 debajo de la descripción del problema

O simplemente haga clic en suscribirse a la derecha si solo desea notificaciones ...

@JonathonReinhart : definitivamente, volví a

Nota: La restricción de mapeo único por demonio está vigente por ahora porque Docker comparte capas de imágenes de su caché local en todos los contenedores que se ejecutan en la instancia del motor. Dado que la propiedad del archivo debe ser la misma para todos los contenedores que comparten el mismo contenido de capa, se tomó la decisión de asignar la propiedad del archivo en la extracción de la ventana acoplable a las asignaciones de usuarios y grupos del demonio para que no haya demoras en la ejecución de contenedores una vez que se descargue el contenido. Este diseño conserva el mismo rendimiento para docker pull, docker push y el inicio del contenedor que los usuarios esperan con los espacios de nombres de usuario deshabilitados.

_ (https://docs.docker.com/engine/reference/commandline/dockerd/#/daemon-user-namespace-options) _

Estimados @JonathonReinhart , @ pa-de-solminihac y @nalipaz ,
¡Gracias por su esfuerzo para educarme a mí y a otros para que no dejen comentarios que no estén relacionados con el tema al hacer precisamente eso! Para su información, Github no permite buscar problemas a los que uno está suscrito sin al menos comentarlos. Para obtener más información, consulte https://github.com/isaacs/github/issues/283. Irónicamente, el problema de Github tiene casi la misma edad que el de Docker, y ambos parecen tener una prioridad similar.

A todos, lo siento por el spam. La primera vez fue una solución para el error de github mencionado anteriormente, y esta vez no pude resistirme a dar la ironía de la situación.

Resolví esto usando

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 indicando a inotifywait que esté atento a los nuevos archivos o directorios creados 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 quién sea el propietario, porque todo corre como root. Fuera del contenedor, el sistema de archivos del host muestra la misma propiedad que cualquier directorio que se haya montado en / mount.

Lo diseñé deliberadamente para establecer solo la propiedad de los archivos y directorios recién creados, con el fin de preservar la propiedad de los archivos y directorios preexistentes. Es más seguro que desperdiciar todo eso con una declaració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, busque inotify-hookable .

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

@ codekitchen-ws Otra advertencia: un archivo se puede mover después de la creación y antes de que cambie el propietario. Dependiendo del shell, también querrá citar "$f" (para evitar la división de palabras en la ruta).

+1

@briansrepo Ese es un enfoque interesante. Si está en una instrucción Dockerfile RUN , se ejecuta en el momento de la compilación. ¿Cómo podría saber el usuario docker run en el momento de la ejecución?

@btiernay ¡Gracias! No usa el UID del usuario que activó la imagen. Copia específicamente el usuario de host y el grupo de hosts de cualquier directorio de host que esté montado en / mount. No mira ningún otro archivo o subdirectorio. Depende del usuario asegurarse de que los permisos estén configurados para algo en lo que puedan escribir en el sistema host.

Ejemplo: suponga que el directorio de host / var / www / html es propiedad de brian: www-data. Lanza una imagen que monta el directorio del sistema host / var / www / html en el directorio de imágenes / mount. Luego crea /mount/index.html desde dentro de la imagen. Si comprueba la propiedad de /var/www/html/index.html en el sistema host, será propiedad de brian: www-data.

Sobre la base de ese ejemplo, digamos que tiene un directorio de host / var / www / html / upload propiedad de www- data: www-data. Tenga en cuenta que el directorio de host montado / var / www / html sigue siendo propiedad de brian: www-data. Ahora ve a la imagen y crea /mount/upload/file.pdf. Si comprueba el archivo de host /var/www/html/upload/file.pdf, será propiedad de brian: www-data , no www- data: www-data , porque el directorio de host montado / var / www / html es propiedad de brian: www-data. ¿Tener sentido?

TL; DR: pasa el usuario: grupo que desea usar al cambiar el directorio de host montado a usuario: grupo.

@briansrepo gracias por la explicación. Todo eso tiene sentido, pero aún no entiendo cómo puede funcionar esto dentro de un RUN . Creo que esto debería ejecutarse en segundo plano cuando se ejecuta el contenedor (es decir, docker run ).

@btiernay También me gusta esta idea.
@briansrepo al menos cubre lo que pasa desde los contenedores.
El proceso de compilación aún se puede abordar con algo como

RUN usermod -u 1000 www-data

Sin embargo, estas siguen siendo soluciones.

En mi pila LEMP tengo esta preconfiguración de Nginx en mi Dockerfile base:

### Start of Nginx WEBSERVER setup
RUN mkdir -p /var/www
# Modify www-data user and set UID, GID to 500
# https://muffinresearch.co.uk/linux-changing-uids-and-gids-for-user/
RUN groupmod -g 500 www-data \
    && usermod -u 500 www-data \
    && usermod -g 500 www-data \
    && chown -R www-data:www-data /var/www \
    && chmod g+s /var/www
### End of Nginx WEBSERVER setup

Este es un truco en el que todos los archivos recién creados de una sesión ssh de host que obtienen el uid, gid de 500 y nginx no tendrán acceso a esos archivos eventualmente (porque el usuario o grupo con la identificación de 500 no existía en el contenedor). Puede verificar qué número de uid, gid tiene que crear para su usuario www-data cuando copia archivos nuevos en el volumen compartido en el host desde una sesión ssh y luego docker exec en este contenedor y mirando los archivos el uid, gid.

El problema que encontré, si copié nuevos archivos en la carpeta compartida en la máquina host (a la que accedió mediante una sesión ssh, como en una instancia de CoreOS en DigitalOcean), Nginx no tiene acceso a esos archivos recién creados. Entonces, si desea una compatibilidad absoluta con los privilegios, debe compartir los archivos de su servidor web en el contenedor Docker en la creación de los contenedores (al menos este fue el caso hace 1 año, cuando me encontré con estos problemas de uid, gid con volúmenes compartidos) .

O también puede instalar el servicio ssh en el contenedor de la ventana acoplable que comparte los archivos con el contenedor nginx, de esta manera, si copia / modifica los archivos, obtienen el uid correcto, gid. Pero esto contra las mejores prácticas de Docker de que debe usar docker inspect lugar de sesiones ssh, porque "Docker no es una máquina virtual" (sería una solución demasiado fácil, ¿verdad?).

En mi opinión, un contenedor Docker debería actuar como un servicio o un ejecutable y no debería tomar como rehenes los archivos de mi servidor web si no quiero. La base de datos es un tipo diferente de cosas (a veces), pero no veo por qué no sería posible lograr la misma infraestructura de contenedores del santo grial, donde todos sus archivos de base de datos estáticos, de servidor web y que viven fuera de los contenedores (pero los contenedores pueden modificarlos (como eliminar, crear, modificar) y también puede modificarlos sin ningún problema de privilegios del host.

Con docker volume create --opt puede definir uid, gid, pero no es fiel a docker-compose : https://github.com/docker/compose/issues/3715

Realmente necesitamos una solución multiplataforma (no gosu) para mapear uid / gid. Este problema por sí solo causa enormes daños en la forma en que los novatos perciben la ventana acoplable.

Hemos creado una solución para este problema que cambia los permisos de usuario / grupo y archivo de un contenedor Docker que se establecieron en el momento de la compilación al UID / GID con el que se inició el contenedor en el tiempo de ejecución.

El proyecto y las instrucciones de instalación están en: https://github.com/boxboat/fixuid

Ejemplo: el contenedor de Docker se creó con el usuario / grupo dockeruser:dockergroup como UID / GID 1000:1000 . El host se ejecuta como UID / GID 1001:1002 . La imagen se ejecuta con docker run -u 1001:1002 . fixuid hará:

  • cambiar dockeruser UID a 1001
  • cambiar dockergroup GID a 1002
  • cambie todos los permisos de archivo para el antiguo dockeruser:dockergroup a 1001: 1002
  • actualizar $ HOME dentro del contenedor a dockeruser $ HOME
  • ahora el contenedor y el host UID / GID coinciden y los archivos creados en el contenedor en los montajes del host coincidirán

Puede ejecutarse como ENTRYPOINT o como parte de un script de inicio. Se instala en el contenedor como un binario propiedad de root con el bit setuid y escala los privilegios para realizar los cambios apropiados. Solo debe usarse en contenedores de desarrollo.

Si esto resulta útil, el motor Docker puede incorporar parte o toda la lógica a través de indicadores en docker run

Resuelto usando docker volume .

@hashar ¿cómo? ¿Puedes dar un ejemplo por favor?

entonces, ¿todavía no hay otra solución para esto que no sea usar gosu y un script de punto de entrada?

Por ahora, parece que hay 2 opciones como solución para esto, hasta que el equipo de Docker haga una actualización oficial sobre esto.

Es una pena que esto siga siendo un problema. En teoría, existe la reasignación de usuarios, pero no es fácil de usar.

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