Qu'est-ce que la (meilleure) façon de gérer les autorisations pour Docker volumes partagés?
J'ai été jouer avec un menu fixe pour un certain temps et de garder sur la recherche de la même chose lorsque l'on traite des données persistantes.
J'ai créer mon Dockerfile
et exposer un volume ou de l'utilisation --volumes-from
à monter un dossier à l'intérieur de mon conteneur.
Quelles autorisations faut-il saisir le volume partagé sur l'ordinateur hôte?
Je pense à deux options:
-
Jusqu'à présent, j'ai permis à chacun d'avoir accès en lecture/écriture, donc je peux écrire dans le dossier du conteneur Docker.
-
Carte, les utilisateurs de l'ordinateur hôte dans le récipient, de sorte que je peux attribuer des autorisations plus précises. Pas sûr que cela est possible et n'ai pas trouvé grand chose à ce sujet. Jusqu'à présent, tout ce que je peux faire est de lancer le conteneur comme certains d'utilisateur:
docker run -i -t -user="myuser" postgres
, mais cet utilisateur a un autre UID que mon hôtemyuser
, si bien que les autorisations ne fonctionnent pas. Aussi, je ne suis pas sûr si le mappage des utilisateurs de poser des risques de sécurité.
Existe-il d'autres alternatives?
Comment êtes-vous les gars et les filles qui s'occupent de ce problème?
- Caisse la réponse d'une question similaire.
- Vous pourriez également être intéressé par ce fil qui traite de ce sujet en détail: groups.google.com/forum/#!msg/panneau de l'utilisateur/cVov44ZFg_c/...
- Avez-vous vu container42.com/2014/11/18/data-only-container-madness?
- Pour le moment, le Support de l'équipe n'est pas de la planification à mettre en œuvre une solution native pour le montage d'accueil-répertoires d'un volume avec des uid/gid. Voir mon commentaire et de réponses sur ce sujet: github.com/docker/docker/issues/7198#issuecomment-230636074
Vous devez vous connecter pour publier un commentaire.
Mise à JOUR 2016-03-02: Comme de Docker 1.9.0, Docker a nommé volumes qui remplacer les données de la seule conteneurs. La réponse ci-dessous, ainsi que mon lié billet de blog, a encore de la valeur dans le sens de comment penser les données à l'intérieur de docker mais pensez à utiliser nommé volumes à mettre en œuvre le modèle décrit ci-dessous, plutôt que de conteneurs de données.
Je crois que la manière canonique de résoudre ce problème est en utilisant les données seulement des conteneurs. Avec cette approche, tous les accès aux données du volume via les conteneurs qui utilisent
-volumes-from
le conteneur de données, afin que l'hôte uid/gid n'a pas d'importance.Par exemple, un cas d'utilisation donné dans la documentation est la sauvegarde d'un volume de données. Pour ce faire, un autre conteneur est utilisé pour faire la sauvegarde via
tar
, et il utilise-volumes-from
afin de monter le volume. Donc, je pense que le point clé de grok est: plutôt que de penser comment faire pour obtenir l'accès aux données sur l'hôte avec les autorisations appropriées, pensez à la façon de faire tout ce dont vous avez besoin, les sauvegardes, la navigation, etc. -- via un autre récipient. Les conteneurs eux-mêmes besoin d'utiliser cohérente uid/gid, mais ils n'ont pas besoin de carte pour quoi que ce soit sur l'ordinateur hôte, ce qui est portable.C'est relativement nouveau pour moi, mais si vous avez un cas d'utilisation particulier n'hésitez pas à commenter et je vais essayer d'étoffer la réponse.
Mise à JOUR: Pour le cas d'utilisation dans les commentaires, vous pourriez avoir une image
some/graphite
pour exécuter graphite, et une imagesome/graphitedata
que le conteneur de données. Donc, en ignorant les ports et ces,Dockerfile
de l'imagesome/graphitedata
est quelque chose comme:Construire et de créer le conteneur de données:
La
some/graphite
Dockerfile devrait également obtenir le même uid/gid, par conséquent, il pourrait ressembler à quelque chose comme ceci:Et il serait de fonctionner comme suit:
Ok, maintenant que nous donne notre graphite conteneur et de données associées,-seul un récipient avec le bon utilisateur/groupe (remarque vous pouvez ré-utiliser le
some/graphite
conteneur pour le conteneur de données ainsi, en substituant les entrypoing/cmd lors de l'exécution, mais le fait d'avoir que des images distinctes de l'OMI est plus clair).Maintenant, disons que vous souhaitez modifier quelque chose dans le dossier de données. Donc, plutôt que de lier le montage du volume de l'hôte et de l'édition il y, créer un nouveau conteneur pour faire ce travail. Appelons cela
some/graphitetools
. Permet également de créer des utilisateur/groupe, tout comme lesome/graphite
image.Vous pourriez faire de ce SEC en héritant de
some/graphite
ousome/graphitedata
dans le Dockerfile, ou au lieu de créer une nouvelle image, tout simplement ré-utiliser l'un de ceux déjà existants (en ignorant point d'entrée/cmd en tant que de besoin).Maintenant, il vous suffit d'exécuter:
et puis
vi /data/graphite/whatever.txt
. Cela fonctionne parfaitement, parce que tous les conteneurs ont les mêmes graphite utilisateur avec appariement des uid/gid.Puisque vous ne jamais monter
/data/graphite
à partir de l'hôte, vous ne se soucient pas de savoir comment l'hôte uid/gid cartes à l'uid/gid définie à l'intérieur de lagraphite
etgraphitetools
conteneurs. Ces conteneurs peuvent désormais être déployées à tout hôte, et ils vont continuer à fonctionner parfaitement.La chose intéressante à ce sujet est que
graphitetools
pourrait avoir toutes sortes d'informations utiles des services publics et des scripts, que vous pouvez maintenant également déployer d'une manière portable.Mise à JOUR 2: Après avoir écrit cette réponse, j'ai décidé d'écrire un plus complet post de blog sur cette approche. J'espère que cela aide.
Mise à JOUR 3: j'ai corrigé cette réponse et a ajouté plus de détails. Elle contenait auparavant des hypothèses erronées au sujet de la propriété et permanentes -- la propriété est généralement attribué à la création d'un volume heure c'est à dire dans le conteneur de données, parce que c'est lorsque le volume est créé. Voir ce blog. Ce n'est pas une obligation si -- vous pouvez simplement utiliser le conteneur de données de référence/de la poignée" et définissez la propriété/perms dans un autre récipient au moyen d'un chown dans un point d'entrée, qui se termine avec gosu pour exécuter la commande que l'utilisateur approprié. Si quelqu'un est intéressé par cette démarche, s'il vous plaît commentaire et je peut fournir des liens vers d'un échantillon à l'aide de cette approche.
/data/graphite
,/data/cabot
etc. Dans les deux cas, le montage du volume directement et par l'intermédiaire d'un données uniquement conteneur, je suis incertain sur ce que les autorisations à appliquer lors de la création d'un nouveau dossier de données pour, disons, une nouvelle JIRA instance de test./data/newcontainer
? Je suppose que vous exécutezdocker
en tant que root (est-il possible de ne pas le faire?) Aussi, est-il une différence dans les autorisations si les données sont montés directement dans le conteneur principal ou par le biais d'un données uniquement conteneur?/var/lib/docker
quelque part, mais toujours un énorme douleurgit clone
dans le volume accessible via--volume-from
un conteneur de données...docker run
avec--volumes-from=graphitedata
laVOLUME /data/graphite
déclaration dans le Dockerfile est redondant, si pas même une collision (je n'ai pas trouvé un cahier des charges correspondant dans les docs). J'ai constaté le problème suivant: lors de l'utilisation de--volumes-from=graphitedata
, le volume correspondant est disponible dans le conteneur cible avec le même point de montage comme utilisé dans la base de données seulement un conteneur, sans avoir deVOLUME
entrée dans le Dockerfile pour le conteneur cible.-v
. Ce dernier est équivalent àVOLUME
dans le Dockerfile, et se lie à un volume de conteneur. L'ancien raconte le Panneau de monter le volume de la spécifié (différent) du conteneur.--volumes-from=graphitedata
lie le volume dans votre récipient jusqu'à un certain point de montage. Ce point de montage se trouve être/data/graphite
, parce que c'est la façon dont vous avez défini vos données uniquement conteneur. Mais vous aussi utiliserVOLUME /data/graphite
dans votre conteneur. C'est redondant et c'est même pas clair que le comportement spécifié pour cette situation devrait être.--volumes-from
remplace le VOLUME de la déclaration dans le conteneur, mais je vais mettre à jour la réponse à la suppression de la "collision".training/postgres
image est utilisée à la fois pour créer le volume et le monter à partir d'un autre conteneur via--volumes-from
). Je tiens à ajouter le descripteur de VOLUME de la consommation conteneur ainsi parce qu'il documents l'exigence de volume, mais laisse la décision de l'endroit où le volume vient de l'ops de l'équipe au moment de l'exécution.-u 1000
serait moins hacky, et ne permettrait pas au début, si votre "conforme ID" est en conflit.Très élégante, une solution peut être vu sur le site officiel redis image et en général dans toutes les images.
Décrit dans l'étape-par-étape du processus:
Comme on le voit sur Dockerfile commentaires:
gosu est une alternative de
su
/sudo
pour une simple étape vers le bas à partir de la racine de l'utilisateur. (Redis est toujours fonctionner avecredis
utilisateur)/data
volume et la définir comme workdirPar la configuration de l' /volume de données avec le
VOLUME /data
de commande, nous avons maintenant un volume distinct qui peut être soit le panneau de volume ou de bind-monté sur un hôte dir.La configuration en tant que le workdir (
WORKDIR /data
) rend le répertoire par défaut dans lequel les commandes sont exécutées à partir d'.Cela signifie que tous les conteneur des exécutions sera exécuté par le menu fixe-point d'entrée de script, et par défaut, la commande à exécuter est redis-server.
docker-entrypoint
est un script qui effectue une fonction simple: Changer le propriétaire du répertoire courant (/data) et de l'étape vers le bas à partir deroot
àredis
à l'utilisateur d'exécuterredis-server
. (Si la commande en cours d'exécution n'est pas redis-server, exécutez la commande directement.)Ceci a l'effet suivant
Si le répertoire " /data est lier monté à l'hôte, le menu fixe-point d'entrée sera de préparer les autorisations de l'utilisateur avant d'exécuter le redis-server sous
redis
utilisateur.Cela vous donne la facilité de l'esprit qu'il n'y a aucune installation pour fonctionner, le conteneur dans toute configuration de volume.
Bien sûr, si vous avez besoin de partager le volume entre les différentes images dont vous avez besoin pour vous assurer qu'ils utilisent le même nom d'utilisateur/groupid sinon le dernier conteneur va détourner les autorisations de l'utilisateur à partir de la précédente.
Ce n'est sans doute pas le meilleur façon pour la plupart des circonstances, mais il n'est pas encore été mentionnés donc peut-être que cela aidera quelqu'un.
Lier mont volume hôte
Host folder FOOBAR is mounted in container /volume/FOOBAR
Modifier votre contenant du script de démarrage pour trouver le GID du volume vous intéresse
$ TARGET_GID=$(stat -c "%g" /volume/FOOBAR)
Assurer que votre utilisateur appartient à un groupe avec ce GID (vous pourriez avoir à créer un nouveau groupe). Pour cet exemple, je vais faire semblant de mon logiciel s'exécute en tant que
nobody
utilisateur lorsqu'à l'intérieur du conteneur, donc je veux m'assurernobody
appartient à un groupe avec un id de groupe égal àTARGET_GID
J'aime cela parce que je peux facilement modifier les autorisations de groupe sur mon hôte, des volumes et de savoir que ceux mis à jour autorisations s'appliquent à l'intérieur du conteneur docker. Cela se produit sans la permission ou la propriété des modifications à mon hôte de dossiers/fichiers, ce qui me rend heureux.
Je n'aime pas cela parce qu'il assume qu'il y a pas de danger à ajouter vous-même à l'arbitraire d'un des groupes à l'intérieur du conteneur qui se trouvent être en utilisant un GID vous le souhaitez. Il ne peut pas être utilisé avec un
USER
clause dans un Dockerfile (à moins que l'utilisateur dispose des privilèges root, je suppose). Aussi, il hurle hack travail 😉Si vous voulez être hardcore vous pouvez évidemment prolonger de plusieurs façons - par exemple, rechercher tous les groupes sur tous les sous-fichiers, plusieurs volumes, etc.
$TARGET_GID
serait d'utilisergrep ':$TARGET_GID:'
, sinon, si le contenant a, par exemple, gid 10001 et votre hôte est de 1000, cette vérification va passer, mais il ne devrait pas.Ok, c'est maintenant suivis au docker question n ° 7198
Pour l'instant, je m'occupe de cela à l'aide de votre seconde option:
Dockerfile
CLI
Mise à JOUR actuellement, je suis plus enclin à Hamy réponse
id -u <username>
,id -g <username>
,id -G <username>
pour obtenir l'id utilisateur et id de groupe d'un utilisateur spécifique au lieuEssayez d'ajouter une commande à Dockerfile
crédits va à https://github.com/denderello/symfony-docker-example/issues/2#issuecomment-94387272
La même chose que vous, je cherchais un moyen de mapper les utilisateurs/groupes à partir de l'hôte de conteneurs docker et c'est le chemin le plus court que j'ai trouvé jusqu'à présent:
Ceci est un extrait de mon menu fixe-composer.yml.
L'idée est de monter (en mode lecture seule) des utilisateurs/groupes de listes à partir de l'hôte dans le conteneur ainsi, après le récipient démarre il aura le même uid->nom d'utilisateur (ainsi que pour les groupes), les couplages avec l'hôte. Maintenant, vous pouvez configurer un utilisateur/groupe de paramètres de votre service à l'intérieur du conteneur, comme si c'était de travailler sur votre système hôte.
Lorsque vous décidez de mettre votre récipient à un autre hôte, vous avez juste besoin de changer le nom d'utilisateur dans le fichier de configuration du service de ce que vous avez sur l'hôte.
-u $( id -u $USER ):$( id -g $USER )
et vous n'avez plus à vous soucier du nom d'utilisateur. Cela fonctionne bien pour les locaux dev environnements où vous souhaitez générer des fichiers (binaires par exemple) à laquelle vous avez accès en lecture/écriture par défaut.Ici est une approche qui utilise encore un seul conteneur, mais n'en a pas besoin pour être synchronisés avec le conteneur de l'application (en termes d'avoir le même uid/gid).
Sans doute, vous voulez exécuter une application dans le conteneur en tant que non-root $UTILISATEUR sans un shell de connexion.
Dans le Dockerfile:
Puis, dans entrypoint.sh:
Pour sécuriser et changement de la racine pour docker un conteneur docker hôte essayez d'utiliser
--uidmap
et--private-uids
optionshttps://github.com/docker/docker/pull/4572#issuecomment-38400893
Aussi, vous pouvez supprimer plusieurs capacités (
--cap-drop
) dans le panneau de conteneurs pour la sécuritéhttp://opensource.com/business/14/9/security-for-docker
Mise à JOUR soutien devrait venir en
docker > 1.7.0
Mise à JOUR Version
1.10.0
(2016-02-04) ajouter--userns-remap
drapeauhttps://github.com/docker/docker/blob/master/CHANGELOG.md#security-2
--uidmap
ni la--private-uids
options. Dirait que le PR n'a pas et n'a pas été fusionnées.Docker version 1.7.0, build 0baf609
"We apparently do have so some of conflicting designs between libnetwork and user namespaces ... and something we'd like to get in for 1.8.0. So don't think we're dropping this, we're definitely going to take a break after all these, and see how we need to reconsider the current design and integration of libnetwork to make this possible. Thanks!"
github.com/docker/docker/pull/12648 je pense Donc que nous devrions nous attendre la prochaine version stable.--userns-remap
ne fonctionne pas encore, dansDocker version 1.10.3, build 20f81dd
. Voir mon commentaire ici.Image De Base
Utiliser cette image: https://hub.docker.com/r/reduardo7/docker-host-user
ou
Important: ce qui détruit conteneur de portabilité entre les hôtes.
1)
init.sh
2)
Dockerfile
3) run.sh
4) Construire avec
docker
4) lancez-vous!
Mon approche est de détecter actuel UID/GID, puis de créer l'utilisateur/de groupe à l'intérieur du conteneur et exécuter le script sous lui, alors tous les fichiers, il va créer va correspondre à l'utilisateur qui lance le script:
Dans mon cas précis, j'ai essayé de construire mon node package avec le nœud de menu fixe de l'image, de sorte que je n'aurais pas à installer la ngp sur le serveur de déploiement. Il a bien fonctionné jusqu'à ce que, à l'extérieur le récipient et sur la machine hôte, j'ai essayé de déplacer un fichier dans le répertoire node_modules que le nœud de menu fixe l'image avait créé, à laquelle j'ai refusé les autorisations, car il a été possédé par la racine. J'ai réalisé que je pouvais contourner ce problème en copiant le répertoire le contenant sur la machine hôte. Via docker docs...
C'est du bash code que j'ai utilisé pour changer le propriétaire du répertoire créé par et à l'intérieur du conteneur docker.
Si nécessaire, vous pouvez supprimer le répertoire avec un deuxième conteneur docker.
Dans le dossier de partage entre le panneau d'accueil et conteneur docker, essayez de commande ci-dessous
Le drapeau-v monte le répertoire de travail en cours dans le récipient. Lorsque le répertoire de l'hôte d'un bind-volume monté n'existe pas, Docker va automatiquement créer ce répertoire sur l'ordinateur hôte pour vous,
Cependant, il y a 2 problèmes que nous avons ici:
Solution:
Conteneur:
créer un utilisateur de dire "testuser", par id d'utilisateur par défaut sera à partir de 1000,
De l'hôte:
créer un groupe de dire "testgroup" avec l'id de groupe de 1000, et chown le répertoire du groupe(testgroup
Si vous utilisez le Panneau de Composer, démarrer le conteneur en previleged mode: