Moby: Ajouter la possibilité de monter le volume en tant qu'utilisateur autre que root

Créé le 17 oct. 2013  ·  157Commentaires  ·  Source: moby/moby

Cas d'utilisation : montez un volume de l'hôte vers le conteneur pour une utilisation par apache en tant qu'utilisateur www.
Le problème est que tous les montages sont actuellement montés en tant que root à l'intérieur du conteneur.
Par exemple, cette commande
docker run -v /tmp:/var/www ubuntu stat -c "%U %G" /var/www
imprimera "racine racine"

Je dois le monter en tant qu'utilisateur www à l'intérieur du conteneur.

areapi arekernel arevolumes exexpert kinenhancement

Commentaire le plus utile

Puis-je dire non - forçant les utilisateurs à ajouter un script d'assistance qui ne

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

(merci @bfirsh pour votre exemple)

est assez terrible.

Cela signifie que le conteneur doit être démarré en tant que root, plutôt que de s'exécuter en tant qu'utilisateur redis prévu. (comme @aldanor y a fait allusion)

et cela signifie qu'un utilisateur ne peut pas faire quelque chose comme :

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

Tous les 157 commentaires

Si vous chown le volume (côté hôte) avant de le monter par liaison, cela fonctionnera.
Dans ce cas, tu pourrais faire :

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

(En supposant que 101:101 est l'UID:GID de l'utilisateur www-data dans votre conteneur.)

Une autre possibilité est de faire le bind-mount, puis chown à l'intérieur du conteneur.

@mingfang Chown ne fonctionnera-t-il pas pour vous ?

Il serait utile d'avoir un raccourci pour cela. Je me retrouve souvent à écrire des scripts run qui définissent simplement les autorisations sur un volume :

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

Que faire si vous n'avez pas les droits sur chown ?

Un script d'aide qui chown le volume résoudrait-il ce problème ? Ce script peut être le ENTRYPOINT de votre Dockerfile.

Puis-je dire non - forçant les utilisateurs à ajouter un script d'assistance qui ne

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

(merci @bfirsh pour votre exemple)

est assez terrible.

Cela signifie que le conteneur doit être démarré en tant que root, plutôt que de s'exécuter en tant qu'utilisateur redis prévu. (comme @aldanor y a fait allusion)

et cela signifie qu'un utilisateur ne peut pas faire quelque chose comme :

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

Il existe _un_ moyen de le faire fonctionner, mais vous devez vous préparer à l'avance dans votre Dockrfile.

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

(Je n'ai pas testé cet exemple, je travaille sur un container chromium qui s'affiche ensuite sur un container X11 _séparé_ qui.... )

Et bien sûr, cette méthode ne fonctionne que pour les nouveaux volumes directs, pas pour lier
montés ou volumes-de volumes. ;)

De plus, plusieurs conteneurs utilisant volumes-from auront des uid/gid différents pour le même utilisateur, ce qui complique également les choses.

@SvenDowideit @tianon cette méthode ne fonctionne pas non plus. Exemple complet :

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

Deux exécutions, avec et sans volume -v :

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

Nous rencontrons un problème qui serait résolu par cela (je pense). Nous avons un partage NFS pour les répertoires personnels de nos développeurs. Les développeurs veulent monter /home/dev/git/project dans Docker mais ne le peuvent pas car nous avons activé Root Squash.

Cela interdit à root d'accéder /home/dev/git/project donc quand j'essaie d'exécuter le montage de docker /home/dev/git/project j'obtiens une erreur lstat permission denied .

@frankamp C'est parce que la préférence actuelle de Docker est de ne pas modifier les éléments hôtes qui ne sont pas sous le contrôle de Docker.

Votre définition "VOLUME" est écrasée par votre -v pwd`:/var/lib/reds`.
Mais dans votre 2ème exécution, il utilise un volume contrôlé par docker, qui est créé dans /var/lib/docker. Lorsque le conteneur démarre, docker copie les données de l'image dans le volume, puis chown le volume avec l' uid:gid du répertoire pour lequel le volume a été spécifié.

Je ne suis pas sûr qu'il y ait beaucoup à faire ici, et malheureusement, les montages liés ne prennent pas en charge (pour autant que je sache) le montage en tant qu'uid/gid différent.

Ma solution à cela était de faire ce que SvenDowideit a fait ci-dessus (créer un nouvel utilisateur et chown à l'avant dans dockerfile), mais ensuite au lieu de monter le volume hôte, utiliser un conteneur de données uniquement et copier le volume hôte que je voulais monter dans le conteneur avec tar cf - . | docker run -i --volumes-from app_data app tar xvf - -C /data . Cela deviendra un peu plus facile une fois https://github.com/docker/docker/pull/13171 fusionné (et docker cp fonctionne dans les deux sens), mais cela pourrait peut-être devenir une alternative à -v host_dir:container_dir , c'est-à-dire. peut-être -vc host_dir:container_dir , (vc pour volume-copy), dans lequel le contenu de host_dir serait copié dans le conteneur de données. Bien que je ne puisse pas dire que je comprends pourquoi/comment les fichiers copiés héritent des autorisations de l'utilisateur du conteneur, d'après ce que je peux dire, et c'est la seule solution raisonnable que j'ai réussi à trouver qui ne détruit pas la portabilité.

Qu'en est-il de l'ACL ?

Existe-t-il un correctif ou une solution de contournement ? Je rencontre le même problème avec OpenShift, le dossier monté appartient à root: root et les images précréées ne fonctionneront pas.

Je cherche aussi une solution de contournement. Si tous les volumes montés appartiennent à root , il est impossible d'exécuter vos conteneurs Docker avec un utilisateur autre que root .

Eh bien, vous pouvez essayer s6-overlay . Il comprend des fonctionnalités spécifiquement ciblées pour aider à contourner ce type de problèmes.

@dreamcat4 : Merci pour le pointeur. La propriété et les autorisations de fixation semblent être une solution de contournement intéressante, mais ne devrais-je pas exécuter mon conteneur Docker en tant que root pour que cela fonctionne ?

@ brikis98 Oui c'est vrai. Cependant, s6-overlay possède également une autre fonctionnalité, qui vous permet de supprimer à nouveau les autorisations lors du lancement de vos serveurs / démons.

@ dreamcat4 Ah, j'ai compris, merci.

J'ai le même uid/gid à l'intérieur et à l'extérieur d'un conteneur et voici ce que j'obtiens :

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

@darkermatter pourriez-vous s'il vous plaît ouvrir un problème séparé ?

pas un problème, mais n'est-ce pas pertinent ici?

@darkermatter ceci est une demande de fonctionnalité, pas un rapport de bogue, mélanger votre cas avec d'autres cas rend difficile le suivi de la discussion, votre problème peut également ne pas être directement lié

@thaJeztah eh bien, comme @frankamp et d'autres l'ont fait, je démontrais simplement ce qui se passe après l'exécution de chmod, etc. dans le Dockerfile. Je vais le déposer en tant que rapport de bogue, mais il est pertinent pour cette discussion.

similaire à ce que @ebuchman a proposé, sans copier un volume hôte, vous pouvez d'abord créer un conteneur de données uniquement, qui fait un
chown 1000:1000 /volume-mount en tant que root au démarrage.
Par exemple, dans docker composer la syntaxe v2

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

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

De cette façon, votre conteneur peut s'exécuter en tant qu'utilisateur non root. Le conteneur de données uniquement ne s'exécute qu'une seule fois.
En supposant que vous connaissiez l'uid et le gid que my-beautiful-service utilise à l'avance. Il est généralement de 1000,1000.

Étant donné que vous pouvez (en 1.11) spécifier des options de montage pour un volume à utiliser dans votre docker volume create , je dirais que cela semble assez proche d'être prêt à être fermé.

Vous ne pouvez pas simplement spécifier uid/gid directement car cela n'est pas pris en charge avec les montages liés, mais de nombreux systèmes de fichiers que vous pouvez utiliser avec les nouveaux opts de montage peuvent fonctionner avec les opts uid/gid.

Je pense que le problème persiste dans les cas où vous souhaitez monter un lecteur CIFS à l'intérieur de votre conteneur, mais cela devrait peut-être être un autre ticket ?

@ michaeljs1990 Vous pouvez le faire, mais pas par conteneur (sauf si vous créez des volumes séparés pour chaque combo uid/gid que vous souhaitez).

@ cpuguy83 , pourriez-vous s'il vous plaît préciser comment il faut utiliser docker volume create pour éviter ce problème ?

Je viens de rencontrer ce problème aujourd'hui avec docker 1.11 et j'ai dû faire un rejigging douloureux pour convaincre l'image docker de me laisser écrire dans des fichiers sur un lecteur monté. Ce serait vraiment bien si je n'avais plus jamais besoin de le refaire, encore moins d'essayer de l'expliquer à quelqu'un d'autre.

Je ne sais pas si c'est ce que vous demandez, mais...

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

Construire l'image ci-dessus nommée "test"

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

/hello et /hello/world dans l'exemple ci-dessus appartiendraient à 1000:1000

Je vois. Donc, j'ai fait quelque chose de similaire mais un peu différent, ce qui peut valoir la peine d'être partagé. Fondamentalement, j'ai ajouté un utilisateur au Dockerfile qui partageait mon UID, GID, nom d'utilisateur et groupe pour l'utilisateur en dehors du conteneur. Tous les <...> sont des choses remplacées par des valeurs pertinentes.

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

Après cela, on peut soit basculer en utilisant USER ou en utilisant su à un moment ultérieur (par exemple, un script de point d'entrée ou lors de l'utilisation d'un shell). Cela m'a permis d'écrire sur le volume monté car j'étais le même utilisateur qui a créé. On peut également utiliser chown à l'intérieur du conteneur pour s'assurer que l'on dispose des autorisations sur les éléments pertinents. De plus, l'installation sudo est généralement une décision intelligente lorsque vous faites cela également.

Bien que cela résolve le problème, je ne sais pas si je l'aime car cela devrait être fait pour n'importe quel utilisateur. De plus, j'ai codé en dur des trucs (beurk!), Mais peut-être que des modèles pourraient être utilisés pour rendre cela un peu plus fluide. Je me demande si cette cale pourrait être absorbée par docker run d'une manière ou d'une autre. S'il existe déjà une meilleure façon de le faire, je serais très intéressé de savoir ce que c'est.

Il existe une option pour mapper les uids/gids des utilisateurs de l'hôte avec les uids/gids des utilisateurs du conteneur avec --userns-remap . Personnellement je n'ai pas essayé. Voir une bonne discussion sur ce sujet http://stackoverflow.com/questions/35291520/docker-and-userns-remap-how-to-manage-volume-permissions-to-share-data-betwee .

@cpuguy83 :

Vous ne pouvez pas simplement spécifier uid/gid directement car cela n'est pas pris en charge avec les montages liés, mais de nombreux systèmes de fichiers que vous pouvez utiliser avec les nouveaux opts de montage peuvent fonctionner avec les opts uid/gid.

À quels systèmes de fichiers pensez-vous accepter les arguments uid/gid ? Je sais que FAT peut le faire, mais cela semble tout aussi hacky que tout ce qui est proposé dans ce fil.

IMO, Docker a deux options :

  1. Prise en charge officielle du montage de volumes en tant qu'utilisateur/groupe spécifié (en utilisant le nom d'utilisateur/groupe défini à l'intérieur du conteneur, ne nécessitant pas que l'hôte ait cette connaissance des composants internes du conteneur).
  2. Ou... débarrassez-vous de la directive USER (et des drapeaux d'exécution associés).

Pouvoir s'exécuter en tant qu'utilisateur non root tout en ne pouvant monter que des volumes appartenant à root est une mauvaise fonctionnalité. Le partage d'uid/gid entre l'hôte et le conteneur est un autre défaut.

Les volumes @mehaase prennent possession de tout ce qui se trouve déjà sur le chemin du conteneur. Si l'emplacement dans le conteneur appartient à root, le volume deviendra root. Si l'emplacement dans le conteneur appartient à autre chose, le volume l'obtiendra.

Une sorte de solution de contournement pour cela serait formidable. À moins que le conteneur ne l'attende spécifiquement, il est _très_ difficile d'ajouter des volumes à des conteneurs standard tels que elasticsearch, redis, couchDB et bien d'autres sans écrire un Dockerfile personnalisé qui définit les autorisations. Cela rend la commande docker run -v ou la directive volume: dans docker-compose inutile.

@chrisfosterelli pourquoi inutile ? Je ne pense pas qu'il soit inhabituel de définir les propriétés des fichiers/répertoires que vous prévoyez d'utiliser.

@ cpuguy83 Parce qu'il ne semble pas possible de définir la propriété sans utiliser un Dockerfile personnalisé qui définit les autorisations et les volumes, c'est pourquoi je pense qu'ils ne sont pas utiles pour définir les volumes. Je ne lie pas les conteneurs à mon système de fichiers hôte, si cela est pertinent.

@chrisfosterelli Mais tous ces Dockerfiles standard devraient déjà avoir les autorisations définies.

Je pense que ce que @chrisfosterelli essaie de dire, @cpuguy83 , (et corrigez-moi si je me trompe @chrisfosterelli) est qu'il est devenu clair que ces variables (UID, GID, etc.) sont dynamiques et doivent être définies sur run-time (en particulier pour les fichiers détenus en interne et à partir de volumes montés), mais nous n'avons pas de moyen de le faire actuellement. La réponse jusqu'à présent semble être qu'ils ne devraient pas être déterminés au moment de l'exécution, mais cela ignore le problème fondamental d'utilisabilité présenté par une telle suggestion. Encore une fois, si je comprends mal tout cela, n'hésitez pas à me corriger.

@jakirkham Je ne dois pas comprendre quel est le problème d'utilisabilité.
Les fichiers sont dans l'image, ils doivent avoir la propriété et les autorisations requises pour que l'application s'exécute. Cela n'a rien à voir avec le volume lui-même. Le volume prend juste ce qui a été défini dans l'image.

@ cpuguy83 J'ai creusé un peu plus et l'ai isolé à ceci: Supposons que j'ai un conteneur elasticsearch qui créera un répertoire /data au démarrage (si aucune donnée n'est présente), puis utilisez docker run -v /data elasticsearch . Le répertoire /data devient la propriété de root:root et le démon qui s'exécute en tant que elasticsearch à l'intérieur du conteneur ne pourra plus démarrer car il ne peut pas écrire dans /data .

Ce serait idéal si je pouvais définir ce volume pour qu'il appartienne à elasticsearch sans avoir besoin d'un Dockerfile personnalisé... bien que je suppose que vous pourriez affirmer que ce type de problème devrait être résolu dans l'image en amont.

@chrisfosterelli , il est question sur les listes de diffusion du noyau d'avoir une superposition comme un pilote qui peut changer de propriétaire, mais nous ne pouvons pas faire grand-chose sans quelque chose comme ça. Je suis curieux, pouvez-vous simplement faire en sorte que tous les fichiers de votre monde de volume lisent et écrivent et définissent les umasks de manière appropriée afin que les nouveaux fichiers le soient également? (je n'ai pas encore essayé).

@justincormack Je crois que oui, mais je pense que cela ne fonctionne pas lorsque je m'attends à ce que le conteneur crée les données dans le volume (plutôt que l'hôte). Je comprends que c'est une sorte de problème étrange, donc je le résous actuellement en le corrigeant dans le Dockerfile en amont lui-même à mkdir -p && chmod le répertoire.

@chrisfosterelli c'est pourquoi j'ai dit de définir l'umask, si votre umask est 000 (dans le conteneur), tous les nouveaux fichiers seront créés avec les autorisations 666 ou 777 , et si le le point de montage est 777 pour commencer, ça devrait aller ? Si les autorisations sont toujours en lecture et en écriture universelles, uid et gid ne devraient pas avoir d'importance ?

@justincormack Oui, cela semble correct ... comment puis-je faire cela lors de la création d'un conteneur Docker avec un volume non monté sur l'hôte?

@chrisfosterelli hmm, c'est une bonne question. Il me semble que les autorisations sur un nouveau volume sont ce que donnerait l'umask par défaut, vous pouvez donc essayer d'exécuter le démon docker avec un umask 000 et voir si le volume est accessible en écriture par le monde. Peut-être devrions-nous avoir des options d'autorisations sur docker volume create .

(vous pouvez le réparer avec un conteneur racine qui a fait chmod et qui est sorti aussi mais c'est moche)

Sur créer n'est pas bon. Le problème est que si le conteneur n'a pas le chemin, le chemin est créé avec root. Cela pourrait sans doute être fait comme quel que soit l'utilisateur transmis.

@ cpuguy83 Je pense qu'il serait plus logique de le créer lorsque l'utilisateur est passé avec -u car ce serait probablement l'utilisateur essayant d'écrire le volume de toute façon depuis l'intérieur du conteneur, n'est-ce pas?

J'ai pu monter en tant qu'utilisateur de mon choix en suivant les étapes ci-dessous :

  • Créez l'utilisateur dans Docker avec le même UID/GID que l'utilisateur propriétaire des fichiers sur l'hôte.
  • Créez les points de montage à l'avance et envoyez-les à l'utilisateur cible dans le conteneur

Citation @chrisfosterelli :

J'ai creusé un peu plus et l'ai isolé à ceci : supposons que j'ai un conteneur elasticsearch qui créera un répertoire /data au démarrage (si aucune donnée n'est présente), puis utilisez docker run -v /data elasticsearch. Le répertoire /data devient la propriété de root:root et le démon qui s'exécute en tant qu'elasticsearch à l'intérieur du conteneur ne pourra plus démarrer car il ne peut pas écrire dans /data.

Ceci est un excellent exemple! J'ai un exemple similaire avec l'image Solr. Solr a besoin d'un ou plusieurs "cœurs", dont chacun est une collection de fichiers de configuration et de fragments d'index associés. Chaque cœur est placé dans un répertoire avec un nom spécifié par l'utilisateur. Par exemple, si je veux créer un noyau nommé products , le chemin serait /opt/solr/server/solr/products . Le nom du noyau est choisi par moi, donc le responsable de l'image Solr ne peut pas pré-créer ce répertoire dans l'image.

Je souhaite que mes données d'index soient enregistrées afin de pouvoir mettre à niveau mon image vers un Solr plus récent sans avoir à réindexer tous mes documents, mais si je monte un volume sur /opt/solr/server/solr/products , il appartient à root et Solr (s'exécutant en tant que solr ) ne peuvent rien y écrire. Le répertoire parent /opt/solr/server/solr contient d'autres fichiers, donc je ne peux pas non plus y monter de volume. (Dans le dernier langage Docker, je crois que mes volumes sont appelés "volumes nommés", c'est-à-dire des volumes qui ne sont pas montés sur un chemin spécifié sur l'hôte mais qui sont totalement gérés par Docker pour moi.)

J'en ai parlé avec le responsable de l'image Solr et il existe des solutions de contournement (et il a apporté quelques modifications à l'image pour aider) mais tout est assez hacky et nécessite des modifications au cas par cas de l'image en amont. Avoir la fonctionnalité discutée dans ce fil rendrait _toutes les images_ plus extensibles sans avoir besoin de créer un nouveau Dockerfile.

@ctindel peut-être... si le répertoire n'existe pas déjà.

@ cpuguy83 C'est vrai, je suis d'accord. C'était définitivement mon cas d'utilisation. Il ne semble pas logique de créer le répertoire en tant que root s'il n'existe pas lorsqu'un ID utilisateur a été explicitement spécifié pour exécuter le conteneur.

@ cpuguy83 cela ne fonctionne que pour le volume nommé.

@kamechen Qu'est-ce qui fonctionne ?

@ cpuguy83 Lorsque vous utilisez un volume nommé, les fichiers sont montés sous l'utilisateur dont vous avez besoin

@eciuca Eh bien... ça dépend. Si le volume nommé était vide ou si les données du volume nommé ont été créées par le même utilisateur dont vous avez besoin.

Y a-t-il déjà eu une solution au problème soulevé par @andrewmichaelsmith ?

Nous rencontrons un problème qui serait résolu par cela (je pense). Nous avons un partage NFS pour les répertoires personnels de nos développeurs. Les développeurs veulent monter /home/dev/git/project dans Docker mais ne le peuvent pas car Root Squash est activé.

Cela interdit à root d'accéder à /home/dev/git/project, donc lorsque j'essaie d'exécuter le montage de docker /home/dev/git/project, j'obtiens une erreur d'autorisation lstat refusée.

Je pense qu'il est possible de contourner ce problème en utilisant bindfs .
Utiliser -v ... de docker pour monter le volume dans un emplacement temporaire, puis bindfs pour le monter là où c'est nécessaire en tant qu'autre utilisateur.

@piccaso , d'après ce que j'ai compris @andrewmichaelsmith , le problème est que le montage lié côté hôte échoue à cause de rootsquash. Mais bindfs pourrait toujours être utilisé comme solution de contournement, mais cette fois du côté de l'hôte. Tout d'abord, sur l'hôte, vous montez par liaison le partage nfs dans un emplacement temporaire en tant qu'utilisateur non root à l'aide de FUSE, puis vous montez ce dossier temporaire dans docker avec -v ... .

Rappelez-vous que bindfs (au moins avec FUSE) a un peu de surcharge CPU.

Oui, bindfs est très indésirable. C'est même plus lent que les systèmes de fichiers CoW.
Il y a du travail en cours dans le noyau pour permettre le changement d'uid/gid sur le montage qui peut aider.

Il y a du travail en cours dans le noyau pour permettre le changement d'uid/gid sur le montage qui peut aider.

Cela n'aidera probablement aussi qu'à résoudre le cas d'utilisation où je veux remapper uid/gid à l'intérieur du conteneur. Le montage lui-même tel qu'exécuté par le démon docker serait toujours exécuté en tant que root sur l'hôte. D'après ce que j'ai compris, les montages liés au noyau ne peuvent être créés qu'en tant que root. Je ne sais pas s'il y a du travail pour changer cela pour permettre aux utilisateurs non root d'effectuer des montages (je connais peu la façon dont Linux gère les montages pour juger si cela a du sens).

@NikolausDemmel Je doute que cela change. L'appel système mount nécessite CAP_SYS_ADMIN, qui n'est pas donné à un utilisateur non root, ni même quelque chose que nous donnons à l'utilisateur root d'un conteneur.

@ cpuguy83 Merci pour la clarification. Cela signifie que le montage de volumes docker sur des dossiers hôtes qui sont des montages NFS avec root-squash ne fonctionnera pas dans un avenir prévisible (en raison des limitations de l'appel système de montage comme vous le dites), sauf pour utiliser des solutions de contournement comme FUSE avec bindfs .

Désolé, c'était légèrement OT, car OP demandait de changer l'UID/GID à l'intérieur du conteneur. Mais c'est un peu l'autre côté de la médaille et cela a été évoqué dans la discussion ci-dessus. Je voulais juste clarifier cette distinction.

J'exécute Docker pour Mac et j'ai monté un volume, mais je n'arrive pas à obtenir les autorisations définies pour que le service Web accède aux fichiers. Comment pourrais-je résoudre ce problème ? J'ai essayé de changer les perms et de définir le groupe sur le personnel, mais il semble qu'Alpine n'ait pas de groupe de personnel.

Désolé si ce n'est pas le meilleur endroit pour le mettre, je me bats depuis des jours et je ne pouvais pas penser à un meilleur endroit.

@NikolausDemmel : Nous essayons d'utiliser Docker pour certains travaux de bioinformatique. Nous avons plusieurs énormes systèmes de fichiers montés à la racine via NFS. Nous lisons des données de séquence énormes (fastq) et écrivons un fichier BAM un peu plus petit avec les lectures génomiques alignées sur le magasin de données. Actuellement, nous pouvons utiliser docker en faisant l'image personnalisée pour créer un utilisateur à l'intérieur du conteneur et utiliser USER à la fin pour le faire fonctionner, mais cela pose problème pour plusieurs raisons :

  1. Si nous voulons utiliser l'image Docker de quelqu'un d'autre, nous devons reconstruire avec un Dockerfile personnalisé
  2. Soit nous devons créer une image docker personnalisée pour chaque utilisateur local, soit nous utilisons un seul compte "service" et nous ne pourrons pas faire la distinction entre les activités de l'utilisateur dans le FS.

Bindfs ou userNS peuvent-ils nous permettre de contourner cela ?

Je pense que je rencontre le même problème, mon cas d'utilisation est:
Les images Docker contiennent nos outils de construction portables pour un projet donné, nous utilisons le montage de volume avec des chemins relatifs soit avec quelque chose comme docker run -v ./:/src/ image ou l'équivalent dans un fichier docker-compose. Une construction est automatiquement lancée et de nouveaux fichiers sont générés dans un sous-dossier du volume lié.
Parfois, nous aimons utiliser ces fichiers construits à partir de l'hôte, mais le fait qu'ils appartiennent toujours à l'utilisateur dans Docker, plutôt qu'à l'utilisateur hôte qui a exécuté Docker, a tendance à compliquer les choses.

Est-ce que je fais quelque chose de particulièrement mal ici ?

@rlabrecque voir mon post plus tôt sur la correspondance de l'identifiant de l'utilisateur docker avec celui de l'hôte. J'ai utilisé cette approche et cela fonctionne très bien pour nous. Fondamentalement, exécutez HOST_UID=$(id -u) et HOST_GID=$(id -g) et générez un Dockerfile qui développe $HOST_GID et $HOST_UID dans les deux commandes ci-dessous :

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

Utilisez le Dockerfile généré avec les ID remplis pour créer votre image.

@haridsv J'ai fait quelque chose de similaire et cela fonctionne très bien sous Linux. Mais cela ne semble pas fonctionner pour moi sous Windows : les fichiers à l'intérieur du montage appartiennent toujours à root.

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 les nouveaux fichiers ou répertoires créés dans le répertoire /mount. Lorsqu'il en remarque un, il modifie 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 le même propriétaire que n'importe quel 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 de tout gâcher avec une instruction chown -R à chaque fois que le système de fichiers est monté. Si les autorisations uniformes fonctionnent pour votre projet et que vous souhaitez une solution plus simple qui s'exécute plus efficacement, consultez inotify-hookable .

Attention : étant donné qu'une surveillance inotify sera établie par sous-répertoire, il est possible que le nombre maximal de surveillances 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.

Nous avons utilisé un script côté hôte pour chown le volume beng monté, ce qui évite d'avoir à reconstruire l'image :

#!/bin/bash
set -e

DOCKER_IMAGE=<docker_image>
COMMAND=<internal_command>

DOCKER_USER=docker-user
DOCKER_GROUP=docker-group

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

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

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

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

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

qu'en est-il de l'utilisation des ACL du système de fichiers sur le répertoire hôte ? De cette façon, vous pouvez dire au système de fichiers d'appliquer des autorisations spécifiques aux fichiers nouvellement créés dans le répertoire. Si vous définissez l'ACL au niveau de l'hôte, si vous modifiez les données du conteneur, cela se produira également.

@thaJeztah @justincormack @cpuguy83

@kamechen semble avoir raison de dire que les volumes nommés "fonctionnent tout simplement". Dans le cas des volumes nommés, les autorisations existantes "se retournent" et modifient les autorisations de volume, et je considère personnellement qu'il s'agit d'un bogue (# 28041).

@thegecko , pourquoi ne pas aller plus loin dans cette approche et ne pas créer d'utilisateurs au sein d'un point d'entrée ?

Voici mon exemple, il détecte un propriétaire du répertoire monté, crée un utilisateur avec le même UID et exécute la commande sous cet utilisateur :

Fichier Docker

FROM ubuntu

RUN mkdir /project
VOLUME /project

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

ADD entrypoint.sh /

ENTRYPOINT ["/entrypoint.sh"]

CMD /project/run.sh

point d'entrée.sh

#!/bin/sh

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

run.sh

#!/bin/sh

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

Lorsque j'exécute sudo docker build -t test . && sudo docker run --rm -v /tmp/docker-test/:/project test:latest , il affiche :

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

Quelqu'un at-il considéré cette question? S'assurer que vos volumes ont le même gid et uid que vos conteneurs rend plus difficile la gestion de vos conteneurs pour ne pas utiliser root. Les meilleures pratiques de Docker recommandent de ne pas exécuter de services avec root si possible, mais ne pas avoir à configurer le gid et l'uid sur l'hôte ainsi que les conteneurs en quelque sorte va à l'encontre de la facilité d'utilisation qui a rendu Docker populaire ?

@AndreasBackx L'utilisation de volumes fonctionne uniquement en supposant que l'image contient des données sur le chemin de votre montage.
L'utilisation de liaisons utilise l'UID/GID du chemin de l'hôte.

Il n'y a actuellement aucun moyen (comme dans aucun support de noyau) de mapper ou de changer l'UID/GID d'un fichier/répertoire à autre chose sans changer l'original à moins d'utiliser quelque chose comme FUSE, qui est horriblement lent.

Mais revenons un instant en arrière.
Docker ne rend pas vraiment les choses plus difficiles ici.
L'UID/GID dans le conteneur est le même que l'UID/GID sur l'hôte... même si les noms d'utilisateur/groupe ne correspondent pas, l'UID/GID est ce qui compte ici.
Tout comme sans docker, vous devez trouver un uid/gid que vous souhaitez utiliser pour vos services et l'utiliser hors convention.
N'oubliez pas qu'un uid/gid n'a pas besoin d'exister dans /etc/passwd ou /etc/group pour que la propriété du fichier lui soit définie.

@cpuguy83 merci pour l'explication.

J'ai rencontré ce problème aujourd'hui lors de la création d'un pipeline node , mon UID d'utilisateur hôte est 1000 et l'image node crée un utilisateur personnalisé avec cet UID spécifique , il y a même un problème à ce sujet

J'utiliserais l'utilisateur du nœud et je passerais à autre chose, mais il se sent un peu sale. Je partage vraiment ce que vous avez écrit @cpuguy83 à propos de "reculons un instant", mais parfois cela peut devenir un problème difficile à résoudre.

Je viens de découvrir l'option -o sur usermod pour autoriser les IDS en double, semble une option légitime.

RUN usermod -o -u 1000 <user>

Je ne sais pas pourquoi cela n'a pas été corrigé de manière raisonnable.

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

connectez-vous pour voir:

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

Le dockefile fait spécifiquement

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

Cela n'a aucun sens que ce volume soit monté en tant que root, lorsque ni l'utilisateur dans le conteneur n'est sélectionné, ni l'utilisateur exécutant la commande sélectionné. Je pourrais comprendre si la commande RUN est montée en tant qu'utilisateur exécutant la commande, ou l'utilisateur propriétaire du répertoire, ou même l'utilisateur spécifié dans le Dockerfile.

Aucun de ceux-ci n'est root, donc le montage en tant que root semble être un bogue.

Je viens également de vérifier, de créer un volume, puis de le monter fonctionne. Donc toujours un bug.

@disarticulate Si vous souhaitez que le chemin de l'hôte soit autre que root, vous devez modifier le chemin de l'hôte.

Je ne pense pas que cela ait été mentionné auparavant, mais ce bogue est particulièrement gênant lorsque vous comptez sur Docker pour créer le volume hôte pour vous. Docker semble toujours créer le volume hôte avec la racine, même lorsque le répertoire sur lequel vous montez a un propriétaire différent.

Il semblerait que la bonne chose à faire ici serait de créer le volume avec des autorisations de propriété appartenant à l'image USER .

@jalaziz que doit-il faire lorsque l'utilisateur du conteneur n'existe pas sur l'hôte ? L'un des principaux avantages des conteneurs est que vous n'avez pas à exposer leurs dépendances (y compris les utilisateurs) à l'hôte.

@taybin Je m'attendrais à ce que Docker crée simplement le dossier avec l' uid:gid de l'utilisateur du conteneur OU si le dossier existe à l'intérieur du conteneur, il créerait le dossier hôte avec le même uid:gid et le même masque.

REMARQUE : Je ne m'attends pas à ce que Docker modifie les autorisations si le dossier existe déjà sur l'hôte.

@taybin Exactement comme @frol décrit. Il devrait simplement utiliser le uid:gid du conteneur.

Cependant, cela révèle mon problème général avec l'approche actuelle. Je dois connaître l'uid que le conteneur utilise pour autoriser les écritures et définir les autorisations sur les répertoires hôtes en fonction de cet uid:gid. Si un auteur en amont modifie l'uid, les autorisations seront interrompues. Tout semble très fragile.

Dans mon cas, je n'avais pas nécessairement un contrôle explicite sur l'image docker utilisée (je ne pouvais pas simplement modifier un Dockerfile à mon goût).

Alors, j'ai essayé ceci:

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

Ce qui crée un dossier appelé ./built-app . Cependant, le propriétaire était toujours root avec des autorisations strictes.

Ma solution de contournement était celle-ci:

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

Qui a toujours le propriétaire root , mais des autorisations assouplies. Ensuite, mon système d'exploitation hôte (Ubuntu) a pu accéder à ./built-app sans privilèges sudo.

@rms1000watt avez-vous essayé la commande suivante ?

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

Cela devrait fonctionner car il utiliserait les UID et GID votre hôte directement sur les fichiers eux-mêmes. Utiliser chmod -R 777 est généralement une mauvaise pratique.

@saada Oups ! Bon appel. Je vais essayer.

J'ai pu accomplir mon approche en lisant ceci et en comprenant comment _UID et GID fonctionnent dans les conteneurs Docker_
https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf

Fondamentalement, il y a un seul noyau et un seul pool partagé d'UID et de GID, ce qui signifie que la racine de votre machine locale est la même que la racine de votre conteneur, ils partagent tous les deux le même UID.


J'ai un serveur apache et je souhaite partager mes fichiers webapp avec le conteneur apache pour le modifier sur l'hôte (développement, les modifier à l'aide d'un éditeur de texte) et voir les résultats par un processus s'exécutant dans le conteneur. Parfois, ce processus écrit de nouveaux fichiers et si je ne modifie pas le comportement par défaut avec les privilèges, les fichiers sont générés par l'utilisateur root et mon utilisateur local ne peut plus les modifier.

Ce que j'ai fait, c'est générer une image personnalisée en ajoutant ceci dans mon dockerfile :

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

Peut-être que pour rendre mon docker-compose.yml portable à tout le monde, il faut mettre quelques paramètres sur le processus de construction.

Voici un modèle de conteneur pour attribuer l'ID utilisateur/ID de groupe au moment de l'exécution d'une manière facilement portable. https://github.com/Graham42/mapped-uid-docker

Le chemin que j'ai suivi :

1- créer le répertoire sur le serveur hôte
2- changez ses permissions pour l'utilisateur qui a userid et groupid = 1000
3- exécuter docker-compose up
vérifié le conteneur et tout va bien.

Remarque : J'utilisais l'utilisateur root sur le serveur hôte et je suppose que si j'utilisais un utilisateur non root qui a uid = 1000, je pourrais monter le volume sans me soucier de l'autorisation, mais je ne l'ai pas encore testé. Y a-t-il quelqu'un qui a suivi un chemin similaire?

Problème typique :

  • docker swarm, donc CAPP_ADD n'est pas disponible, bind-mount n'est pas une solution
  • deux conteneurs de deux images différentes partagent le même volume, donc différentes bases de données d'utilisateurs/groupes sur les deux
  • par exemple, il faut avoir les droits d'accès www-data (c'est-à-dire chiffrer le téléchargeur de certificat)
  • l'autre utilise également www-data (c'est-à-dire nginx)
  • mais un troisième nécessite l'accès de l'utilisateur openldap (c'est-à-dire le serveur openldap)
  • chmod si simple n'est pas non plus une solution

Cela signifie que j'ai un serveur Web, qui obtient des certificats SSL pour ses domaines à partir de let's encrpt et un serveur OpenLDAP pour le même domaine, où je souhaite réutiliser les certificats.

Il existe d'autres combinaisons qui rencontrent exactement le même problème.

Aucune idée sur la façon de résoudre ça?

Comment résoudriez-vous cela sans Docker ? Ceci n'est pas spécifique à Docker
problème.

Le ven. 12 janvier 2018 à 10h24, Marc Wäckerlin [email protected]
a écrit:

Problème typique :

  • docker swarm, donc CAPP_ADD n'est pas disponible, bind-mount n'est pas un
    Solution
  • deux conteneurs de deux images différentes partagent le même volume, donc
    différentes bases de données d'utilisateurs/groupes sur les deux
  • par exemple, il faut avoir les droits d'accès www-data (c'est-à-dire chiffrer
    téléchargeur de certificat)
  • l'autre utilise également www-data (c'est-à-dire nginx)
  • mais un troisième nécessite l'accès de l'utilisateur openldap (c'est-à-dire openldap
    serveur)
  • chmod si simple n'est pas non plus une solution

Cela signifie que j'ai un serveur Web qui obtient des certificats SSL pour ses domaines
de let's encrpt et un serveur OpenLDAP pour le même domaine, où je veux
pour réutiliser les certificats.

Il existe d'autres combinaisons qui rencontrent exactement le même problème.

Aucune idée sur la façon de résoudre ça?


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/2259#issuecomment-357267193 , ou muet
le fil
https://github.com/notifications/unsubscribe-auth/AAwxZgyvdCwGGVkUqCxK9nDFw1zxSKjUks5tJ3kXgaJpZM4BGxv9
.

--

  • Brian Goff

Même sans essaim, je pourrais le résoudre dans docker : bind-mount.

C'est un problème spécifique à docker-swarm, car il n'y a pas de CAP_ADD.

Les montages de liaison @mwaeckerlin ne peuvent pas correspondre à différents ID utilisateur.
Mais même avec un essaim, vous pouvez lier le montage .... pourquoi CAP_ADD est-il nécessaire?

Sans CAP_ADD, le montage à l'intérieur du menu fixe échoue.

Mais en écrivant mon commentaire, je viens d'avoir une solution possible, mais malheureusement cela nécessite de changer le Dockerfile dans les deux images, donc cela ne fonctionnera pas pour la bibliothèque ou d'autres images tierces :

  • créer un groupe avec un identifiant de groupe commun explicitement donné dans tous les Dockerfiles
  • donner des droits au groupe

@mwaeckerlin Pourquoi avez-vous besoin de monter à l'intérieur du conteneur ?

Parce que je ne peux pas spécifier un utilisateur/groupe avec l'option docker -v .

L'idée spécifiée ci-dessus était : le montage lié à l'intérieur du conteneur, puis chown sur la cible ne devrait pas changer la source.

@mwaeckerlin Si vous le changez, c'est changé partout. C'est le nœud du problème dans ce numéro.
Chowning/Chmoding un fichier/répertoire monté en liaison change les deux endroits.

De plus, il n'est pas nécessaire de pouvoir monter à l'intérieur du conteneur, vous pouvez --mount type=bind,source=/foo,target=/bar

Oui, je viens de le tester en dehors de docker, donc l'idée ci-dessus est fausse.

Le principal problème, que j'ai souvent vu dans docker, est que les utilisateurs, les groupes ne sont pas identiques dans différentes images, même lorsque le même nom d'utilisateur ou nom de groupe existe dans les deux, ils ont souvent des identifiants différents.

Ici, quelque chose comme ça aiderait au moins dans certains cas : --mount type=bind,source=/foo,target=/bar,user=me,group=mine

Des recommandations ou des meilleures pratiques concernant ce sujet : utilisateur de volume partagé par différents utilisateurs dans différentes images dans docker swarm ?

  1. Ne partagez pas les volumes
  2. Synchronisez vos uid/gids
  3. Assurez-vous que les autorisations sont suffisamment permissives pour tous ceux qui partagent
  4. Utilisez des supports de fusibles sur l'hôte pour vous lier à différents uid/gid pour chaque conteneur

Pouvez-vous préciser le point 4 ?
Un exemple pratique peut-être sur la façon de le faire?

Le ven. 12 janvier 2018, 17 h 27, Brian Goff, [email protected] a écrit :

>

  1. Ne partagez pas les volumes
  2. Synchronisez vos uid/gids
  3. Assurez-vous que les autorisations sont suffisamment permissives pour tous ceux qui partagent
  4. Utilisez des supports de fusibles sur l'hôte pour vous lier à différents uid/gid pour chacun
    récipient


Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/2259#issuecomment-357282169 , ou muet
le fil
https://github.com/notifications/unsubscribe-auth/AHSjvgjb0BFbJhZ1VWM-pLGfa7tRBvDNks5tJ4VPgaJpZM4BGxv9
.

En utilisant quelque chose comme https://bindfs.org/ - il y a même au moins un plugin de volume Docker qui l'implémente déjà (https://github.com/lebokus/docker-volume-bindfs est le premier résultat que j'ai trouvé via Google) .

Je ne peux pas modifier l'autorisation après avoir monté le volume, est-ce que quelqu'un a compris cela ?

une solution de contournement :
Ajouter ceci à Dockerfile
RUN echo "if [ -e container_volume_path ]; then sudo chown user_name container_volume_path; fi" >> /home/user_name/.bashrc
La propriété de container_volume_path est modifiée après le montage du volume.

Être capable de mapper uid et gid semble être un mystérieux élément manquant à la gestion du volume docker. La voie la moins surprenante serait de l'inclure et les correctifs suggérés sont maladroits et plus difficiles à découvrir, tout en n'offrant aucun avantage en matière de meilleures pratiques :

Ré:
1) Ne partagez pas les volumes

  • Bon, mais sans importance pour la discussion sur le mappage uid/gid
    2) Synchronisez vos uid/gids
  • C'est ce que la fonctionnalité est destinée à faire, mais sans forcer un chown dans un Dockerfile
    3) Assurez-vous que les autorisations sont suffisamment permissives pour tous ceux qui partagent
  • Cela repose à nouveau sur le comportement défini dans un Dockerfile, alors qu'il pourrait s'agir d'un simple mappage
    4) Utilisez des supports de fusibles sur l'hôte pour lier différents uid/gid pour chaque conteneur
  • Bon conseil, cela ressemble aussi à du rasage de yak.

@colbygk

alors qu'il pourrait s'agir d'un simple mappage

C'est le problème, il n'est pas possible de faire un "mappage simple" car il n'est pas pris en charge au niveau de la couche vfs.
Certains systèmes de fichiers offrent la possibilité de mapper la propriété (par exemple, bindfs ou nfs), mais l'implémentation dans le cas générique n'est actuellement pas possible.

J'ai besoin de volumes partagés, par exemple dans la situation suivante :

Certificats partagés

  • le conteneur 1 est un reverse-proxy qui gère let's encrypt pour tous les domaines hébergés
  • le conteneur 2 est un serveur ldap qui doit également fournir le certificat de son domaine

solution : le conteneur d'images 2 hérite de la même image que le conteneur 1, l'image de base commune crée un groupe commun, puis les deux conteneurs ont le même accès de groupe

Dockerfile de base commune :

RUN groupadd -g 500 ssl-cert

letsencrypt-config.sh dans l' image let's encrypt :

chgrp -R ssl-cert /etc/letsencrypt

Dockerfile de mwaeckerlin/reverse-proxy :

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

Dockerfile de mwaeckerlin/openldap :

RUN usermod -a -G ssl-cert openldap

C'est ça.

Tout cela illustre comment modifier les permissions d'utilisateur pendant le point d'entrée ou pendant le processus de construction pour que l'intégralité du docker s'exécute dans un utilisateur différent.

Mais peut-être que j'ai raté un gros point après avoir cherché sur le Web pendant 3 jours.
Aucune des recommandations et (solutions de contournement) ci-dessus ou autrement liées ne fonctionnera de quelque manière que ce soit.

Tous les volumes montés sur un conteneur appartiennent toujours à root:root à l'intérieur du conteneur. Peu importe si je change le propriétaire à l'avance sur l'hôte avec l'UID/GID correspondant ou non.

Je ne peux pas perdre le sentiment d'être stupide en essayant de faire quelque chose de très très basique - de mon point de vue.

  • Windows 10 Professionnel 1803 (17134.112)
  • Docker pour Windows 18.03.1-ce-win65 (17513)
  • Windows WSL avec Hyper-V et Ubuntu

Essayer de démarrer un conteneur apache2 simple où la racine du document est montée sur l'hôte afin que je puisse développer sur le code source php tout en le testant immédiatement sur le conteneur docker.

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

À l'intérieur du conteneur Docker, le directoy _/var/www/html_ appartient toujours à _ root:root_ , donc mon application php ne pourra jamais fopen, ou écrire avec des données dans ce dossier.
Rien n'a encore fonctionné... :(

Pour ceux qui recherchent une solution raisonnablement élégante, consultez ce que @elquimista a suggéré ici . J'ai testé cela et fonctionne bien

Nous utilisons https://github.com/boxboat/fixuid#specify -paths-and-behavior-across-devices avec de la chance. De plus, il configure un utilisateur à l'intérieur du conteneur pour correspondre à un utilisateur sur l'hôte.

Voici un exemple de configuration à partir de l'image :

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

et pour exécuter :

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

Notez que cela est également gênant lors de l'utilisation de systèmes de stockage qui ne prennent pas en charge les autorisations et la propriété Unix. Dans ce cas, le montage du stockage doit être effectué de manière à ce qu'il obtienne le bon uid à utiliser à l'intérieur du conteneur, car toute tentative de chown les fichiers échoue tout simplement. S'il y avait un moyen de dire à docker de présenter les fichiers comme appartenant à un uid particulier, quelle que soit la propriété en dehors du conteneur, cela simplifierait les choses.

@tlhonmey

S'il y avait un moyen de dire à docker de présenter les fichiers comme appartenant à un uid particulier

Il n'y en a pas, pas sans un système de fichiers personnalisé (par exemple, comme bindfs).

@tlhonmey Ouais, j'ai pu contourner le problème des "systèmes de stockage qui ne prennent pas en charge les autorisations Unix" avec quelques liens symboliques.

Fondamentalement, en montant à partir de lecteurs NTFS, je mettrais les choses dans -v ./HostNtfsStuff:/data/ntfsMount , puis je ferais un lien symbolique et chown que ln -s -T /data/ntfsMount /var/lib/myApp && chown -Rh myApp:myApp /var/lib/myApp/

Vous pouvez aussi tester : su myApp -c 'echo foo > /var/lib/myApp/bar' && cat /data/ntfsMount/bar

Mon utilisation était que les développeurs Windows puissent exécuter des conteneurs MySQL et persister sur des volumes montés, mais cela s'applique à de nombreuses applications.

La solution consiste donc à gérer manuellement un tas de paires uid:gid et à espérer qu'elles ne se heurtent pas sur l'hôte, ou un script d'assistance, ou :

Il existe _un_ moyen de le faire fonctionner, mais vous devez vous préparer à l'avance dans votre Dockrfile.

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

(Je n'ai pas testé cet exemple, je travaille sur un container chromium qui s'affiche ensuite sur un container X11 _séparé_ qui.... )

J'utilisais la dernière technique jusqu'à aujourd'hui quand j'ai essayé de lier le volume du conteneur et il s'est cassé. Apparemment tu ne peux pas faire ça. Le volume est créé en tant que root, puis l'application à l'intérieur ne peut pas y écrire en tant qu'utilisateur. Le remplissage automatique décrit dans la documentation VOLUME ne semble pas non plus fonctionner avec le montage lié.

J'ai vu ceci en lisant Dockerfile Best Practices et le script d'assistance est ce qu'ils recommandent :

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

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

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

    exec gosu postgres "$@"
fi

exec "$@"

Donc, un chown récursif pour vous assurer que vous êtes propriétaire à chaque démarrage, puis exécutez votre application en tant qu'utilisateur. exec force également le PID 1 pour que les signaux fonctionnent. Et si je veux remplir le volume avec quelque chose comme un script d'assistance à utiliser en dehors du conteneur sur les données résultantes, il doit probablement également figurer dans le script d'assistance. Vous vous demandez cependant s'il y a un impact sur les performances au démarrage du conteneur si votre application stocke des tonnes de fichiers sur un volume, en particulier si le stockage n'est pas local.

Il semble qu'il pourrait y avoir une meilleure solution. Peut-être quelque chose comme mapper l'uid et le gid du conteneur à celui d'un nom d'utilisateur et d'un groupe spécifiés sur l'hôte. Docker peut-il jeter un coup d'œil au /etc du conteneur et comprendre cela peut-être?

Vous ne pouvez pas mapper les uids/gids au niveau du système de fichiers, du moins pas sans fusible.

Vous ne pouvez pas mapper les uids/gids au niveau du système de fichiers, du moins pas sans fusible.

Un peu ce que je craignais. Avez-vous une idée de ce que pourrait être la pénalité de performance si Docker utilisait un fusible comme celui-ci ?

@mdegans

Donc, un chown récursif pour vous assurer que vous avez la propriété à chaque démarrage,

Vous n'avez pas besoin de faire un chown à chaque démarrage. Au lieu de cela, vérifiez le propriétaire du répertoire de données et ne faites le chown récursif que s'il n'est pas correct. Comme ça:

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

Donc, idéalement, cela ne se produira qu'au premier démarrage.

Et soyez très prudent lorsque vous exécutez un conteneur avec un tel script de point d'entrée ; si vous montez (par exemple) votre répertoire personnel dans le conteneur, tous vos fichiers seront convertis en postgres

Dans une bonne conception d'image docker, l'utilisateur d'exécution n'est pas root et ne peut donc pas chown fichiers… !

Dans une bonne conception d'image docker, l'utilisateur d'exécution n'est pas root et ne peut donc pas chown les fichiers... !

Correct, mais rien ne devrait arrêter un commutateur vers et depuis root , ce qui est souvent nécessaire... tout comme vous ne devriez normalement pas exécuter quoi que ce soit comme root jusqu'à ce que vous en ayez besoin, mais lorsque vous le faites, vous pouvez effectuer une ou plusieurs des actions suivantes :

  • sudo
  • su
  • USER root

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

À mon humble avis, il appartient à l'utilisateur de l'image Docker de s'assurer qu'il définit correctement l'autorisation sur le volume monté.

C'est très similaire à ce que nous faisions traditionnellement avant que les conteneurs ne soient une chose, par exemple lorsque je voulais exécuter nginx et que je devais m'assurer que le répertoire HTML statique appartenait au bon utilisateur. Pour savoir que j'aurais besoin d'ouvrir mon fichier nginx.conf, vérifiez l'utilisateur des travailleurs et définissez les autorisations en conséquence. En fait, tout cela a été décrit dans la documentation nginx.

C'est juste un problème d'autorisation Unix, rien de nouveau avec Docker ici. Alors peut-être que la solution à ce problème est une meilleure documentation pour chaque image Docker de ce qui devrait être la propriété des volumes montés. Je ne me souviens pas que le démon de démarrage nginx s'assurait que le répertoire avait le bon propriétaire, il échouerait simplement s'il n'était pas correctement configuré.

