Moby: Rendre uid et gid configurable pour les volumes partagés

Créé le 23 juil. 2014  ·  141Commentaires  ·  Source: moby/moby

Veuillez fournir une option pour rendre la propriété des volumes partagés configurable.

Par exemple, mon cas d'utilisation actuel consiste à exécuter logstash-forwarder dans un conteneur, qui a /var/lib/docker partagé en lecture seule en tant que volume de l'hôte.

Étant donné que /var/lib/docker est défini sur 0700 root:root sur l'hôte, je ne peux pas accéder au volume en tant qu'utilisateur non root.

Ce que j'aimerais avoir, c'est quelque chose comme avec NFS où l'on peut mapper l'uid et le gid de l'hôte aux utilisateurs et groupes sur le client.

C'est-à-dire que docker run -v /var/lib/docker:/var/lib/ docker:ro :$user:$group rendrait le volume disponible dans le conteneur en lecture seule, appartenant à $user:$group.

kinfeature

Commentaire le plus utile

Nous avons vraiment besoin d'une solution multiplateforme (pas gosu) pour mapper uid/gid. Ce problème à lui seul cause d'énormes dommages à la façon dont docker est perçu par les novices.

Tous les 141 commentaires

Je ne sais pas _comment_ ils ont implémenté cela, et si une fonctionnalité comparable existe sur Linux, mais sur OS X, une fonctionnalité existe pour "ignorer la propriété" sur un volume. En fait, cela permettra à _n'importe quel_ utilisateur de voir les fichiers/répertoires comme s'il en était le propriétaire.

Bien que cela ne convienne pas à tous les cas, cela peut être un bon ajout

gh#5910 gère en quelque sorte cela du côté SELinux.

lien : #5910 ;)

Le changement SELinux change en fait les étiquettes sur le contenu. Potentiellement, vous pouvez faire le changement sur l'hôte. Je ne connais aucun autre moyen de le faire pour UID/GID. Mais faire un chown -R $UID:$GID sur le point de montage.

Ou vous pouvez ajouter ce type d'accès à l'aide d'ACL. Mais je pense que vous devrez changer chaque INODE sur le point de montage.

J'ai aussi besoin de cette fonctionnalité.

Par exemple, je souhaite créer un conteneur Web et y attacher des volumes avec des sites Web et des configurations, afin que ce conteneur soit complètement universel pour un nombre quelconque de sites Web.

Cependant, j'ai besoin d'un accès git pour transférer le code vers le référentiel du site Web. Étant donné que je souhaite que mes applications soient isolées, je souhaite que chaque répertoire de site Web appartienne à un utilisateur / groupe distinct, et ce serait formidable si les fichiers écrits par le conteneur Docker dans le volume appartenaient à cet utilisateur / groupe distinct.

+1 pour cette fonctionnalité.
Je ne comprends pas comment les volumes de lecture/écriture peuvent fonctionner sans cela. Attendre que le guid/uid soit le même sur l'image et l'hôte est une exigence forte incompatible avec les principes d'isolation de Docker.

Je travaille personnellement autour de cela avec des commandes useradd/groupadd laides et lentes pour mes outils de développement Dockerized : https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/bin-docker/nspire-docker

Je suis peut-être complètement à côté de l'essentiel. Mais je me débattais avec un problème similaire où je voulais m'assurer que l'utilisateur http dispose des autorisations d'écriture sur /var/log, qui est un volume et provient probablement de l'hôte avec root:root en tant que propriétaire.

Je l'ai résolu en définissant un point d'entrée qui garantit que les répertoires de journaux sont créés et disposent des autorisations appropriées. Je suppose que cela fonctionne car le script du point d'entrée s'exécute en tant que root.

(commentaire supprimé -- mauvais onglet, désolé)

J'ai piraté cela dans Ubuntu en dehors de Docker. Installez le package bindfs et liez le répertoire avec le contenu du volume à un autre chemin tout en mappant l'UID et le GID à ceux utilisés à l'intérieur du conteneur :

sudo bindfs -u UID -g GID ancien chemin nouveau chemin

Utilisez ensuite newpath comme volume docker. Oldpath affiche toujours la propriété correcte pour l'hôte, newpath pour l'invité.

@jjv le problème est que bindfs est VRAIMENT VRAIMENT lent.

@ cpuguy83 oui c'est loin d'être optimal mais peut-être aide quelqu'un dans une situation similaire. Il s'agissait de faire fonctionner les choses à l'intérieur d'une machine virtuelle de développement (vmhgfs ne permet pas de définir l'UID/GID) pendant la production, l'UID et le GID doivent toujours correspondre entre l'hôte et l'invité...

Ce serait en fait bien si un type de fonctionnalité bindfs était utilisé lorsque docker implémente cela, en supposant que cela ne cause pas trop de problèmes de performances. De cette façon, vous n'auriez pas à vous assurer que le conteneur était exécuté en tant qu'utilisateur correct. Il devrait également être possible d'utiliser des noms logiques au lieu du littéral uid/gid.

@jsternberg C'est un énorme succès de performance. Assez semblable à l'utilisation de dossiers partagés vbox.

+1

pour les cas d'utilisation de développement local, je pense que Docker a définitivement besoin de cette fonctionnalité. Et dans ce cas, je veux que cette fonctionnalité prenne en charge à la fois Windows et OSX.

Vagrant semble prendre en charge cela en mappant l'UID/PID de l'utilisateur hôte sur celui de l'utilisateur vagabond. Mais pour le développement, je veux vraiment utiliser Docker au lieu de Vagrant, car il est beaucoup plus léger que Vagrant pour exécuter des applications multi-hôtes.

S'il vous plaît, dites-moi ce qui me manque ici (je n'ai aucune expérience avec Go), mais la fonction Go Mount() n'accepte-t-elle pas les drapeaux ? Ne pourrions-nous pas autoriser une commande comme
-v host/folder:container/folder -mount-as user:group
Ne pourriez-vous pas simplement obtenir l'uid/gid avec lookup (https://golang.org/src/os/user/lookup_unix.go)
puis les passer (uid=1,gid=1) en tant qu'indicateurs dans Mount() ? (https://golang.org/src/syscall/syscall_linux.go?s=19154:19249#L754)

Les montages de liaison

La séparation de l'option -v de l'option --mount-as provoque également une confusion lorsqu'il existe plusieurs options -v

Quelle est une bonne solution de contournement pour cela? J'adorerais utiliser Docker pour le développement actif, et ne pas avoir de volume monté quelconque n'est pas vraiment une option car je devrais reconstruire chaque fois que je modifie mon code.

La raison pour laquelle je souhaite utiliser Docker pour le développement actif est qu'il soit cohérent avec mon environnement de production.

@berfarah J'utilise docker pour un développement actif tous les jours.
Il y a rarement le cas où j'ai besoin de jouer avec les permanentes.
Si vous utilisez boot2docker sur OSX, assurez-vous que votre répertoire de travail réside dans /Users et tout devrait bien se passer.

@ cpuguy83 Merci pour la réponse rapide. J'ai des problèmes d'autorisations avec un environnement rails où les journaux ne peuvent pas être écrits, et il y a parfois des points d'échec en raison des autorisations. Cela est dû au fait que mes services ont un UID différent de celui des fichiers.

@berfarah Ma solution de contournement consiste à écrire mes fichiers docker de telle sorte que les utilisateurs/groupes de conteneurs qui possèdent le code aient le même UID/GUID que mon utilisateur hôte. Par exemple, puisque mon UID d'utilisateur hôte est 1000 :

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

@berfarah Avez-vous des logs sur stdout/stderr pour RAILS_ENV=development ?

@cpuguy83 Ce problème n'affecte pas OSX ; thaJeztah a commenté le 24 juillet 2014 :

sur OS X, une fonctionnalité existe pour « ignorer la propriété » sur un volume. En fait, cela permettra à tout utilisateur de voir les fichiers/répertoires comme s'il en était le propriétaire.

@ncjones en fait, la même chose s'applique à OS X. Les "volumes" dont je parlais là, sont les disques durs / partitions (volumes) utilisés sur OS X lui-même. Je doute que cela fasse une différence pour travailler avec Boot2Docker, mais je n'en suis pas sûr.

Mon commentaire visait à informer si quelque chose de _similaire_ était possible sous Linux (donc à l'intérieur de la machine virtuelle Boot2Docker)

Désolé pour la confusion là-bas.

@ryneeverett Merci, c'est utile. Est-ce que vous finissez ensuite par modifier les autorisations de 775 à partir de 755 et 664 à partir de 644 respectivement, là où vous en avez besoin ? edit : Compétences en lecture !

@cpuguy83 Merci ! Cela semble être une solution plus restrictive que la solution de @ryneeverett , car ce n'est pas tout à fait quelque chose que je peux simplement reporter sur tous les projets.

@berfarah Heureux que vous ayez trouvé cela utile. Oui, je m'assure simplement que mes fichiers hôtes disposent des autorisations appropriées et que Docker les préserve dans les volumes.

+1

C'est quelque chose qui serait extrêmement utile pour les volumes partagés via docker, et répond à un problème de sécurité que j'ai :

  • Volumes partagés où l'uid et le gid du conteneur sont accidentellement mappés à un utilisateur privilégié non root sur l'hôte. (par exemple, les fichiers créés par le conteneur sur l'hôte sont mappés vers un utilisateur qui peut sudo sans mot de passe, accéder à un contenu autrement restreint, etc.)

Corriger cela serait très pratique pour les entreprises exécutant une tonne de conteneurs avec Apache ou un middleware et partageant les volumes de journalisation et/ou divers répertoires de contenu/téléchargement. J'ai aussi personnellement eu quelques maux de tête avec ces autorisations lors de la conteneurisation des applications des utilisateurs finaux sous Linux (comme syncomm/spotify). Aujourd'hui, bon nombre des solutions de contournement sont elles-mêmes problématiques. En fin de compte, cela doit être corrigé à l'intérieur de docker. Je ne me sens particulièrement pas à l'aise d'exécuter des scripts shell root comme point d'entrée, en particulier lorsque ce problème met en évidence la façon dont l'uid/gid 0:0 dans le conteneur sera mappé à root sur mon hôte. J'aime la proposition initiale "docker run -v /var/lib/docker:/var/lib/ docker:ro :$user:$group".

@syncomm, j'adopterais l'approche exactement opposée.
Docker ne peut pas faire d'hypothèses sur la propriété de vos données.

L'approche que vous mettez en évidence au bas de votre commentaire serait faisable si nous devions mapper automatiquement ces fichiers réels sur un fs basé sur des fusibles où nous pouvons changer les uid/gids... et cela aurait un impact significatif sur les performances.

Et bientôt, l'uid 0 dans le conteneur ne sera plus l'uid 0 sur l'hôte... ce qui rend également la propriété des fichiers encore plus délicate.

Est-ce un doublon du #2259 ?

@ cpuguy83 Merci pour les commentaires, même si je ne suis pas sûr de ce que vous entendez par l'approche exactement opposée. Nuage tu expliques ? Je suis d'accord pour dire que la propriété des données ne devrait pas être assumée par docker, mais je pense que fournir un mappage cohérent du conteneur à l'hôte rend certainement le travail de contrôle de ces données beaucoup plus facile pour les consommateurs de docker.

Je suis d'accord que, comme la solution de contournement de bindfs, en faire un emballage de fusible entraînerait une surcharge importante. Cependant, il doit y avoir un moyen de sortir de cette énigme sans pénalités énormes. Essentiellement, le conteneur se comporte correctement (comme s'il s'agissait d'une machine unique distincte de l'hôte), et lorsque nous montons le répertoire d'un hôte en tant que volume, il y voit (correctement) le système de fichiers POSIX, les autorisations et tout. Malheureusement, cela rend très difficile le partage de données entre les deux "hôtes" de manière cohérente. Des choses comme nfs, cifs, etc. sont habituées à cela et prennent en charge le mappage uid et gid - je pense qu'il pourrait y avoir un parallèle ici pour résoudre le problème. Honnêtement, je dois creuser davantage dans le référentiel pour comprendre où cela se passe dans le code et mieux le comprendre.

Quand les changements que vous avez mentionnés concernant la propriété des fichiers seront-ils supprimés ? L'uid 0 n'étant PAS le même pour le conteneur et l'hôte, je me sentirais beaucoup plus à l'aise pour créer un point d'entrée d'un script shell racine. Ensuite, il suffit d'effectuer la solution de contournement suggérée en passant le bon uid/gid en tant qu'env et en faisant un adduser au lancement du conteneur.

@syncomm Malheureusement, pas trop à ma connaissance, non sans les envelopper dans un autre type de système de fichiers qui peut être monté avec les paramètres uid/gid.

En fin de compte, cela ressemble à quelque chose qui nécessite la prise en charge du noyau pour un remappage bidirectionnel complet des UID et GID, et ne semble même pas facile à gérer.

Pour les scénarios non sensibles aux performances, peut-être que quelque chose pourrait être fait en utilisant FUSE.

Toujours +1 pour les cas d'utilisation de développement, car je me retrouve avec des fichiers appartenant à root chez moi.

Pour mon cas d'utilisation, il suffirait que docker puisse simplement appliquer l'étiquette personnalisée uid/gid et selinux au volume hôte lorsqu'il le crée en laissant l'autorisation et les étiquettes seules si le répertoire existe déjà. Actuellement, je contourne cela en ayant un point d'entrée séparé pour l'image qui s'exécute en tant que root juste pour corriger l'autorisation de volume.

@ibukanov, il ne peut pas appliquer uid/gid, mais l'étiquette selinux arrive.

@cpuguy83 quelle est la raison technique de l'impossibilité d'appliquer un uid/gid personnalisé lors de la création d'un répertoire de volume hôte ?

@ibukanov Voir les commentaires ci-dessus.

@ cpuguy83 Je ne vois tout simplement pas dans les commentaires quel est le problème. Pour mon cas utilisateur, je n'ai besoin d'aucun remappage de uid/gid. Actuellement à l'intérieur du conteneur lors de l'exécution en tant que root, je peux chown uid:gid /host_volume && chmod 770 /host_volume . Ce qui serait bien si le docker pouvait le faire tout seul lorsqu'il crée le répertoire sur l'hôte derrière /host_volume. De cette façon, je n'aurais pas besoin d'un hack pour fournir un point d'entrée supplémentaire dans le conteneur juste pour effectuer l'opération ci-dessus en tant que racine de conteneur et je peux toujours exécuter le code à l'aide d'un compte non root.

@ibukanov Ah, c'est autre chose.
Docker n'apporte pas, tout à fait exprès, de modifications aux répertoires des hôtes.
Si nous faisons #9092, alors si docker a créé le répertoire, il le traitera comme un volume normal (c'est-à-dire, copiez tout sur le chemin du volume dans le conteneur sur l'hôte et chmod/chown tel qu'il était dans le conteneur).

@ cpuguy83 - eh bien, docker change quelque chose sur l'hôte lorsqu'il crée le volume hôte manquant. Mais #9092 sonne comme si cela résoudrait effectivement mon cas d'utilisation.

@cpuguy83 a écrit :

Et bientôt l'uid 0 dans le conteneur ne sera plus l'uid 0 sur l'hôte... ce qui rend également la propriété des fichiers encore plus délicate.

Y a-t-il un problème existant pour suivre cela? Je n'ai pas réussi à en trouver un.

Merci!

Y a-t-il un problème existant pour suivre cela? Je n'ai pas réussi à en trouver un.

@dato Recherchez « Espace de nom utilisateur » ; une première implémentation peut être trouvée ici : https://github.com/docker/docker/pull/12648 et ici https://github.com/docker/docker/pull/11253

Mais il y a diverses discussions/problèmes antérieurs à cela :)

+1

juste pour que je sache que je suis dans le même bateau que tout le monde :

J'utilise l'image nginx et monte un volume sur /usr/shared/nginx/html pour le développement local. Nginx s'exécute en tant que www-data , mais le volume est monté en tant que 1000:staff et j'obtiens donc 403 forbidden .

@MrMMorris Je ne pense pas que ce soit le même bateau - ce problème se produit lorsque les fichiers créés dans un conteneur (sur un volume monté) ne sont pas lisibles en dehors du conteneur sans accès sudo. Votre utilisateur de www-data n'a besoin que d'un accès en lecture aux fichiers montés, vous devriez donc pouvoir seulement chmod a+r sur vos fichiers.

@ncjones chmod/chown semble n'avoir aucun effet sur les autorisations dans le conteneur

Je suis tellement confus parce que je jure que cela a fonctionné à plusieurs moments pendant mon utilisation...

Bon ben c'est gênant...

Il semble que soit après la mise à niveau pour composer la version 1.3.0rc-1 (probablement pas), soit la suppression de tous mes conteneurs/images et l'exécution à nouveau de docker-compose up ont tout corrigé.... Plus de 403 forbidden

Je savais que cela fonctionnait avant d'une manière ou d'une autre, alors j'ai adopté l'ancienne approche rm -rf * ..

J'ai également besoin que ce problème soit résolu d'une manière ou d'une autre. J'ai une image docker que j'utilise pour exécuter un gros travail de compilation qui doit être isolé. Ainsi, le conteneur doit monter, recevoir une entrée externe, traiter puis produire les binaires (sortie). Sans une gestion appropriée des autorisations, cela a été un cauchemar d'essayer de faire fonctionner cela. Mes images doivent être portables, je ne peux donc pas supposer grand-chose à propos de l'hôte.

@alercunha Dans votre cas, il semble bien d'utiliser un seul utilisateur dans le conteneur docker, c'est-à-dire compiler en tant que root

@alercunha
Nous avons contourné ce problème dans un paramètre de build en demandant au conteneur Docker de chiffrer la sortie de build. Notre Dockerfile contiendra quelque chose comme :

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

L'uid/gid réel de l'utilisateur de l'hôte Docker peut ensuite être fourni au conteneur lors de l'exécution. Par exemple, une commande de construction Jenkins utilisera quelque chose comme :

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

@motin Construire en tant que root est quelque chose que j'essaie d'éviter car j'utilise docker/buildroot pour créer plusieurs projets tiers. L'idée est d'avoir une certaine protection contre ce code source qui perturbe mon environnement de construction. Donc, construire en tant que root ne semble pas être une bonne idée.

@ncjones Merci ! C'est en fait une bonne idée, cela pourrait bien fonctionner comme solution dans mon cas particulier.

@alercunha Dans ce cas, il pourrait être utile d'envisager d'utiliser des images/conteneurs séparés pour chaque projet tiers. Cela pourrait également mieux profiter à la communauté open source, par exemple si vous soumettez des images docker officielles pour la construction de chacun de ces projets tiers.

Pour accorder tous les privilèges à www-data vous pouvez utiliser :

RUN usermod -u 1000 www-data

Problème rencontré lors de l'exécution d'une tâche dans docker sur un volume monté. Les fichiers résultants appartenaient à root et ne pouvaient pas être gérés par l'utilisateur exécutant la commande docker. La solution de contournement actuelle consiste à exécuter après le travail pour corriger les autorisations.

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

est-il possible que docker modifie l'autorisation des volumes montés basés sur l'hôte à appartenir à l'utilisateur spécifié dans la commande USER du DockerFile ? Il est clair que les autorisations doivent être configurables, mais nous pouvons avoir le comportement par défaut.

@mig-foxbat
Pour mes besoins, il suffirait que docker définisse simplement la propriété et l'autorisation sur le répertoire hôte à partir du point de montage dans l'image lorsque le répertoire hôte est créé pour la première fois. Si le répertoire hôte existe déjà, le docker peut le laisser tranquille.

@mig-foxbat & @ibukanov la condition préalable obligatoire pour moi, lors de l'ouverture de ce problème, était que les autorisations sur le système de fichiers des hôtes ne soient

Ce que vous essayez de faire peut facilement être fait aujourd'hui en exécutant _chown_ dans un script de démarrage dans votre conteneur.

J'adore l'architecture de plug-in de volume à venir, mais je préférerais de loin que l'équipe Docker ajoute cette fonctionnalité. Docker fonctionne bien jusqu'à ce que vous utilisiez des volumes avec un utilisateur non root dans votre conteneur. Ensuite, lorsque les choses (par exemple, la journalisation) ne fonctionnent pas, vous lancez votre ordinateur portable à travers la fenêtre Starbucks ou vous trouvez l'élément de débordement de pile référencé ci-dessus.

+1 Je voudrais que des conteneurs exécutent des applications en tant qu'utilisateur non root, ce qui devient compliqué en raison de ce problème.

Pourquoi ne pas implémenter cette fonctionnalité en utilisant la capacité id_map de LXC ?

Je viens de remarquer que la réponse à "id_map" (alias prise en charge de l'espace de nom d'utilisateur) est déjà mentionnée ci-dessus par @thaJeztah

Bien qu'il faille un peu de travail supplémentaire pour définir les autorisations, nous exécutons des dizaines de conteneurs en tant que non-root et évitons les problèmes d'autorisation. La plupart de nos conteneurs de données commencent par quelque chose comme :
ENV CONTAINER_USER consul
ENV CONTAINER_UID 312312
RUN adduser -D $CONTAINER_USER -u $CONTAINER_UID
RUN mkdir -p /var/consul/
CMD chown $CONTAINER_USER.$CONTAINER_USER /var/consul/

Le conteneur d'exécution réel étant similaire en termes de définition des informations UID/useradd. Il s'agit d'un travail en double (il faut définir l'UID à la fois sur le conteneur de données et le conteneur d'exécution), mais c'est assez mineur. Avoir des autorisations de modification de docker ou des autorisations de carte à la volée ajouterait une certaine complexité et les utilisateurs devraient être plus prudents du point de vue de la sécurité. Je suis également pour tout ce qui aide à réduire la complexité de la ligne de commande, donc si tout est contenu dans le fichier docker, c'est un peu plus simple ce qui se passe.

Maintenant, il y a la note ci-dessus d'essayer d'accéder aux fichiers hôtes dans un conteneur avec une sorte de mappage. Je pense que c'est certainement une proposition risquée. Essayer souvent de partager des fichiers sans mappage d'hôte direct est probablement la meilleure solution, sinon vous inversez quelque peu la sécurité de docker. Plutôt qu'un conteneur ayant moins d'autorisations qu'il n'en aurait autrement, vous parlez d'un conteneur exécuté en tant que non-root ayant un accès au niveau racine (cas présumé d'utilisation) pour héberger des fichiers. Je pense que les autorisations de groupe ou d'autres solutions devraient l'emporter dans la plupart des situations.

J'ai contourné cela avec un script shell de point d'entrée qui affiche le répertoire monté et exécute la sous-commande via su.

Un exemple dans un conteneur solr où le répertoire /data est monté en tant que volume à partir de l'hôte :

#!/bin/bash

chown -R $SOLR_USER:$SOLR_USER /data

su -c "$@" -m $SOLR_USER

_SONDAGE UTILISATEUR_

_La meilleure façon d'être averti lorsqu'il y a des changements dans cette discussion est de cliquer sur le bouton S'abonner en haut à droite._

Les personnes énumérées ci-dessous ont apprécié votre discussion significative avec un +1 aléatoire :

@jcercurati
@iangelov
@scue
@razvanphp
@fantôme
@andrerocker
@anandnalya
@ddopson
@hason
@hadim
@iyn
@cgrantcharovtp
@sandytrinh
@gomex
@DrBenton
@tehmaspc
@segphault
@avaz
@edavisme
@ayeo
@stanislavb
@smebberson
@tony-kerz
@msierks
@pdonorio
@samsong8610
@qm78
@joshughes
@roelvanduijnhoven
@vladimirbright
@ava-dylang

Dire quoi que ce soit sur ces fils de discussion abonné automatiquement un utilisateur, donc oui, toutes ces personnes sont abonnées à moins qu'elles ne se soient en outre intentionnellement désabonnées. (pas sûr non plus de _à qui_ vous faites référence en tant que your )