Cependant, c'est vrai que parce que nous avons maintenant des utilisateurs potentiellement définis à l'intérieur du conteneur et non à l'extérieur, cela rend les choses différentes (et elles ne le sont pas). Mais l'UID intérieur et extérieur sont équivalents, donc l'utilisateur foobar avec l'UID 2000 peut exister à l'intérieur d'un conteneur et non à l'extérieur, mais l'UID 2000 peut toujours être défini sur des fichiers et des répertoires à l'extérieur. Nous devons changer notre façon de penser en termes d'UID/GID plutôt qu'en termes de noms conviviaux avec lesquels nous avions l'habitude de traiter.
Cela rend également les choses potentiellement plus difficiles si vous avez besoin de partager un volume entre 2 conteneurs écrits par 2 auteurs différents. Il est possible que la définition des autorisations à l'aide du système Unix traditionnel (d'utilisateur, de groupe et autres) ne suffise pas à résoudre le problème (pas d'UID ou de GID commun). J'avoue que depuis que j'utilise Docker, j'utilise beaucoup plus POSIX ACL. Je peux donc attribuer 3 autorisations d'utilisateurs différents sur le même fichier. par exemple, un rédacteur de conteneur avec la permission rw, un lecteur de conteneur avec la permission r et un utilisateur hôte avec la permission r.

Une autre option : le GID commun peut être appliqué à l'aide de l'indicateur setgid pour les répertoires partagés. Le masque de fichier peut être appliqué à l'aide d'ACL.

Avant de faire quoi que ce soit dans le conteneur Docker, exécutez :

```
umask 0000
````

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

Je reviens tard sur ce fil pour réaffirmer à quel point cette fonctionnalité serait utile.

Pour être honnête, je déploie des conteneurs depuis environ un an maintenant, et je vois que cela devient un vrai problème partout. Apporter une solution à ce niveau, ici, semble être le seul choix sensé.

Dans l'état actuel des choses, un nombre considérable d'images Docker ont choisi de continuer à exécuter leurs points d'entrée en tant que root afin de pouvoir amorcer les autorisations de répertoire et de fichier uniquement pour supprimer les privilèges avant d'exécuter le processus d'application.

Un vrai problème apparaît quand on se rend compte que tout le monde ne peut pas recourir à cette pratique. Pour certaines plates-formes populaires, comme Kubernetes ou OpenShift, certains de ces environnements peuvent être configurés pour ne pas autoriser les conteneurs privilégiés... parce que... la sécurité. Du haut de ma tête, je ne vois pas comment une grande institution financière envisagerait même d'adopter une plate-forme de conteneurs traitant des informations sensibles sans ce type de restriction.

Les problèmes de sécurité soulevés par la pratique _entrypoint-as-root_ ont conduit un grand nombre de graphiques helm Kubernetes à fournir initContainers pouvant chown et chmod volumes avant le démarrage du conteneur d'applications . Cela peut sembler être une bonne solution, mais croyez-moi quand je dis ceci : ce n'est pas le cas.

Les graphiques Helm, en particulier, sont jonchés de uids et gids codés en dur, car ceux-ci doivent être extraits secrètement de l'exécution de l'application. Ces informations sont cachées à l'intérieur du conteneur et ne sont pas disponibles rapidement lors du déploiement.

Bien qu'il existe un certain nombre de façons de contourner le problème, il continue de tourmenter les configurations de déploiement partout comme un _hack pour faire fonctionner les choses_. Le nombre de déploiements concernés par cela augmente rapidement et les techniques auxquelles les gens ont recours sont contraires à tous les autres avantages que les conteneurs apportent à la table.

J'espère qu'il existe un moyen d'implémenter cela dans le cadre de la spécification OCI afin que d'autres solutions qui dépendent de Docker puissent l'utiliser pour fournir avec élégance un déploiement entièrement automatisé.

ALORS, la question devient : où d'autre sur Internet développent-ils la spécification OCI commune, où cette discussion devrait-elle être menée ? En supposant que ce n'est pas la meilleure façon d'intégrer cette fonctionnalité à Docker (éventuellement, par le biais d'une exigence de conformité à une future adoption de normes communément convenues).

Étant donné que le problème ne disparaît jamais tout seul, la solution nécessite des changements très fondamentaux.

initContainers qui peuvent chown et chmod volumes avant le démarrage du conteneur d'application. Cela peut sembler être une bonne solution, mais croyez-moi quand je dis ceci : ce n'est pas le cas.

FWIW ; cette fonctionnalité ne serait nécessaire que dans les situations où les fichiers sont partagés entre plusieurs espaces de noms (soit des fichiers (pré)existants sur "l'hôte", soit un emplacement de fichier commun partagé entre plusieurs conteneurs exécutés en tant qu'utilisateurs différents). Dans les situations où les fichiers sont pré-créés sur l'hôte, cela peut être atténué en s'assurant que ces fichiers ont la propriété et les autorisations correctes avant de les partager avec le conteneur. En fait, ce n'est pas différent (par exemple) de l'exécution de nginx sur l'hôte et de la vérification que les fichiers de la racine Web disposent des autorisations appropriées.

Lors du partage entre des conteneurs qui s'exécutent en tant qu'utilisateur différent, exécutez les deux conteneurs avec le même uid (ou gid , et définissez les autorisations de groupe correctes, de la même manière que cela fonctionnerait lors de l'exécution de deux processus non conteneurisés qui doivent avoir accès aux mêmes ressources).

certains de ces environnements peuvent être configurés pour ne pas autoriser les conteneurs privilégiés... parce que... la sécurité. Du haut de ma tête, je ne vois pas comment une grande institution financière envisagerait même d'adopter une plate-forme de conteneurs traitant des informations sensibles sans ce type de restriction.

Juste pour éviter la confusion; un conteneur s'exécutant en tant que root n'est pas la même chose qu'un conteneur "privilégié" ( --privileged ou des options, telles que --cap-add définies). Les conteneurs privilégiés ( --privileged ) sont très peu sécurisés, alors qu'un conteneur fonctionnant sous root est entièrement confiné et ne pourra pas sortir ; lui transmettre des fichiers/répertoires montés en liaison, c'est percer des trous, donc _va_ lui donner accès aux fichiers/répertoires que vous transmettez en tant que montage en liaison.

Les graphiques Helm, en particulier, sont jonchés d'UID et de GID codés en dur, car ceux-ci doivent être extraits secrètement de l'exécution de l'application. Ces informations sont cachées à l'intérieur du conteneur et ne sont pas disponibles rapidement lors du déploiement.

Vous vous demandez : si ces uids/gids ne sont pas connus ; à quoi ressemblerait l'UX ? (car je devrais fournir un uid/gid de mappage à utiliser pour mapper un uid/gid hôte à un conteneur-uid/gid (inconnu) ?

ALORS, la question devient : où d'autre sur Internet développent-ils la spécification OCI commune, où cette discussion devrait-elle être menée ?

Je ne pense pas (en un coup d'œil) qu'une modification de la spécification OCI soit nécessaire ; cela peut être résolu en dehors de la spécification OCI ; le problème principal est que les mécanismes pour mapper les uids/gids sont actuellement manquants dans le noyau (ou existent (comme shiftfs ), mais ne sont pas couramment disponibles)

Il s'agit d'un pentagramme classique du passage du passage des responsabilités / quelqu'un d'autre peut ou doit résoudre ce problème. Soit c'est le :

  • Utilisateur
  • La mise en place spécifique de la plateforme Docker / conteneurisation
  • Spécification OCI
  • Noyau
  • Système de fichiers

Le problème a déjà été effectivement énoncé : le fait que l'utilisateur fasse cela est à la fois maladroit et moins sûr. Cependant, l'effet d'entraînement des utilisateurs faisant des hacks par image est également important :

C'est-à-dire que vous ne pouvez pas si facilement interagir et partager / mélanger des images pour travailler ensemble à partir de différents utilisateurs. Donc soit :

  • Casse le partage communautaire (beaucoup). Parce que différents utilisateurs définissent à partir du même pool d'espaces de noms global leurs uids et gids pour leurs images développées individuellement
  • Oblige les utilisateurs à développer leur propre norme ad hoc et espère que les autres suivront une convention qu'ils ont eux-mêmes choisie
  • Oblige les utilisateurs à utiliser root pour tout. Ce qui est pour certains moins sécurisé. Parce que vous supprimez une couche supplémentaire de protection contre l'escalade privilégiée que vous auriez autrement eue. Et rend les vulnérabilités de rupture de conteneur beaucoup plus faciles à exploiter, puisque l'utilisateur est déjà root à l'intérieur du conteneur pour commencer. Sans parler de la possibilité d'exécuter d'autres services dans le même conteneur, ce qui est également une autre façon d'aller de côté, avant de monter.

C'est donc un commerce. Ceux ci-dessus sont les compromis actuels. Alors que vous auriez différents ensembles de compromis pour transférer la responsabilité ailleurs, à une ou plusieurs des autres entités énumérées ci-dessus.

BTW, en ce qui concerne l'examen plus approfondi d'une solution basée sur le système de fichiers, a trouvé ce commentaire "potentiellement utile" des liens d'araignée :

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

Qui a plusieurs références différentes à cette même fonctionnalité générale (à d'autres projets/emplacements), y compris à un système de fichiers distribué (connu sous le nom de 'Lustre'), et à d'autres problèmes concernant ZFS. Eh bien, il se trouve que j'utilise moi-même ZFS ici.

Ensuite, j'ai également trouvé une autre copie du même bogue sur ubuntu / launchpad. Faisant référence au même problème ZOL # 4177,

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

Ce qui indique que le bogue en question a été corrigé dans la version zfs 0.6.5.7+ SO. Cela signifie-t-il que nous pouvons potentiellement utiliser zfs et ACL, comme une sorte de magasin de sauvegarde pour remapper les uid et les gid d'une manière ou d'une autre ? Eh bien, ce n'est pas quelque chose dont j'ai entendu parler auparavant.

Oh peut-être que cette solution ne fonctionne que pour les conteneurs LXC. Parce qu'il disait aussi dans ses commentaires là-bas (le responsable du projet LXC), "nous utilisons des assistants setuid (newuidmap et newgidmap)" qui peuvent ensuite "configurer une carte uid et gid". Donc, il y a probablement aussi un mécanisme nécessaire dans LXC lui-même, sinon la partie zfs acls ne peut pas être utilisée ? Ou peut-être que je me trompe. Je ne suis pas tout à fait sûr de suivre tout cela jusqu'au bout.

Un autre lien intéressant, cette fois sur shiftfs , et une discussion sur la possibilité d'absorber ses fonctionnalités dans des superpositions. Ce qui est bien sûr un système de fichiers sous-jacent que docker utilise déjà.

Cependant, que se passe-t-il si la fonctionnalité de remappage est implémentée dans overlayfs , mais que je souhaite utiliser le pilote de stockage zfs à la place pour mon système de fichiers sous-jacent ? Dois-je alors être exclu de la capacité de remapper les uids/gids, s'il est implémenté sur une base par système de fichiers ? Ou pouvons-nous avoir les deux implémentés séparément? Désolé, je ne sais pas si le démon Docker doit être conscient de ces remappages et fournir une API et des drapeaux communs (à transmettre à la couche de pilotes fs). Ou si nous effectuions à la place ce remappage manuellement nous-mêmes du côté hôte (dans le système de fichiers, en dehors de docker). Cet aspect reste également un peu flou pour moi.

[EDIT] Oups, j'ai oublié d'inclure le lien ! C'est ici

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

Ce problème concerne les volumes/bind-mounts, donc séparés du système de fichiers du conteneur

Nous utiliserions trop avec un décalage uid/gid pour le bindmount si la superposition incorporait des fonctionnalités shiftfs, mais nous devions nous rabattre sur autre chose (ou rien) sur les systèmes non pris en charge.

Podman est un remplacement sans racine de Docker https://www.youtube.com/watch?v=N0hSn5EwW8w https://podman.io/ . Avec podman, la racine n'est pas utilisée, l'autorisation de l'utilisateur est donc gérée correctement. Notre équipe est passée à Podman à cause de ce problème et a très bien fonctionné.

Cela n'a aucun sens.
Les mêmes problèmes s'appliquent.
Notez que docker a également un mode sans racine.

Vous pouvez tester Podman avec les commandes suivantes. Podman n'a pas de démon séparé contrairement à Docker, et tout s'exécute sous l'utilisateur qui exécute les commandes podman . Ainsi, les fichiers créés dans podman appartiennent à l'utilisateur qui a exécuté la commande podman run ... .

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

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

/podman_test #

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

Ce n'est pas l'endroit approprié pour faire de la publicité pour podman -- s'il existe des détails techniques spécifiques sur son fonctionnement qui peuvent aider à résoudre ce problème, il serait pertinent d'en discuter, en particulier en tant que solutions potentielles au problème que vous re commentant actuellement. Jusqu'à présent, ce n'est pas ce que cela a été, alors s'il vous plaît, prenez cette discussion ailleurs.

Le fait que podman ait une architecture très différente de Docker, ce qui rend ce problème moins grave/douloureux, ne permet pas magiquement à Docker de changer complètement son fonctionnement juste pour résoudre ce seul problème. Je peux vous assurer qu'il y a beaucoup de raisons pour lesquelles Docker est structuré comme il l'est, et c'est franchement une mauvaise foi d'ignorer toute cette histoire.

@tianon Oui absolument, il y a des avantages et des inconvénients pour les deux approches. J'ai mentionné podman simplement parce que l'exécution d'un conteneur avec podman avec l'utilisateur cible résout spécifiquement ce problème technique, à savoir "monter le volume en tant qu'utilisateur autre que root".

S'il vous plaît jeter un oeil à l'autorisation de "test_file" créé dans mon commentaire ci-dessus. Il monte d'abord le répertoire "~/podman_test" et écrit le fichier "test_file" dans le conteneur podman. Ensuite, une fois que l'utilisateur sort du conteneur, vous pouvez voir que le fichier appartient à "kkimdev", et non à root.

Le problème est que votre suggestion pour résoudre un problème avec Docker est que cela revient à "ne pas utiliser Docker", ce qui n'est pas très constructif sur le suivi des problèmes pour Docker.

Oui, podman est conçu différemment, ce qui rend ce problème sans objet pour cet outil - c'est bien, mais totalement hors sujet ici. Rootless a différents compromis, dont certains conviennent à certaines personnes, d'autres non. Cela s'améliore avec le temps (et surtout les améliorations du noyau), mais ce n'est pas une solution générique pour tout le monde ici.

Cela nécessite soit des modifications du noyau, soit un shim pour une solution générique, comme indiqué en détail ci-dessus (et comme @ cpuguy83 et d'autres ont travaillé pour essayer d'aider à résoudre ce problème de manière générique).

Docker avait ce problème particulier ouvert depuis 2013 et près de six ans plus tard, il n'y a pas d'amélioration facile en vue. Podman a été conçu pour gagner en compatibilité avec Docker, mais résoudre également les défauts de conception de Docker (y compris l'exécution en tant qu'utilisateur non privilégié qui ne nécessitera pas de démon Docker superutilisateur).

Si les utilisateurs sont en mesure de donner aux autres un conseil sur un problème GitHub, c'est très bien. Ceci est une communauté. N'hésitez pas à recommander tout ce qui pourrait être utile.

Je peux vous assurer qu'il y a beaucoup de raisons pour lesquelles Docker est structuré comme il l'est

Il en va de même pour grep . Mais si quelqu'un a besoin de chercher plus rapidement, je recommanderais toujours ripgrep . Même sur le suivi des problèmes grep . Peu importe de qui il s'agit, tant qu'il résout le problème des utilisateurs et les rend heureux.

Si Podman ne fonctionne pas pour vous : très bien ! Mais si cela aide les autres parce qu'ils n'ont qu'à remplacer docker par podman dans leur infrastructure : laissez-les faire.

L'argument principal de Podman est qu'il n'exécute pas de démon et c'est mon principal argument contre lui. Comment récupérer mon conteneur après un redémarrage ? Je ne le ferai pas à la main et tout le reste n'est que mauvaise conception. De plus, je ne veux pas que mon conteneur Docker appartienne à un utilisateur mais au système, ce qui signifie root.
Podman a du sens si vous êtes la seule personne à l'utiliser.

Et pour résoudre votre problème : Construisez un conteneur avec COPY --chown ...:... !

De plus, Docker n'a pas de tels problèmes et vous pouvez contrôler à distance les serveurs Docker, ce qui est également important pour moi.

Il existe des outils pour générer des pods à partir de conteneurs en cours d'exécution, ce que je ne recommanderai pas non plus, car vous devez les créer à partir de zéro de manière propre.

Je suppose que nous devrions revenir sur le sujet maintenant : à mon humble avis, le premier conseil était correct, mais tout le reste fait exploser ce problème et ne résoudra rien.


@ SuperSandro2000 , vous pouvez cependant cliquer ici pour la réponse à vos déclarations.

Comment récupérer mon conteneur après un redémarrage ? Je ne le ferai pas à la main et tout le reste n'est que mauvaise conception.

Eh bien, Podman a une intégration native avec systemd (comme _presque_ tout sur presque toutes les distributions GNU Linux modernes). Ainsi, vous n'avez pas besoin de maintenir "deux" systèmes de démarrage (comme avoir d'abord systemd pour démarrer le démon Docker qui doit ensuite effectuer une autre série de conteneurs de démarrage dans une configuration différente). Ainsi, avec Podman, vous pouvez tout contrôler avec systemd (ce qui signifie : le système que vous avez probablement déjà installé et en cours d'exécution de toute façon).

De plus, je ne veux pas que mon conteneur Docker appartienne à un utilisateur mais au système, ce qui signifie root.

C'est tout à fait bien si vous ne le voulez pas. Vous pouvez toujours exécuter Podman en tant que superutilisateur, mais vous n'avez plus à le faire. En général, cela est considéré comme une mauvaise idée et augmente la surface d'attaque car si quelqu'un est capable d'exploiter votre démon Docker, il a le contrôle sur _tout_ sur le système.

Podman a du sens si vous êtes la seule personne à l'utiliser.

Cette affirmation n'a aucun sens. Podman vous permet de vous répartir sur un seul système, ce qui est particulièrement utile si plusieurs personnes travaillent sur le même système.

Et pour résoudre votre problème : Construisez un conteneur avec COPY --chown ...:... !

À mon humble avis, le problème ici est de _monter_ un volume pour un conteneur sur _runtime_. Ce qui n'a que peu à voir avec la construction d'une image.

De plus, Docker n'a pas de tels problèmes et vous pouvez contrôler à distance les serveurs Docker, ce qui est également important pour moi.

C'est marrant que tu mentionnes exactement le blog qui contient ce post . Cependant, je ne suis pas très expérimenté avec les détails du réseau des deux implémentations, mais comme je l'ai compris, podman commence avec le moins de règles de réseau possible et les utilisateurs non privilégiés ne peuvent pas configurer les paires veth

Pour être clair, vous devriez pouvoir obtenir le même effet avec docker sans racine qu'avec podman.
En effet, dockerd s'exécute en tant qu'utilisateur et la racine du conteneur est mappée sur votre UID.

Cela a des inconvénients et ne fonctionne bien sûr pas lors du partage d'un démon avec plusieurs utilisateurs.
https://get.docker.com/rootless

Le 27 juin 2019 à 7h52, Alexander Adam [email protected] a écrit :

Je suppose que nous devrions revenir sur le sujet maintenant : à mon humble avis, le premier conseil était correct, mais tout le reste fait exploser ce problème et ne résoudra rien.

@ SuperSandro2000 https://github.com/SuperSandro2000 , vous pouvez cependant cliquer ici pour la réponse à vos déclarations.
https://podman.io/blogs/2018/09/13/systemd.html https://osric.com/chris/accidental-developer/2018/12/docker-versus-podman-and-iptables/ https:/ /osric.com/chris/accidental-developer/2018/12/using-docker-to-get-root-access/

Vous recevez ceci parce que vous avez été mentionné.
Répondre à cet e - mail directement, voir sur GitHub https://github.com/moby/moby/issues/2259?email_source=notifications&email_token=AAGDCZXX2UQCG7LUVH57V6LP4TH2DA5CNFSM4AI3DP62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYXL2XI#issuecomment-506379613 , ou couper le fil https://github.com/notifications/ désinscription-auth/AAGDCZX437HJP4M6XG3SEY3P4TH2DANCNFSM4AI3DP6Q .

@alexanderadam

À mon humble avis, le problème ici est de monter un volume pour un conteneur lors de l'exécution. Ce qui n'a que peu à voir avec la construction d'une image.

Ma solution était de ne pas monter le répertoire mais de le cuire dans le conteneur si c'est possible.

Je veux dire que le podman sonne bien mais je ne changerai pas car pour l'instant je ne vois aucun avantage pour moi. Merci pour l'explication en tout cas.

podman souffre du même problème si Apache à l'intérieur du conteneur est exécuté sous l'utilisateur www . https://github.com/containers/libpod/issues/3990

La solution pourrait être de mapper l'utilisateur www du conteneur à l'UID sur l'hôte s'il n'y a pas d'utilisateur root à l'intérieur du conteneur. Je ne sais pas si c'est possible.

Si vous souhaitez exécuter avec --read-only (pour faire la même chose que la politique Kubernetes readOnlyRootFilesystem ), il est possible de faire ce qui suit. Il s'appuie sur la solution de contournement que @jpetazzo suggérait :

  • Mon image docker crée et utilise un utilisateur avec uid=1001 et gid=1001
  • Séparément, créez un volume docker
  • Chown l' uid:gid à 1001
  • Montez cette image lors de l'exécution de l'application.

Dockerfile :

FROM ubuntu

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

USER appuser

Puis:

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

Maintenant, lors de l'exécution de l'image docker et du montage du volume, /some_dir appartient à l'utilisateur que je veux.

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

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

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

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

Je soulignerai à nouveau, car il se perd facilement dans le fil, qu'un lien symbolique chowned fonctionnera probablement pour la plupart des scénarios. L'inconvénient étant que vous avez besoin d'un moyen de le configurer, ce qui signifie souvent remplacer le point d'entrée par un script qui exécute ensuite la commande d'origine.

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

+1

Je pense que c'est jusqu'à présent le problème le plus ennuyeux que j'ai avec docker et voir combien de temps il est déjà ouvert suggère que ce n'est pas le cas pour beaucoup d'autres ?

Ce n'est pas un problème si vous connaissez la solution de contournement. Mes cas :

  • L'hôte est Linux

    • uid dans le conteneur == uid souhaité sur l'hôte - aucune solution de contournement n'est nécessaire
    • uid dans le conteneur != uid souhaité sur l'hôte - exécutez simplement quelques commandes setfacl et donnez l'accès rw à la fois à l'utilisateur hôte et à l'utilisateur du conteneur
  • L'hôte est MacOS - tout fonctionne immédiatement pour l'application Docker officielle.

il suffit d'exécuter quelques commandes setfacl et de donner un accès rw à la fois à l'utilisateur hôte et à l'utilisateur du conteneur

C'est un problème. Je ne veux pas exécuter quelques commandes setfacl pour chaque image docker et détecter le système d'exploitation.

C'est aussi un énorme problème de sécurité.

Exemple de scénario :

  • host1 a installé docker
  • host1 a plusieurs services exécutés dans des conteneurs docker - qui sont tous des chemins locaux de montage sous /docker/my-service-01|02|03|etc
  • chaque conteneur a été construit par un fournisseur différent et chacun suit sa propre politique uid et guid , vous obligeant ainsi à chown -R uid.gid /docker/my-service-01... en conséquence.

Résultat:

  • À un moment donné, les utilisateurs normaux ou de service créés sur host auront un accès complet à /docker/my-service-01|02|03|etc , ce qui n'est ni prévu ni souhaité.
  • Si vous souhaitez monter un volume en "lecture seule" sur deux conteneurs de fournisseurs différents, cela échouera car les uid.gid ne correspondront pas à ceux requis et vous ne pourrez pas chown car chaque conteneur a sa propre politique uid.gid et ils sont différents :)

Oui, nous avons longuement discuté de ce problème précédemment et le fait clé communiqué (à ce moment-là) était que le noyau Linux ne disposait pas d'un mécanisme de support sous-jacent pour fournir des uid et des gid remappables. Il faudrait donc ajouter au noyau pour que ce projet (moby / docker) implémente cette fonctionnalité hautement souhaitable. Sinon, nous aurions déjà obtenu cette fonctionnalité il y a quelque temps. À l'époque où il a été examiné pour la première fois.

Donc, la façon la plus productive de poursuivre cette discussion (aujourd'hui) serait de : voir si cette situation a changé depuis. Recherchez un commentaire technique des développeurs principaux du noyau Linux sur vger.org. Recherchez les anciens ensembles de correctifs / demandes de fusion sur le noyau pour cette fonctionnalité manquante sous-jacente. etc.

Dans l'espoir d'une meilleure compréhension de ce qui s'est passé à ce niveau inférieur. Quelle était la pierre d'achoppement ? Était-ce un problème de performances ? Était-ce une objection en termes de modèle de sécurité / d'affaiblissement ? Est-ce toujours sur la table ou dans une future feuille de route, mais n'a de sens qu'après l'implémentation des autres fonctionnalités B et C ? Tout ce développement du noyau se poursuit ailleurs. Dans d'autres canaux.

@DXist Le fait que cela fonctionne comme par magie sur OSX et non sur Linux est surprenant et constitue un problème en soi.

Selon le dernier commentaire de @ dreamcat4 , quelqu'un a-t-il fait une nouvelle tentative pour voir quel en est le statut ? Avons-nous maintenant un support dans le noyau pour les uids et gids remappables ? Quel est l'état général ici ?

J'ai utilisé Linux User Namespaces pour résoudre parfaitement ce problème. Fonctionne exactement de la même manière (AFAICT) que les autres plates-formes (le conteneur voit le volume monté lié comme racine, l'hôte le voit comme l'utilisateur qui exécute docker).

Le guide est ici : https://www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/

@patrobinson +1

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