C'est définitivement un must. Docker doit remapper correctement les UID. Sinon, tout ce qui est créé du conteneur au volume du système d'exploitation hôte appartient à root. La solution de contournement est terrible - changer d'utilisateurs à l'intérieur du conteneur, ce qui entraîne toutes sortes de complications, devoir mâcher partout, le Dockerfile grandit avec la laideur. Et le pire de tous, les UID codés en dur rendent les conteneurs non portables !

+1 Cette fonctionnalité serait très appréciée, car je veux éviter de basculer entre le conteneur Docker et mon système hôte, juste pour éviter d'écraser l'identifiant des utilisateurs sur les fichiers.

Obtenir la personnalisation de l'UID est possible dès maintenant, mais dans les limites suivantes :

  • La personnalisation de l'UID est possible en faisant en sorte que le conteneur accepte le ou les UID dont il a besoin via la variable d'environnement. Cela donne à l'hôte un contrôle total sur le(s) uid(s) utilisé(s) par le conteneur et présente un avantage supplémentaire : plusieurs variables peuvent être définies sur la même valeur uid. Le remappage d'UID ne peut pas prendre en charge le mappage d'UID de conteneurs multiples vers un UID d'hôte unique, car le mappage doit être de 1:1. Par exemple, si le mappage souhaité était en fait que l'application devrait s'exécuter en tant que uid=0, vous pouvez le faire en injectant des variables, mais pas via un remappage uid. Voir la solution @ncjones et @mitchcapper ci-dessus.
  • La racine uid=0 notamment ne peut cependant pas être changée en une valeur différente, sauf en remappant : #12648.

Presque tous les frameworks de développement Web modernes ont un dossier de journaux et un dossier de cache qui se trouvent à l'intérieur du projet, définis dans la configuration du projet et partagés via le volume monté. J'ai d'abord utilisé vboxfs mais c'était trop lent. J'ai trouvé docker-machine-nfs pour créer des montages NFS et c'est rapide, mais maintenant mes fichiers Web dans des conteneurs appartiennent à 502: dialout et ne peuvent pas être chmod ou chown, donc mon application Web ne s'exécutera pas. J'ai essayé docker vagrant box, mais cela nécessite vagrant avec toutes les différentes vars et configurations d'environnement, et ne fonctionne pas encore avec docker-machine. Même s'il s'agit d'un processus manuel à court terme, existe-t-il une solution de contournement pour ajouter l'utilisateur 502 à www-data ou quelque chose du genre ? C'est tout ce dont j'ai besoin pour être en affaires !

+1

Pour ceux qui suivent ; il existe actuellement un PR pour une fonctionnalité expérimentale qui changera de manière récursive la propriété des fichiers montés par liaison. Il doit cependant être utilisé avec précaution, car cette fonctionnalité modifiera les fichiers sur l'hôte (ce qui peut ne pas être ce que vous voulez dans tous les cas); voir https://github.com/docker/docker/pull/14632 (et https://github.com/docker/docker/pull/16767)

+1

Au fait, j'ai résolu ce problème en utilisant ACL

@kvaps ,

@posita , mon pari est que @kvaps parle des ACL POSIX . Si j'ai raison, ce n'est pas la même chose que la demande OP.

@posita , @denydias , désolé pour la longue réponse. Oui, je parle de ça.
J'ai de nombreux conteneurs comme owncloud, samba et minidlna. Tout le monde travaille avec un uid et un gid différents.
Ils fonctionnent tous avec les mêmes fichiers. Qu'est-ce que tout le monde peut lire et écrire des fichiers, j'ai monté le système de fichiers avec l'option acl dans la machine hôte, et j'ai donné à tout le monde les droits uid et gid pour ces fichiers simplement, comme la commande 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 , la commande setfacl ne fonctionne pas dans Dockerfile . Exemple:

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

Résultat:

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

Les ACL ne fonctionnent qu'après le montage sur la machine hôte et l'exécution de setfacl . Version 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

C'est très simple à faire correctement, et aussi très simple à foutre en l'air. Alors ne la gâchez pas !
La bonne façon de procéder est la suivante : la première fois que le conteneur est exécuté, l'hôte injecte les uids que le conteneur doit utiliser (comme déjà décrit ci-dessus).
La pire façon de procéder est de s'attendre à ce que le conteneur impose ses exigences d'UID à l'hôte. C'est faux, faux, faux. Par exemple, considérons deux conteneurs qui partagent un montage commun : un conteneur écrit les fichiers à servir et un autre conteneur exécute httpd pour servir les fichiers. Maintenant, si ces deux conteneurs ont des définitions concurrentes pour uid, ce système sera au pire cassé, ou déficient au mieux. Les listes de contrôle d'accès définies n'auront aucun sens pour l'hôte, et elles seront probablement plus larges que nécessaire, ce qui signifie qu'il s'agit désormais d'un problème de sécurité. S'il vous plaît ne faites pas cela!! Faites-le de la bonne façon.

D'accord. Laisser le mappage entre l'UID et le conteneur est une solution suffisante. Je voulais juste que docker montre la voie par l'exemple et prenne en charge de tels mappages UID/GID dans les images docker officielles.

Résolu au moment de l' exécution , sans avoir à chown .

J'ai utilisé quelque chose de proche de la solution de @ncjones , mais je ne veux pas chown fichiers

Je crée un utilisateur dédié dans mon Dockerfile :

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

Je définis un script de démarrage dans mon Dockerfile :

CMD ["/run.sh"]

J'ai cette ligne dans mon script /run.sh :

usermod -u $USER_ID username

Maintenant, je peux choisir USER_ID démarrage du conteneur :

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

J'ai réussi à résoudre ce problème en utilisant les nouveaux arguments dockerfile. Cela ne nécessite rien de spécial une fois le conteneur construit, alors j'ai pensé partager. (Nécessite Docker 1.9)

Dans le 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} 

Ensuite pour construire :

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

Tout le reste est comme d'habitude :)

Éditer:
J'ai écrit ce post sur le mauvais problème (c'était un autre lié à boot2docker).
Désolé.

@pa-de-solminihac usermod -u $USER_ID username changera l'identifiant de l'utilisateur de username et déclenchera un changement de propriété des fichiers dans username 's HOME, mais chaque fichier précédemment possédé par username dehors de son HOME deviendront probablement illisibles/inscriptibles puisqu'ils appartiennent maintenant à un autre utilisateur

@riquito je l'utilise avec un utilisateur dédié, créé dans le Dockerfile :

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

Par conséquent, il n'y a pas de fichiers précédemment détenus par username . Donc je suppose qu'il n'y a pas de problème ;)

Pour info, setfacl ne fonctionne _pas_ sur les volumes remontant à 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

(Dans ce cas, /opt/test est hébergé depuis OS X via une machine Docker et Boot2Docker. Voir aussi boot2docker/boot2docker#581.)

@posita Utilisez -vous virtualbox pour héberger votre image de démarrage ? Si tel est le cas, cela peut en fait être une limitation de la façon dont virtualbox gère les dossiers partagés. J'ai eu beaucoup de mal à faire tout type de perméabilité régulière via le dossier partagé de la boîte virtuelle.

@ava-dylang, c'est un bon point. Ce qui précède se fait via Docker Machine avec le pilote Parallels , qui utilise l'implémentation des dossiers partagés natifs de Parallels, qui semble également limitée. (Voir également ce https://github.com/docker/machine/issues/13#issuecomment-164320881 concernant une proposition pour ces types d'environnements.)

FWIW, j'avais des problèmes avec la propriété des fichiers dans mon utilitaire, Scuba .

J'ai contourné le problème en ajoutant un script "init" qui crée un utilisateur dans le conteneur avec le même UID/GID que l'utilisateur appelant dans l'hôte. Voir JonathonReinhart/scuba#11 et JonathonReinhart/scuba#13.

Désormais, les fichiers créés dans le conteneur ressemblent exactement à ce qu'ils avaient été créés sur l'hôte.

_Mise à jour :_ Cela a causé des problèmes (JonathonReinhart/scuba#22). Au lieu de cela, je l'ai corrigé en générant mes propres /etc/passwd et amis, en fonction de l'uid/gid de l'utilisateur hôte, et je l'ai injecté dans le conteneur (voir JonathonReinhart/scuba#24).

+1

Pour le rendre plus maintenable et sécurisé lorsque l'hôte s'exécute en mode multi-locataire.

J'ai eu des problèmes d'autorisation avec de telles installations Wordpress, lorsque vous partagez l'intégralité de Wordpress de l'hôte au conteneur avec un volume.

Dans ma pile, j'ai une image de base, qui est une Debian avec mes modifications de base et chaque autre image sera construite à partir de cette image.

Dans l'image de base, j'ai cette partie :

### 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 n'est pas créé par les installations php ou nginx. C'est un utilisateur/groupe défini par défaut dans Debian et peut-être d'autres distributions. Certaines installations PHP, Nginx suggèrent d'utiliser cet utilisateur dans leurs fichiers de configuration.

Si l'UID/GID de votre utilisateur hôte est 500 (la plupart des UID/GID du premier utilisateur non root Linux par défaut sont 500 ou 1000), alors ce script change l'UID/GID de l'utilisateur www-data à 500 à partir de 33. De cette façon si vous partagez quoi que ce soit de l'hôte, Docker pense que ces fichiers et dossiers appartiennent à l'utilisateur www-data !

Dans vos fichiers de paramètres PHP-FPM, définissez également l'utilisateur et le groupe sur www-data .

Dans votre nginx Dockerfile, vous devez également définir ceci :

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

De cette façon, l'utilisateur nginx peut accéder aux fichiers appartenant à www-data (vous pouvez définir le nom d'utilisateur de nginx dans les fichiers de configuration nginx).

Après ce hack, mon installation Wordpress n'a AUCUN problème d'autorisation ! Tous les fichiers résident sur l'hébergeur + la mise à jour de Wordpress fonctionne parfaitement !

@DJviolin Je ne suis pas sûr qu'un problème comme celui-ci soit le bon endroit pour un tutoriel Wordpress, et j'hésite à l'expliquer ici. Cependant, pour les débutants malchanceux qui pourraient en quelque sorte trébucher sur ceci:

  1. Ce que vous avez posté fait beaucoup d'hypothèses sur l'installation - c'est-à-dire les valeurs UID/GID, les noms d'utilisateur et de groupe, etc. Ce n'est pas très portable entre les distributions.
  2. Plus important encore, donner un accès en écriture mondiale (0777) à l'ensemble de votre installation Wordpress est extrêmement dangereux et explicitement déconseillé dans la documentation officielle de WP. De plus, avec tout cela monté depuis l'hôte, vous venez d'autoriser des téléchargements arbitraires depuis Internet à écrire sur le système de fichiers _host_.

@jantman Désolé, mon mauvais. On dirait que le premier hack résout également les problèmes d'autorisation. Il n'est pas nécessaire de modifier les autorisations par défaut.

Évidemment, tout le monde doit trouver son UID d' utilisateur hôte

Jusqu'à ce que docker ne donne pas de solution à ce problème, les hypothèses resteront.

Ma solution est la même que celles de

Vous pouvez le faire en créant des volumes locaux, il vient d'atterrir dans le maître https://github.com/docker/docker/pull/20262.

Fermeture comme corrigé.

Salut, j'ai aussi dû faire une solution de contournement dans mon fichier docker :

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

puis dans start.sh

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

Comme $USER_ID peut être injecté en tant que paramètre d'environnement, il est possible d'utiliser cette image docker sans modification.

Quoi qu'il en soit, je pense qu'il devrait y avoir plus de fonctionnalités intégrées pour ce genre de choses et je me demande comment utiliser les volumes locaux suggérés par @calavera , quelqu'un peut-il fournir un exemple?

@keywan-ghadami J'étais aussi perplexe sur les volumes locaux. Le problème est que vous devez d'abord créer le système de fichiers (ou utiliser tmpfs). Il n'utilise donc pas /var/lib/docker. En fait, vous ne pouvez pas utiliser un sous-répertoire de _tout_ FS existant car les montages de liaison ne prennent pas en charge l'option uid . Je ne sais pas à quoi servent les volumes locaux ; vous pouvez également créer et monter le FS vous-même, puis utiliser un volume hôte normal ( -v my-created-fs:container-mount-point ).

Je suis assez en retard sur ce fil, mais ce problème a-t-il été résolu? Ce n'est pas clair à 100% à partir de tous les différents problèmes référencés ici. @brthor semble avoir la meilleure solution d'après ce que je peux voir, mais implique des options de ligne de commande qui pourraient plus facilement être simplement ajoutées dans le Dockerfile et effectuées en coulisses.

Pour moi, le codage en dur de l'UID et du GID est une mauvaise idée pour la portabilité entre les environnements et je ne vois pas la nécessité d'ajouter des arguments de ligne de commande chaque fois que je démarre un conteneur ou que je crée une image alors que cela pourrait être une simple option dans le Dockerfile. Ne pourrait-il pas y avoir une option simple dans le Dockerfile ou peut-être via docker-compose.yml où vous pouvez spécifier une sorte d'option "map uid from host"?

Il existe peut-être déjà une bonne solution, mais je ne peux pas vraiment la comprendre à partir de la documentation ou de ce fil.

Merci @alvinchevolleaux, je peux confirmer que nous utilisons avec succès la solution que j'ai publiée ci-dessus dans le CI pour https://github.com/dotnet/cli depuis des mois maintenant.

Recommandez-le!

@brthor Oui, c'est ce que j'ai export USER_ID=$(id -u) à mon .bash_profile donc tout est automatique pour mes différents environnements. Merci beaucoup.

Comme indiqué ci-dessus, lorsque vous partagez du contenu de votre dossier de départ dans un conteneur, ajoutez un compte d'utilisateur avec le même UID que le vôtre. Voici une astuce pour faire face si votre UID n'est pas 1000. Je suppose que chaque utilisateur crée sa propre image docker à partir du Dockerfile.

Votre Dockerfile doit contenir :

RUN useradd --uid 1000 -m vagrant
USER vagrant

La constante 1000 est remplacée par votre UID réel à l'aide d'un _git filter_. Exécutez ce qui suit sur votre hôte :

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

Enfin, ajoutez un fichier .gitattributes pour appliquer le filtre git :

Dockerfile filter=uidfix

Cela fonctionne en remplaçant 1000 par votre UID réel lorsque vous extrayez le Dockerfile en _smudging_ le fichier. Git va _nettoyer_ le fichier (en remettant 1000 ) lorsque vous commitez. Toutes les commandes exécutées dans le conteneur s'exécutent en tant qu'utilisateur vagrant avec l'UID correct.

Seams ce ticket devrait être rouvert car toutes les solutions fournies ici ne sont que des solutions de contournement
J'ai trouvé une bonne solution documentée et plus complète dans https://github.com/rocker-org/rocker/blob/master/rstudio/userconf.sh
Il utilise des arguments d'exécution qui permettent d'utiliser des images de pré-construction ce qui n'est pas possible avec le filtre git

@calavera je ne comprends pas ta solution.

par exemple

$ 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

Quand je regarde dans le répertoire /tmp/test, il n'y a pas de fichiers. Il ne semble pas que le dossier /tmp/test soit même en train d'être monté dans le conteneur... Il crée plutôt un volume de conteneur. Ce qui n'est pas vraiment ce que je veux.

Je ne trouve aucune documentation qui me dit quelles sont les options --opt valides. Donc, je suis vraiment en train de deviner comment cela est supposé fonctionner.

Veuillez rouvrir ce problème. Le nouveau pilote local ne semble pas du tout résoudre le problème du montage des répertoires hôtes locaux avec les identifiants d'utilisateur sélectionnés.

@calavera
Pouvez-vous s'il vous plaît commenter comment nous pouvons résoudre le problème des fichiers supprimés en tant que root avec des volumes hôtes locaux ? J'ai vu ce problème survenir fréquemment, en particulier lors de l'utilisation de docker pour les scénarios CI.

En regardant le PR lié, je ne vois rien d'évident immédiatement, mais je suis sûr qu'il me manque quelque chose

J'ai utilisé des variantes de cette solution de contournement dans mes conteneurs, telles que docbill/docker-force . Cependant, il me vient à l'esprit qu'une solution plus propre est un contenant qui n'est chargé que de faire la racine de courge...

Utiliser quelque chose comme bindfs pour local devrait aider. Vous pouvez l'exécuter avec -o map=$(id -u)/root:@$(id -g)/ @root (en supposant qu'il n'y a pas d'espace de nom d'utilisateur) et vous devriez voir les fichiers comme les vôtres en dehors du conteneur alors qu'ils appartiennent à racine à l'intérieur.

@ktosiek Merci, cela semble avoir du potentiel. Pourriez-vous publier un exemple complet de commande docker run ou de session de console ?

Quelqu'un pourrait-il publier une mise à jour de l'état de ce problème : a-t-il été fermé car « ne corrigera pas » ou cela a-t-il été réellement mis en œuvre ? Le fil est assez long, donc s'il vous plaît pardonnez-moi car je ne peux pas voir d'un coup d'œil quelle est la résolution.

@quinncomendant voir https://github.com/docker/docker/issues/7198#issuecomment -191990887
Signalez si cela ne fonctionne pas.

Merci @LK4D4.

Pour résumer, le problème a été résolu avec un correctif qui permet le montage opte pour le pilote de volume local .

Pour autant que je sache, il n'y a pas d'options pour définir l' utilisateur:groupe d'un _répertoire hôte monté en tant que volume_ (veuillez me corriger si cette option existe - c'est ce que je suis venu apprendre ici).

@quinncomendant correct ; lors du montage par liaison d'un répertoire hôte, vous souhaitez que le conteneur utilise les fichiers qui s'y trouvent tels quels, ce qui inclut les autorisations. Si vous souhaitez modifier ces autorisations, vous devez le faire sur l'hôte, avant de les monter en liaison

@quinncomendant Ou en termes plus simples, c'est un NE PAS CORRIGER .... Depuis le
la solution fournie ne fait rien pour résoudre le problème
signalé, et il n'y a pas non plus de plan pour résoudre ce problème.

Le 6 juillet 2016 à 17h20, Sebastiaan van Stijn [email protected]
a écrit:

@quinncomendant https://github.com/quinncomendant correct ; lorsque
bind-mounting un host-directory vous voulez que le conteneur utilise les fichiers qui
sont là tels quels, ce qui inclut les autorisations. Si vous voulez changer ces
autorisations, vous devez le faire sur l'hôte, avant de les lier

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/7198#issuecomment -230909967, ou couper le son
le fil
https://github.com/notifications/unsubscribe/ADBcWLihVjI1FoSMLKu7DyhwFOpGX0KKks5qTBwMgaJpZM4CQMjR
.

Cela semble être un problème NE RÉSOUDRA PAS. Il semble toujours que les aspects de _développement_ de la conteneurisation continuent d'être négligés et nous obligent toujours à écrire des hacks.

J'ai spécifiquement rencontré ce problème parce que les développeurs que je soutiens exécutent des commandes de génération de fichiers de projet depuis l'intérieur d'un conteneur et vers le volume monté sur l'hôte (l'installation de ces outils sur l'hôte va à l'encontre de l'objectif d'utiliser un conteneur, n'est-ce pas ?).

Ils veulent itérer rapidement sur ces fichiers, mais comme d'autres dans ce fil l'ont souligné, ils sont écrits en tant que uid/gid sous lequel le conteneur s'exécute, ce qui nécessite qu'ils soient correctement enregistrés sur l'hôte pour être manipulés davantage (par un IDE par exemple).

Il doit vraiment y avoir un moyen _spécifique au docker_ de caler dans un uid/gid temporaire dans ce genre de cas.

@boj C'est le scénario exact que j'ai rencontré lors du développement de Scuba . Ma solution actuelle crée, au démarrage, un utilisateur dans le conteneur avec le même uid/gid que l'utilisateur hôte. Ce n'est pas la solution la plus simple, mais ça marche bien.

@JonathonReinhart Merci, vous m'avez donné un peu d'inspiration.

J'ai fini par écrire un script wrapper appelé depuis l'hôte comme ceci (ils utilisent django dans ce cas):

# 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 Le problème potentiel avec cette solution ( -u $(id -u):$(id -g) ) est qu'il n'y a pas d'entrée dans /etc/passwd ou /etc/group pour cet uid/gid dans le conteneur : https://github .com/JonathonReinhart/scuba/issues/11

@JonathonReinhart Noté. Dans ce cas particulier, je me soucie uniquement des fichiers écrits sur l'hôte du développeur et du fait qu'ils ont les mêmes autorisations que l'utilisateur hôte.

Ne vous inquiétez pas de ce qui se passe réellement au moment de l'exécution, c'était tout ce dont j'avais vraiment besoin.

@JonathonReinhart

Si le logiciel dans le conteneur a besoin d'une entrée dans /etc/passwd ou /etc/group, rendez-les accessibles en écriture dans l'image, puis ajoutez-y les entrées nécessaires au démarrage.

Ainsi, la solution mentionnée par @JonathonReinhart (

Il semble que cela soit déjà pris en charge dans runc (https://github.com/opencontainers/runc/blob/8c9db3a7a5145f6b26c8051af319eee6f72c9ca8/libcontainer/configs/config.go#L19-24). Dans Docker, il y a la configuration userns-remap pour le démon, ici nous aurions essentiellement besoin de l'avoir plus fine (au niveau du conteneur au lieu du niveau du démon), y a-t-il un intérêt / un plan pour soutenir cela?

Ce docker-compose.yml ne fonctionne pas :

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

Quelqu'un peut me dire pourquoi ? Je suis les directives officielles : https://docs.docker.com/engine/reference/commandline/volume_create/#/driver -specific-options

Est-il possible d'attacher des volumes nommés à partir de l'hôte ? Avec driver_opts vous pouvez définir uid (et peut-être gid ?).

+1

+1

@lazyuser @xiaods Veuillez arrêter avec les +1. Il n'accomplit rien d'autre que de spammer tous ces ---> participants.

@bamarni Oui, je pense que la nouvelle fonctionnalité d'espace de noms utilisateur peut résoudre ce problème, mais comme vous l'avez dit, elle devrait être implémentée par conteneur. Le résultat final serait : Un conteneur s'exécute comme ce qu'il pense être "root", mais est en fait l'UID/GID transmis sur la ligne de commande docker run . Les fichiers "sortiraient" alors du conteneur appartenant à l'utilisateur approprié.

@lazyuser @xiaods @JonathonReinhart vous devriez plutôt cliquer sur le bouton +1 sous la description du problème

Ou cliquez simplement sur s'abonner à droite si vous ne voulez que des notifications...

@JonathonReinhart : certainement, j'ai revu la doc mais malheureusement avoir le démon de mappage à l'échelle au lieu de par conteneur était une décision consciente en raison d'une limitation :

Remarque : La restriction de mappage unique par démon est en place pour le moment car Docker partage les couches d'images de son cache local sur tous les conteneurs exécutés sur l'instance de moteur. Étant donné que la propriété du fichier doit être la même pour tous les conteneurs partageant le même contenu de couche, la décision a été prise de mapper la propriété du fichier sur docker pull aux mappages d'utilisateur et de groupe du démon afin qu'il n'y ait aucun délai pour l'exécution des conteneurs une fois le contenu téléchargé. Cette conception préserve les mêmes performances pour docker pull, docker push et démarrage de conteneur que les utilisateurs attendent avec les espaces de noms d'utilisateur désactivés.

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

Cher @JonathonReinhart , @pa-de-solminihac et @nalipaz ,
Merci pour vos efforts pour m'éduquer et éduquer les autres à ne pas laisser de commentaires sans rapport avec le problème en faisant exactement cela ! Pour info, Github ne permet pas de rechercher des problèmes auxquels un abonné est abonné sans au moins les commenter. Pour plus d'informations, voir https://github.com/isaacs/github/issues/283. Ironiquement, le problème de Github a presque le même âge que celui de Docker, et les deux semblent avoir la même priorité.

À tous, désolé pour le spam. La première fois, il s'agissait d'une solution de contournement pour le bogue github susmentionné, et cette fois, je n'ai tout simplement pas pu résister à l'ironie de la situation.

J'ai résolu ce problème en utilisant inotifywait . Vous devrez installer inotify-tools pour l'exécuter dans votre image docker. Il est possible de l'exécuter sur votre système hôte à la place, mais je voulais une solution portable.

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

Cela fonctionne en demandant à inotifywait de surveiller tout nouveau fichier ou répertoire créé dans le répertoire /mount. Lorsqu'il en remarque un, il change la propriété du même utilisateur et groupe que le dossier /mount. J'ai utilisé la représentation entière des deux, au cas où l'utilisateur/groupe hôte n'existerait pas dans le conteneur. À l'intérieur du conteneur, peu importe à qui il appartient, car tout s'exécute en tant que root. En dehors du conteneur, le système de fichiers hôte affiche la même propriété que le répertoire monté sur /mount.

Je l'ai délibérément conçu pour définir uniquement la propriété des fichiers et répertoires nouvellement créés, afin de préserver la propriété des fichiers et répertoires préexistants. C'est plus sûr que d'effacer tout cela avec une instruction chown -R à chaque fois que le système de fichiers est monté. Si des autorisations uniformes fonctionnent pour votre projet et que vous souhaitez une solution plus simple et plus efficace, consultez inotify-hookable .

Attention : étant donné qu'une montre inotify sera établie par sous-répertoire, il est possible que le nombre maximum de montres inotify par utilisateur soit atteint. Le maximum par défaut est 8192 ; il peut être augmenté en écrivant dans /proc/sys/fs/inotify/max_user_watches.

@codekitchen-ws Autre avertissement : un fichier peut être déplacé après sa création et avant le changement de propriétaire. Selon le shell, vous voudrez également citer "$f" (pour éviter le fractionnement des mots dans le chemin).

+1

@briansrepo C'est une approche intéressante. S'il s'agit d'une instruction Dockerfile RUN , cela s'exécute au moment de la construction. Comment pourrait-il connaître l'utilisateur docker run au moment de l'exécution ?

@btiernay Merci ! Il n'utilise pas l'UID de l'utilisateur qui a déclenché l'image. Il copie spécifiquement l'utilisateur hôte et le groupe d'hôtes de tout répertoire hôte monté sur /mount. Il ne regarde aucun autre fichier ou sous-répertoire. Il appartient à l'utilisateur de s'assurer que les autorisations sont définies sur quelque chose sur lequel il peut écrire sur le système hôte.

Exemple : Supposons que le répertoire hôte /var/www/html appartient à brian:www-data. Vous lancez une image qui monte le répertoire système hôte /var/www/html dans le répertoire image /mount. Ensuite, vous créez /mount/index.html depuis l'intérieur de l'image. Si vous allez vérifier la propriété de /var/www/html/index.html sur le système hôte, il appartiendra à brian:www-data.

Sur la base de cet exemple, supposons que vous ayez un répertoire hôte /var/www/html/upload appartenant à www-data:www-data. Gardez à l'esprit que le répertoire hôte monté /var/www/html appartient toujours à brian:www-data. Allez maintenant dans l'image et créez /mount/upload/file.pdf. Si vous vérifiez le fichier hôte /var/www/html/upload/file.pdf, il appartiendra à brian:www-data , et non à www-data:www-data , car le répertoire hôte monté /var/www/html est propriété de brian:www-data. Avoir du sens ?

TL;DR : vous passez l' utilisateur:groupe que vous souhaitez utiliser en chown le répertoire hôte monté à utilisateur:groupe.

@briansrepo merci pour l'explication. Tout cela a du sens, mais je ne comprends toujours pas comment cela peut fonctionner à l'intérieur d'un RUN . Je pense que cela devrait s'exécuter en arrière-plan lorsque le conteneur est exécuté (c'est- docker run dire

@btiernay J'aime aussi cette idée.
@briansrepo au moins, cela couvre ce qui se passe à partir des conteneurs.
Le processus de construction peut toujours être abordé avec quelque chose comme

RUN usermod -u 1000 www-data

Ce sont quand même des solutions de contournement.

Dans ma pile LEMP, j'ai cette préconfiguration Nginx dans mon Dockerfile de 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

Il s'agit d'un hack où tous les fichiers nouvellement créés à partir d'une session ssh hôte obtenant l'uid, le gid de 500 et nginx n'auront finalement pas accès à ces fichiers (car l'utilisateur ou le groupe avec l'id de 500 n'existait pas dans le conteneur). Vous pouvez vérifier quel uid, quel numéro de gid vous devez créer pour votre utilisateur www-data lorsque vous copiez de nouveaux fichiers dans le volume partagé sur l'hôte à partir d'une session ssh et plus tard vous docker exec dans ce conteneur et en regardant les fichiers l'uid, gid.

Le problème que j'ai trouvé, si je copiais de nouveaux fichiers dans le dossier partagé sur la machine hôte (auquel vous avez accédé par une session ssh, comme dans une instance CoreOS sur DigitalOcean), Nginx n'a pas accès à ces fichiers nouvellement créés. Donc, si vous voulez une compatibilité absolue avec les privilèges, vous devez partager vos fichiers de serveur Web dans le conteneur Docker lors de la création des conteneurs (au moins c'était le cas il y a 1 an, lorsque je rencontre ces problèmes uid, gid avec les volumes partagés) .

OU vous pouvez également installer le service ssh dans le conteneur docker qui partage les fichiers avec le conteneur nginx, de cette façon, si vous copiez/modifiez des fichiers, ils obtiennent le bon uid, gid. Mais cela contre les bonnes pratiques de Docker que vous devriez utiliser docker inspect au lieu de sessions ssh, car "Docker n'est pas une VM" (ce serait une solution trop facile, non ?).

À mon avis, un conteneur Docker devrait agir comme un service ou un exécutable et ne devrait pas prendre en otage les fichiers de mon serveur Web si je ne le souhaite pas. La base de données est un type de chose différent (parfois), mais je ne vois pas pourquoi il ne serait pas possible d'obtenir la même infrastructure de conteneurs du Saint Graal, où tous vos fichiers de base de données statiques, de serveur Web et de base de données vivent en dehors des conteneurs (mais les conteneurs peuvent modifiez-les (comme supprimer, créer, modifier) ​​et vous pouvez également les modifier sans aucun problème de privilège de la part de l'hôte.

Avec docker volume create --opt vous pouvez définir uid, gid, mais ce n'est pas vrai pour docker-compose : https://github.com/docker/compose/issues/3715

Nous avons vraiment besoin d'une solution multiplateforme (pas gosu) pour mapper uid/gid. Ce problème à lui seul cause d'énormes dommages à la façon dont docker est perçu par les novices.

Nous avons créé une solution de contournement pour ce problème qui modifie les autorisations d'utilisateur/groupe et de fichier d'un conteneur Docker qui ont été définies au moment de la construction sur l'UID/GID avec lequel le conteneur a été démarré au moment de l'exécution.

Le projet et les instructions d'installation se trouvent sur : https://github.com/boxboat/fixuid

Exemple : Le conteneur Docker a été créé en utilisant l'utilisateur/groupe dockeruser:dockergroup comme UID/GID 1000:1000 . L'hôte s'exécute en tant qu'UID/GID 1001:1002 . L'image est exécutée avec docker run -u 1001:1002 . fixuid :

  • changer dockeruser UID en 1001
  • changer dockergroup GID en 1002
  • changer toutes les autorisations de fichier pour l'ancien dockeruser:dockergroup en 1001:1002
  • mettre à jour $HOME à l'intérieur du conteneur vers dockeruser $HOME
  • maintenant le conteneur et l'UID/GID de l'hôte correspondent et les fichiers créés dans le conteneur sur les montages de l'hôte correspondront

Il peut s'exécuter en tant que ENTRYPOINT ou dans le cadre d'un script de démarrage. Il est installé dans le conteneur en tant que binaire appartenant à root avec le bit setuid , et élève les privilèges pour apporter les modifications appropriées. Il ne doit être utilisé que dans des conteneurs de développement.

Si cela s'avère utile, le moteur Docker peut être en mesure d'incorporer tout ou partie de la logique via des indicateurs dans docker run

Résolu en utilisant docker volume .

@hashar comment ? pouvez-vous donner un exemple svp

alors n'y a-t-il toujours pas de solution à cela autre que d'utiliser gosu et un script de point d'entrée ?!

Pour l'instant, il semble qu'il existe 2 options pour contourner ce problème, jusqu'à ce que l'équipe Docker fasse une mise à jour officielle à ce sujet.

Dommage que ce soit toujours un problème. En théorie, il existe userns-remap mais ce n'est pas convivial.

Cette page vous a été utile?
0 / 5 - 0 notes