Moby: Machen Sie uid und gid für freigegebene Volumes konfigurierbar

Erstellt am 23. Juli 2014  ·  141Kommentare  ·  Quelle: moby/moby

Geben Sie eine Option an, um den Besitz von freigegebenen Volumes konfigurierbar zu machen.

Mein aktueller Anwendungsfall besteht beispielsweise darin, dass der Logstash-Forwarder in einem Container ausgeführt wird, der /var/lib/docker schreibgeschützt als Volume vom Host freigegeben hat.

Da /var/lib/docker auf dem Host auf 0700 root:root gesetzt ist, kann ich als Nicht-Root-Benutzer nicht auf das Volume zugreifen.

Was ich gerne hätte, ist so etwas wie bei NFS, wo man uid & gid vom Host auf Benutzer & Gruppen auf dem Client abbilden kann.

Dh docker run -v /var/lib/docker:/var/lib/ docker:ro :$user:$group würde das Volume im Container schreibgeschützt verfügbar machen, das zu $user:$group gehört.

kinfeature

Hilfreichster Kommentar

Wir brauchen wirklich eine plattformübergreifende Go-to-Lösung (nicht gosu), um uid/gid zuzuordnen. Allein dieses Problem verursacht enorme Schäden in der Wahrnehmung von Docker durch Anfänger.

Alle 141 Kommentare

Ich weiß nicht, _wie_ sie dies implementiert haben, und wenn eine vergleichbare Funktion unter Linux existiert, aber unter OS X, existiert eine Funktion, um den Besitz eines Volumes zu ignorieren. Effektiv wird dies dazu führen, dass _jeder_ Benutzer die Dateien/Verzeichnisse sieht, als ob er der Eigentümer wäre.

Obwohl dies nicht allen Fällen dient, kann es eine nette Ergänzung sein

gh#5910 handhabt dies von der SELinux-Seite.

Link: #5910 ;)

Die SELinux-Änderung ändert tatsächlich die Beschriftungen des Inhalts. Möglicherweise können Sie die Änderung auf dem Host vornehmen. Ich kenne keine andere Möglichkeit, dies für UID/GID zu tun. Aber chown -R $UID:$GID auf dem Mount-Punkt.

Oder Sie können diese Art des Zugriffs mithilfe von ACLs hinzufügen. Aber ich denke, Sie müssen jede INODE am Mount-Punkt ändern.

Ich brauche diese Funktion auch.

Ich möchte beispielsweise einen Web-Container erstellen und Volumes mit Websites und Konfigurationen anhängen, damit der Container für eine beliebige Anzahl von Websites vollständig universell ist.

Ich benötige jedoch Git-Zugriff, um Code in das Website-Repository zu übertragen. Da ich möchte, dass meine Apps isoliert werden, möchte ich, dass jedes Website-Verzeichnis einem separaten Benutzer / einer separaten Gruppe gehört, und es wäre großartig, wenn Dateien, die vom Docker-Container in das Volume geschrieben werden, diesem separaten Benutzer / dieser separaten Gruppe gehören.

+1 für diese Funktion.
Ich verstehe nicht, wie Lese-/Schreib-Volumes ohne es funktionieren können. Zu erwarten, dass die guid/uid auf dem Image und dem Host gleich ist, ist eine starke Anforderung, die mit den Isolationsprinzipien von Docker nicht vereinbar ist.

Ich persönlich arbeite daran mit hässlichen und langsamen useradd/groupadd-Befehlen für meine Dockerized-Entwicklungstools: https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/bin-docker/nspire-docker

Ich könnte den Punkt völlig übersehen. Aber ich hatte mit einem ähnlichen Problem zu kämpfen, bei dem ich sicherstellen möchte, dass der http-Benutzer Schreibberechtigungen auf /var/log hat, einem Volume, das wahrscheinlich vom Host mit root:root als Eigentümer stammt.

Ich habe es gelöst, indem ich einen Einstiegspunkt festgelegt habe, der sicherstellt, dass die Protokollverzeichnisse erstellt werden und die richtigen Berechtigungen haben. Ich denke, das funktioniert, weil das Einstiegspunktskript als Root ausgeführt wird.

(Kommentar entfernt - falscher Tab, sorry)

Ich habe dies in Ubuntu außerhalb von Docker gehackt. Installieren Sie das Paket bindfs und binden Sie das Verzeichnis mit dem Volume-Inhalt an einen anderen Pfad, während Sie UID und GID den im Container verwendeten zuordnen:

sudo bindfs -u UID -g GID oldpath newpath

Verwenden Sie dann newpath als Docker-Volume. Oldpath zeigt immer noch die richtigen Besitzrechte für den Host an, newpath für den Gast.

@jjv das Problem ist, dass bindfs

@ cpuguy83 ja, es ist

Es wäre eigentlich schön, wenn eine Art von bindfs-Funktionalität verwendet würde, wenn Docker dies implementiert, vorausgesetzt, es verursacht keine zu großen Leistungseinbußen. Auf diese Weise müssen Sie nicht sicherstellen, dass der Container als der richtige Benutzer ausgeführt wird. Es sollte auch möglich sein, logische Namen anstelle des Literals uid/gid zu verwenden.

@jsternberg Es ist ein GROßER Performance-Hit. Ziemlich ähnlich wie die Verwendung von freigegebenen vbox-Ordnern.

+1

für die Anwendungsfälle der lokalen Entwicklung denke ich, dass Docker diese Funktion auf jeden Fall braucht. Und in einem solchen Fall möchte ich, dass diese Funktion sowohl Windows als auch OSX unterstützt.

Vagrant scheint dies zu unterstützen, indem die UID/PID des Host-Benutzers der des Vagrant-Benutzers zugeordnet wird. Aber für Entwicklungszwecke möchte ich Docker anstelle von Vagrant verwenden, da es viel leichter als Vagrant für die Ausführung von Multi-Host-Anwendungen ist.

Bitte sagen Sie mir, was mir hier fehlt (ich habe keine Erfahrung mit Go), aber akzeptiert die Funktion Go Mount() keine Flags? Könnten wir nicht einen Befehl zulassen wie
-v host/folder:container/folder -mount-as user:group
Könntest du nicht einfach die uid/gid mit lookup abrufen (https://golang.org/src/os/user/lookup_unix.go)
und sie dann (uid=1,gid=1) als Flags an Mount() übergeben? (https://golang.org/src/syscall/syscall_linux.go?s=19154:19249#L754)

@krisgraham bind-Mounts unterstützen die Einstellung von uid/gid nicht.

Auch das Trennen der Option -v von der Option --mount-as führt zu Verwirrung, wenn mehrere Optionen -v vorhanden sind

Was ist ein guter Workaround dafür? Ich würde Docker gerne für die aktive Entwicklung verwenden, und kein gemountetes Volume zu haben, ist keine wirkliche Option, da ich jedes Mal neu erstellen müsste, wenn ich meinen Code ändere.

Der Grund, warum ich Docker für die aktive Entwicklung verwenden möchte, ist, dass es mit meiner Produktionsumgebung konsistent ist.

@berfarah Ich benutze Docker für die aktive Entwicklung jeden Tag.
Es ist selten der Fall, dass ich mit Dauerwellen herumspielen muss.
Wenn Sie boot2docker unter OSX verwenden, stellen Sie sicher, dass Ihr Arbeitsverzeichnis in /Users liegt und es Ihnen gut geht.

@cpuguy83 Danke für die schnelle Antwort. Ich habe Berechtigungsprobleme mit einer Rails-Umgebung, in der keine Protokolle geschrieben werden können, und es gibt gelegentlich Fehlerquellen aufgrund von Berechtigungen. Dies liegt daran, dass meine Dienste eine andere UID haben als die der Dateien.

@berfarah Meine

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

@berfarah Haben Sie Protokolle, um stdout/stderr für RAILS_ENV=development zu gehen?

@cpuguy83 Dieses Problem betrifft OSX nicht; thaJeztah kommentierte am 24. Juli 2014:

Unter OS X gibt es eine Funktion zum "Ignorieren" des Eigentums an einem Volume. Effektiv wird dadurch jeder Benutzer die Dateien/Verzeichnisse sehen, als ob er der Eigentümer wäre.

@ncjones eigentlich gilt das gleiche für OS X. Die "Volumes", von denen ich dort gesprochen habe, sind die Festplatten / Partitionen (Volumes), die auf OS X selbst verwendet werden. Ich bezweifle, dass dies einen Unterschied für die Arbeit mit Boot2Docker macht, aber ich bin mir nicht sicher.

Mein Kommentar sollte darüber informieren, ob unter Linux (also innerhalb der Boot2Docker-VM) etwas _Ähnliches_ möglich ist.

Sorry für die Verwirrung dort.

@ryneeverett Danke, das ist hilfreich. Ändern Sie dann nur die Berechtigungen von 755 auf 775 und von 644 auf 664, wo Sie es brauchen? Edit: Lesekompetenz!

@cpuguy83 Danke! Das scheint eine einschränkendere Lösung zu sein als die Lösung von @ryneeverett , da ich sie nicht auf alle Projekte übertragen kann.

@berfarah Schön , dass Sie das hilfreich fanden. Ja, ich stelle nur sicher, dass meine Hostdateien die richtigen Berechtigungen haben und Docker behält sie in den Volumes bei.

+1

Dies wäre für freigegebene Volumes über Docker äußerst nützlich und behebt ein Sicherheitsproblem, das ich habe:

  • Freigegebene Volumes, bei denen die Container-UID und -GID versehentlich einem privilegierten Nicht-Root-Benutzer auf dem Host zugeordnet sind. (z. B. die vom Container auf dem Host erstellten Dateien werden einem Benutzer zugeordnet, der ohne Passwd sudo, auf anderweitig eingeschränkte Inhalte zugreifen kann usw.)

Dies zu beheben wäre sehr praktisch für Unternehmen, die eine Menge Container mit Apache oder einer Middleware ausführen und die Protokollierungsvolumes und/oder verschiedene Inhalts-/Upload-Verzeichnisse verteilen. Ich persönlich hatte auch einige Kopfschmerzen mit diesen Berechtigungen beim Containerisieren von Endbenutzer-Apps in Linux (wie syncomm/spotify). Viele der heutigen Workarounds sind selbst problematisch. Letztendlich muss dies im Docker behoben werden. Ich fühle mich besonders nicht wohl dabei, Root-Shell-Skripte als Einstiegspunkt auszuführen, insbesondere wenn dieses Problem hervorhebt, wie die 0:0-uid/gid im Container auf root auf meinem Host abgebildet wird. Ich mag den ursprünglichen Vorschlag "docker run -v /var/lib/docker:/var/lib/ docker:ro :$user:$group".

@syncomm Ich würde genau das Gegenteil vorgehen.
Docker kann keine Annahmen über das Eigentum an Ihren Daten treffen.

Der Ansatz, den Sie am Ende Ihres Kommentars hervorheben, wäre machbar, wenn wir diese echten Dateien automatisch einem auf Sicherungen basierenden fs zuordnen würden, in dem wir uids/gids ändern können ... und dies würde einen erheblichen Einfluss auf die Leistung haben.

Und bald wird uid 0 im Container nicht mehr uid 0 auf dem Host sein ... was auch den Dateibesitz noch komplizierter macht.

Ist das ein Duplikat von #2259?

@ cpuguy83 Vielen Dank für das Feedback, obwohl ich nicht sicher bin, was Sie mit dem genau entgegengesetzten Ansatz meinen. Cloud erklären Sie? Ich würde zustimmen, dass das Eigentum an Daten nicht von Docker übernommen werden sollte, aber ich glaube, dass die Bereitstellung einer konsistenten Zuordnung von Container zu Host die Aufgabe der Überwachung dieser Daten für Docker-Konsumenten erheblich erleichtert.

Ich stimme zu, dass es, wie bei der Problemumgehung von bindfs, einen erheblichen Overhead verursachen würde, es zu einem Fuse-Wrapper zu machen. Es muss jedoch einen Ausweg ohne hohe Strafen geben. Im Wesentlichen verhält sich der Container korrekt (als wäre er eine separate, eindeutige Maschine vom Host), und wenn wir das Verzeichnis eines Hosts als Volume mounten, sieht er (korrekt) das POSIX-Dateisystem dort, Berechtigungen und alles. Leider macht es das wirklich schwierig, Daten zwischen den beiden "Hosts" auf konsistente Weise zu teilen. Dinge wie nfs, cifs usw. werden dafür verwendet und unterstützen das UID- und GID-Mapping - ich würde denken, dass es hier eine Parallele zur Lösung des Problems geben könnte. Ehrlich gesagt muss ich mehr in das Repo eintauchen, um herauszufinden, wo dies im Code passiert, und es besser zu verstehen.

Wann werden die von Ihnen erwähnten Änderungen bezüglich der Dateieigentümerschaft aufgehoben? Da die uid 0 für Container und Host NICHT gleich ist, würde ich mich viel wohler fühlen, einen Einstiegspunkt für ein Root-Shell-Skript zu erstellen. Dann müssen Sie nur noch die vorgeschlagene Problemumgehung ausführen, indem Sie die richtige uid/gid als env übergeben und beim Containerstart einen Adduser ausführen.

@syncomm Leider, meines Wissens nicht, nicht ohne sie in ein anderes Dateisystem zu packen, das mit uid/gid-Einstellungen gemountet werden kann.

Letztendlich sieht dies nach etwas aus, das Kernel-Unterstützung für die vollständige bidirektionale Neuzuordnung von UIDs und GIDs erfordert und nicht einmal einfach zu verwalten aussieht.

Für nicht leistungsempfindliche Szenarien könnte vielleicht etwas mit FUSE getan werden.

Immer noch +1 für Anwendungsfälle in der Entwicklung, da ich bei mir zu Hause Dateien im Besitz von Root habe.

Für meinen Anwendungsfall würde es ausreichen, wenn Docker beim Erstellen des Host-Volumes nur benutzerdefinierte uid/gid- und selinux-Label anwenden könnte, wobei die Berechtigung und die Labels allein bleiben, wenn das Verzeichnis bereits vorhanden ist. Derzeit kann ich das umgehen, indem ich einen separaten Einstiegspunkt für das Image habe, das als Root ausgeführt wird, nur um die Volume-Berechtigung zu beheben.

@ibukanov kann uid/gid nicht anwenden, aber das Selinux-Label kommt.

@ cpuguy83 Was ist der technische Grund dafür, dass beim Erstellen eines Host-Volume-Verzeichnisses keine benutzerdefinierte UID/GID angewendet werden kann?

@ibukanov Siehe obige Kommentare.

@ cpuguy83 Ich sehe aus den Kommentaren einfach nicht, was das Problem ist. Für meinen Anwendungsfall benötige ich keine Neuzuordnung von uid/gid. Derzeit innerhalb des Containers, wenn ich als Root ausgeführt werde, kann ich chown uid:gid /host_volume && chmod 770 /host_volume . Was wäre schön, wenn der Docker das alleine kann, wenn er das Verzeichnis auf dem Host hinter /host_volume anlegt. Auf diese Weise würde ich keinen Hack benötigen, um einen zusätzlichen Einstiegspunkt im Container bereitzustellen, nur um die obige Operation als Container-Root auszuführen, und kann den Code immer mit einem Nicht-Root-Konto ausführen.

@ibukanov Ah, das ist etwas anderes.
Docker nimmt absichtlich keine Änderungen an den Hostverzeichnissen vor.
Wenn wir #9092 ausführen, dann behandelt Docker, wenn er das Verzeichnis erstellt hat, es wie ein normales Volume (dh kopiert alles im Volume-Pfad im Container auf den Host und chmod/chown so, wie es im Container war).

@cpuguy83 -

@cpuguy83 schrieb:

Und bald wird uid 0 im Container nicht mehr uid 0 auf dem Host sein ... was auch den Dateibesitz noch komplizierter macht.

Gibt es ein bestehendes Problem, um dies zu verfolgen? Ich konnte keinen finden.

Vielen Dank!

Gibt es ein bestehendes Problem, um dies zu verfolgen? Ich konnte keinen finden.

@dato Suchen Sie nach "Benutzernamensraum"; eine erste Implementierung findet sich hier: https://github.com/docker/docker/pull/12648 und hier https://github.com/docker/docker/pull/11253

Aber es gibt verschiedene Diskussionen / Probleme davor :)

+1

nur damit ich weiß, dass ich mit allen im selben Boot sitze:

Ich verwende das nginx-Image und mounte ein Volume in /usr/shared/nginx/html für die lokale Entwicklung. Nginx läuft als www-data , aber das Volume wird als 1000:staff gemountet und so erhalte ich 403 forbidden .

@MrMMorris Ich glaube nicht, dass dies dasselbe Boot ist - dieses Problem tritt auf, wenn Dateien, die in einem Container (auf einem bereitgestellten Volume) erstellt wurden, außerhalb des Containers ohne Sudo-Zugriff nicht gelesen werden können. Ihr www-data-Benutzer benötigt nur Lesezugriff auf die bereitgestellten Dateien, daher sollten Sie nur chmod a+r auf Ihre Dateien zugreifen können.

@ncjones chmod/chown scheint keine Auswirkungen auf die Berechtigungen im Container zu haben

Ich bin so verwirrt, weil ich schwöre, dass dies während meiner Verwendung an mehreren Stellen funktioniert hat ...

Okay, das ist peinlich...

Es scheint, dass entweder nach dem Upgrade auf 1.3.0rc-1 (wahrscheinlich nicht) ODER das Löschen aller meiner Container/Images und das erneute Ausführen von docker-compose up alles behoben hat .... Nicht mehr 403 forbidden

Ich wusste schon vorher, dass es irgendwie funktioniert, also habe ich den alten rm -rf * Ansatz gewählt.

Ich brauche dieses Problem auch irgendwie gelöst. Ich habe ein Docker-Image, das ich verwende, um einige umfangreiche Kompilierungsarbeiten auszuführen, die isoliert werden müssen. Der Container muss also hochfahren, einige externe Eingaben empfangen, verarbeiten und dann die Binärdateien (Ausgaben) erstellen. Ohne die richtige Berechtigungsverwaltung war es ein Albtraum, dies zum Laufen zu bringen. Meine Bilder müssen portabel sein, daher kann ich nicht viel über den Host aussagen.

@alercunha In Ihrem Fall klingt es gut, einen einzelnen Benutzer im Docker-Container zu verwenden, dh als Root zu kompilieren

@alercunha
Wir haben dieses Problem in einer Build-Einstellung umgangen, indem der Docker-Container die Build-Ausgabe geändert hat. Unser Dockerfile enthält so etwas wie:

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

Die tatsächliche uid/gid des Benutzers des Docker-Hosts kann dann bei der Ausführung dem Container bereitgestellt werden. Ein Jenkins-Build-Befehl verwendet beispielsweise Folgendes:

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

@motin Das

@ncjones Danke! Das ist eigentlich eine gute Idee, könnte in meinem speziellen Fall als Lösung gut funktionieren.

@alercunha In diesem Fall lohnt es sich möglicherweise, für jedes

Um alle Privilegien für www-data zu erteilen, können Sie Folgendes verwenden:

RUN usermod -u 1000 www-data

Beim Ausführen eines Auftrags im Docker auf einem bereitgestellten Volume ist ein Problem aufgetreten. Die resultierenden Dateien waren im Besitz von root und konnten von dem Benutzer, der den docker-Befehl ausführte, nicht verwaltet werden. Die aktuelle Problemumgehung besteht darin, nach dem Auftrag auszuführen, um die Berechtigungen zu korrigieren.

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

Ist es möglich, dass Docker die Berechtigung von hostbasierten gemounteten Volumes so ändert, dass sie dem Benutzer gehören, der im USER-Befehl von DockerFile angegeben ist? Natürlich müssen die Berechtigungen konfigurierbar sein, aber wir können dies als Standardverhalten festlegen.

@mig-foxbat
Für meine Zwecke würde es ausreichen, wenn docker beim erstmaligen Erstellen des Hostverzeichnisses nur den Besitz und die Berechtigung für das Hostverzeichnis vom Einhängepunkt im Image festlegt. Wenn das Hostverzeichnis bereits existiert, könnte der Docker es in Ruhe lassen.

@mig-foxbat & @ibukanov die zwingende Voraussetzung für mich beim Öffnen dieses Problems war, dass die Berechtigungen auf dem Hosts-Dateisystem nicht geändert werden (wie bei einer virtuellen in Container-Zuordnung ähnlich wie bei _NFS_).

Was Sie versuchen, können Sie heute leicht tun, indem Sie _chown_ in einem Startskript in Ihrem Container ausführen.

Ich liebe die kommende Volume-Plug-in-Architektur, aber ich würde es viel lieber machen, dass das Docker-Team diese Funktion hinzufügt. Docker funktioniert gut, bis Sie Volumes mit Nicht-Root-Benutzern in Ihrem Container verwenden. Wenn dann Dinge (zB Logging) nicht funktionieren, werfen Sie entweder Ihren Laptop durch das Starbucks-Fenster oder Sie finden das oben genannte Stackoverflow-Element.

+1 Ich möchte Container haben, die Anwendungen als Nicht-Root-Benutzer ausführen, was aufgrund dieses Problems kompliziert wird.

Warum implementieren Sie diese Funktion nicht mit der id_map-Funktion von LXC?

Mir ist gerade aufgefallen, dass die Antwort auf "id_map" (auch bekannt als User Namespace-Unterstützung) oben bereits von @thaJeztah erwähnt wird

Während es ein wenig zusätzliche Arbeit erfordert, Berechtigungen festzulegen, führen wir Dutzende von Containern als Nicht-Root-Container aus und vermeiden die Berechtigungsprobleme. Die meisten unserer Datencontainer beginnen mit etwas wie:
ENV CONTAINER_USER Konsul
ENV CONTAINER_UID 312312
RUN adduser -D $CONTAINER_USER -u $CONTAINER_UID
RUN mkdir -p /var/consul/
CMD chown $CONTAINER_USER.$CONTAINER_USER /var/consul/

Der eigentliche Run-Container ist in Bezug auf das Festlegen der UID/useradd-Informationen ähnlich. Dies ist eine doppelte Arbeit (die UID muss sowohl für den Datencontainer als auch für den Ausführungscontainer festgelegt werden), aber es ist ziemlich gering. Wenn Docker-Berechtigungen oder Kartenberechtigungen spontan ändern, würde dies eine gewisse Komplexität erhöhen, und Benutzer müssten aus Sicherheitsgründen vorsichtiger sein. Ich bin auch für alles, was dazu beiträgt, die Komplexität der Befehlszeile zu reduzieren. Wenn also alles in der Dockerdatei enthalten ist, ist es etwas einfacher, was passiert.

Jetzt gibt es den obigen Hinweis, dass versucht wird, auf Hostdateien in einem Container mit einer Art Zuordnung zuzugreifen. Ich denke, das ist sicherlich ein riskantes Unterfangen. Oft ist es wahrscheinlich die beste Lösung, Dateien ohne direkte Hostzuordnung zu teilen, da Sie sonst die Docker-Sicherheit etwas invertieren. Anstatt eines Containers mit weniger Berechtigungen als sonst, sprechen Sie von einem Container, der als Nicht-Root ausgeführt wird und Zugriff auf Root-Ebene hat (vermutlich häufiger Anwendungsfall) zum Hosten von Dateien. Gruppenberechtigungen oder andere Lösungen sollten sich meiner Meinung nach in den meisten Situationen durchsetzen.

Ich habe dies mit einem Einstiegspunkt-Shell-Skript umgangen, das das gemountete Verzeichnis chowns und den Unterbefehl über su ausführt.

Ein Beispiel in einem solr-Container, in dem das Verzeichnis /data als Volume vom Host bereitgestellt wird:

#!/bin/bash

chown -R $SOLR_USER:$SOLR_USER /data

su -c "$@" -m $SOLR_USER

_BENUTZER-UMFRAGE_

_Der beste Weg, um über Änderungen in dieser Diskussion benachrichtigt zu werden, besteht darin, oben rechts auf die Schaltfläche Abonnieren zu klicken._

Die unten aufgeführten Personen haben Ihre aussagekräftige Diskussion mit einem zufälligen +1 gewürdigt:

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

Wenn Sie etwas in diesen Threads sagen, abonniert ein Benutzer automatisch, also werden alle diese Leute abonniert, es sei denn, sie haben sich zusätzlich absichtlich abgemeldet. (auch nicht sicher, auf wen_ Sie sich als your beziehen)

Dies ist definitiv ein Muss. Docker muss UIDs richtig neu zuordnen. Ansonsten gehört alles, was vom Container bis zum Host-Betriebssystemvolume erstellt wird, dem Root. Der Workaround ist furchtbar - wechselnde Benutzer innerhalb des Containers, was zu allerlei Komplikationen führt, überall knabbern zu müssen, das Dockerfile wächst hässlich. Und das Schlimmste von allen hartkodierten UIDs macht die Container unportabel!

+1 Diese Funktion wäre sehr dankbar, da ich vermeiden möchte, zwischen Docker-Container und meinem Hostsystem zu wechseln, nur um zu vermeiden, dass die Benutzer-ID in Dateien überschrieben wird.

Eine UID-Anpassung ist ab sofort möglich, jedoch innerhalb der folgenden Einschränkungen:

  • Eine Uid-Anpassung ist möglich, indem der Container die Uid(s) akzeptiert, die er über eine Umgebungsvariable benötigt. Dies gibt dem Host die volle Kontrolle über die UID(s), die der Container verwendet, und hat einen zusätzlichen Vorteil: Mehrere Variablen können auf denselben UID-Wert gesetzt werden. Die Uid-Neuzuordnung kann die Zuordnung mehrerer Container-UIDs zu einer einzelnen Host-UID nicht unterstützen, da die Zuordnung 1:1 erfolgen muss. Wenn die gewünschte Zuordnung beispielsweise darin bestand, dass die Anwendung als uid=0 ausgeführt werden soll, können Sie dies durch Einfügen von Variablen tun, jedoch nicht über die Neuzuordnung von UID. Siehe @ncjones- und @mitchcapper- Lösung oben.
  • Die Root-UID=0 kann jedoch insbesondere nicht auf einen anderen Wert geändert werden, außer durch Neuzuordnung: #12648.

Fast alle modernen Webentwicklungs-Frameworks haben einen Logs-Ordner und einen Cache-Ordner, die sich innerhalb des Projekts befinden, in der Projektkonfiguration definiert und über das gemountete Volume freigegeben werden. Ich habe zuerst vboxfs verwendet, war aber zu langsam. Ich habe docker-machine-nfs gefunden , um NFS-Mounts zu erstellen, und es ist schnell, aber jetzt gehören meine Webdateien in Containern 502:dialout und können nicht chmod oder chown sein, sodass meine Web-App nicht ausgeführt wird. Ich habe die Docker-Vagrant-Box ausprobiert

+1

Für diejenigen, die diesem folgen; Derzeit gibt es eine PR für eine experimentelle Funktion, die den Besitz von gebundenen Dateien rekursiv ändert. Es sollte jedoch mit Vorsicht verwendet werden, da diese Funktion die Dateien auf dem Host ändert (was möglicherweise nicht in allen Fällen das ist, was Sie wollen); siehe https://github.com/docker/docker/pull/14632 (und https://github.com/docker/docker/pull/16767)

+1

Übrigens habe ich dieses Problem mit ACL gelöst

@kvaps ,

@posita , meine Wette ist, dass @kvaps über POSIX-ACLs spricht. Wenn ich richtig liege, ist das nicht dasselbe wie die OP-Anfrage.

@posita , @denydias , sorry für die lange Antwort. Ja, ich rede davon.
Ich habe viele Container wie owncloud, samba und minidlna. Jeder arbeitet mit anderen UID und Gid.
Sie arbeiten alle mit den gleichen Dateien. Was würde jeder Dateien lesen und schreiben können? Ich habe das Dateisystem mit der Option acl in den Host-Rechner gemountet und jedem die Uid- und Gid-Rechte für diese Dateien einfach gegeben, wie zum Beispiel chown Befehl:

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

@kvaps , Befehl setfacl funktioniert nicht in Dockerfile . Beispiel:

FROM nginx

ADD data/conf /etc/nginx

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

VOLUME /etc/nginx

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

Ergebnis:

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

ACLs funktionieren nur nach dem Mounten auf dem Host-Rechner und Ausführen von setfacl . Docker-Version:

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

Dies ist sehr einfach richtig zu machen und auch sehr einfach zu vermasseln. Also nicht vermasseln!
Der richtige Weg, dies zu tun, ist: Beim ersten Ausführen des Containers injiziert der Host, welche Uids der Container verwenden soll (wie oben bereits beschrieben).
Der schlimmste Weg, dies zu tun, ist: Erwarten Sie, dass der Container dem Host seine UID-Anforderungen auferlegt. Das ist falsch, falsch, falsch. Betrachten Sie beispielsweise zwei Container, die sich einen gemeinsamen Mount teilen: Ein Container schreibt Dateien zum Bereitstellen, und ein anderer Container führt httpd aus, um die Dateien bereitzustellen. Wenn beide Container konkurrierende Definitionen für uid haben, ist dieses System schlimmstenfalls kaputt oder bestenfalls mangelhaft. Die gesetzten ACLs ergeben für den Host keinen Sinn und sind wahrscheinlich breiter als nötig, was bedeutet, dass es sich jetzt um ein Sicherheitsproblem handelt. Bitte mach das nicht!! Mach es richtig.

Einverstanden. Es ist eine gute Lösung, die Zuordnung zwischen UID und Container zu belassen. Wollte nur, dass Docker mit gutem Beispiel vorangeht und solche UID/GID-Mappings in den offiziellen Docker-Images unterstützt.

Zur Laufzeit gelöst, ohne chown .

Ich habe etwas verwendet , das der Lösung von kommt , aber ich möchte keine chown Dateien verwenden, da ich nicht möchte, dass sie auf dem Host geändert werden. Also habe ich mich entschieden, die UID beim Containerstart zu ändern.

Ich erstelle einen dedizierten Benutzer in meinem Dockerfile :

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

Ich definiere ein Startskript in meinem Dockerfile :

CMD ["/run.sh"]

Ich habe diese Zeile in meinem /run.sh Skript:

usermod -u $USER_ID username

Jetzt kann ich USER_ID auswählen, wenn der Container startet:

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

Es ist gelungen, dies mit den neuen Dockerfile-Argumenten zu lösen. Es ist nicht erforderlich, nach dem Erstellen des Containers etwas Besonderes zu tun, also dachte ich, ich würde es teilen. (Erfordert Docker 1.9)

Im Dockerfile:

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

Dann bauen:

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

Alles andere ist wie gewohnt :)

Bearbeiten:
Ich habe diesen Beitrag zum falschen Thema geschrieben (es war ein anderer im Zusammenhang mit boot2docker).
Es tut uns leid.

@pa-de-solminihac usermod -u $USER_ID username ändert die Benutzer-ID von username und löst eine Eigentumsänderung der Dateien in username s HOME aus, aber jede Datei, die zuvor im Besitz von . war username außerhalb seines HOMEs werden wahrscheinlich unlesbar/unbeschreibbar, da sie jetzt einem anderen Benutzer gehören

@riquito Ich verwende es mit einem dedizierten Benutzer, der im Dockerfile :

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

Daher gibt es keine Dateien, die zuvor im Besitz von username . Also ich denke es gibt kein Problem ;)

Zu Ihrer Information, setfacl funktioniert _nicht_ auf Volumes, die auf OS X zurückgehen:

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

(In diesem Fall wird /opt/test von OS X über die Docker-Maschine und Boot2Docker gehostet. Siehe auch boot2docker/boot2docker#581.)

@posita Verwenden Sie Virtualbox, um Ihr Boottodocer-Image zu hosten? Wenn ja, kann dies tatsächlich eine Einschränkung bei der Art und Weise sein, wie virtualbox freigegebene Ordner verwendet. Ich hatte eine Menge Probleme, eine regelmäßige Durchlässigkeit durch den freigegebenen Ordner der virtuellen Box zu erreichen.

@ava-dylang, das ist ein guter Punkt. Das obige geschieht über Docker Machine mit dem Parallels-Treiber , der die native Implementierung von Parallels für freigegebene Ordner verwendet, die ähnlich eingeschränkt erscheint. (Siehe auch https://github.com/docker/machine/issues/13#issuecomment-164320881 bezüglich eines Vorschlags für diese Arten von Umgebungen.)

FWIW, ich hatte Probleme mit dem Dateibesitz in meinem Dienstprogramm Scuba .

Ich habe das Problem umgangen, indem ich ein "init" -Skript hinzugefügt habe, das einen Benutzer im Container mit derselben UID/GID wie der aufrufende Benutzer im Host erstellt. Siehe JonathonReinhart/scuba#11 und JonathonReinhart/scuba#13.

Jetzt sehen im Container erstellte Dateien genau so aus, wie sie auf dem Host erstellt wurden.

_Update:_ Das führte zu Problemen (JonathonReinhart/scuba#22). Ich habe es stattdessen behoben, indem ich meine eigenen /etc/passwd und Freunde generierte, basierend auf der uid/gid des Host-Benutzers, und sie in den Container injizierte (siehe JonathonReinhart/scuba#24).

+1

Um es wartungsfreundlicher und sicherer zu machen, wenn der Host im Multi-Tenant-Modus ausgeführt wird.

Ich hatte Berechtigungsprobleme bei solchen Wordpress-Installationen, wenn Sie das gesamte Wordpress vom Host zum Container mit einem Volume teilen.

In meinem Stack habe ich ein Basis-Image, das ein Debian mit meinen grundlegenden Modifikationen ist und jedes andere Image wird aus diesem Image erstellt.

Im Basisbild habe ich diesen Teil:

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

www-data wird nicht von PHP- oder Nginx-Installationen erstellt. Es ist ein standardmäßig definierter Benutzer/eine Gruppe in Debian und möglicherweise anderen Distributionen. Einige PHP- und Nginx-Installationen schlagen vor, diesen Benutzer in ihren Konfigurationsdateien zu verwenden.

Wenn die UID/GID Ihres Host-Benutzers 500 ist (die meisten Standard-UID/GID des ersten Nicht-Root-Benutzers von Linux ist 500 oder 1000), dann ändert dieses Skript die UID/GID des www-data Benutzers von 33 auf 500 Wenn Sie alles vom Host freigeben, denkt Docker, dass diese Dateien und Ordner dem www-data Benutzer gehören!

Setzen Sie in Ihren PHP-FPM-Einstellungsdateien den Benutzer und die Gruppe ebenfalls auf www-data .

In Ihrem nginx Dockerfile müssen Sie dies auch einstellen:

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

Auf diese Weise kann der nginx Benutzer auf die Dateien zugreifen, die www-data (Sie können den Benutzernamen von nginx in den nginx-Konfigurationsdateien definieren).

Nach diesem Hack hat meine Wordpress-Installation KEINE Berechtigungsprobleme! Alle Dateien befinden sich auf dem Host + die Aktualisierung von Wordpress funktioniert einwandfrei!

@DJviolin Ich bin mir nicht sicher, ob ein Problem wie dieses der richtige Ort für ein Wordpress-Tutorial ist, und ich zögere, es hier zu erläutern. Für die unglücklichen Neulinge, die irgendwie darüber stolpern könnten:

  1. Was Sie gepostet haben, macht eine Menge Annahmen über die Installation - zB UID/GID-Werte, Benutzer- und Gruppennamen usw. Es ist nicht sonderlich auf Distributionen übertragbar.
  2. Noch wichtiger ist, dass es extrem gefährlich ist, weltweit beschreibbaren Zugriff (0777) auf Ihre gesamte Wordpress-Installation zu gewähren, und in der offiziellen WP-Dokumentation wird ausdrücklich davon abgeraten. Darüber hinaus haben Sie mit all dem, was vom Host gemountet ist, nur erlaubt, dass beliebige Uploads aus dem Internet in das Dateisystem _host_ geschrieben werden.

@jantman Entschuldigung, mein

Natürlich muss jeder seine Host-Benutzer- UID:GID herausfinden und die Konfiguration entsprechend ändern. Verbinden Sie sich außerdem mit einem bereits bestehenden oder neuen Benutzer in der Quest. Meins ist ein funktionierendes Beispiel für einen lebenden Stapel.

Bis Docker keine Lösung für dieses Problem gibt, bleiben die Annahmen bestehen.

Meine Lösung ist die gleiche wie bei @JonathonReinhart oder @pa-de-solminihac.

Sie können dies tun, indem Sie lokale Volumes erstellen, die gerade im Master https://github.com/docker/docker/pull/20262 gelandet sind

Schließe dies als behoben.

Hallo, ich musste auch einen Workaround in meinem Dockerfile machen:

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

und dann in start.sh

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

Da $USER_ID als Umgebungsparameter eingefügt werden kann, ist es möglich, dieses Docker-Image ohne Änderung zu verwenden.

Wie auch immer, ich denke, es sollte mehr eingebaute Funktionalität für diese Art von Sachen geben und frage mich, wie man die von @calavera vorgeschlagenen lokalen Volumes

@keywan-ghadami Ich habe auch über lokale Bände gerätselt. Das Problem ist, dass Sie zuerst das Dateisystem erstellen müssen (oder tmpfs verwenden). Es verwendet also nicht /var/lib/docker. Tatsächlich können Sie kein Unterverzeichnis von _beliebigen_ vorhandenen FS verwenden, da bind-Mounts die Option uid nicht unterstützen. Ich weiß nicht, wofür lokale Volumes da sind; Sie können das FS auch selbst erstellen und mounten und dann ein normales Host-Volume verwenden ( -v my-created-fs:container-mount-point ).

Ich bin ziemlich spät zu diesem Thread, aber wurde dieses Problem behoben? Es ist nicht 100% klar aus all den verschiedenen Problemen, auf die hier Bezug genommen wird. @brthor scheint die beste Lösung zu haben, was ich sehen kann, beinhaltet jedoch Befehlszeilenoptionen, die einfacher in die Dockerfile eingefügt und hinter den Kulissen ausgeführt werden könnten.

Für mich ist die Hartcodierung von UID und GID eine schlechte Idee für die Portabilität zwischen Umgebungen und ich sehe nicht die Notwendigkeit, jedes Mal, wenn ich einen Container starte oder ein Image erstelle, Befehlszeilenargumente hinzuzufügen, wenn dies eine einfache Option im Docker-Datei. Könnte es nicht eine einfache Option in der Dockerfile oder vielleicht über docker-compose.yml geben, wo Sie eine Art "Map-UId vom Host"-Option angeben können?

Es gibt vielleicht schon eine gute Lösung, aber ich kann dies nicht wirklich aus der Dokumentation oder diesem Thread herausfinden.

Danke @alvinchevolleaux Ich kann bestätigen, dass wir die Lösung, die ich oben im CI für https://github.com/dotnet/cli gepostet habe, seit Monaten erfolgreich verwenden.

Empfehlen Sie es weiter!

@brthor Ja, so habe ich es gemacht, ich habe export USER_ID=$(id -u) zu meinem .bash_profile hinzugefügt, damit es für meine verschiedenen Umgebungen automatisch funktioniert. Vielen Dank.

Wie oben beschrieben, fügen Sie beim Freigeben von Inhalten aus Ihrem Home-Ordner in einen Container ein Benutzerkonto mit derselben UID wie Ihres hinzu. Hier ist ein Trick, um damit fertig zu werden, wenn Ihre UID nicht 1000 ist. Ich gehe davon aus, dass jeder Benutzer sein eigenes Docker-Image aus der Dockerfile erstellt.

Ihr Dockerfile sollte Folgendes enthalten:

RUN useradd --uid 1000 -m vagrant
USER vagrant

Die Konstante 1000 wird mit einem _git filter_ für Ihre tatsächliche UID ersetzt. Führen Sie Folgendes auf Ihrem Host aus:

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

Fügen Sie schließlich eine .gitattributes Datei hinzu, um den Git-Filter anzuwenden:

Dockerfile filter=uidfix

Dies funktioniert, indem Sie 1000 durch Ihre tatsächliche UID ersetzen, wenn Sie das Dockerfile auschecken, indem Sie die Datei _smudging_. Git wird die Datei _säubern_ (und 1000 ), wenn Sie einen Commit ausführen. Alle im Container ausgeführten Befehle werden als vagrant Benutzer mit der richtigen UID ausgeführt.

Nahtlos sollte dieses Ticket erneut geöffnet werden, da alle hier bereitgestellten Lösungen nur Problemumgehungen sind
Ich habe eine gut dokumentierte und umfassendere Lösung in https://github.com/rocker-org/rocker/blob/master/rstudio/userconf.sh gefunden
Es verwendet Laufzeitargumente, die es ermöglichen, vorgefertigte Images zu verwenden, was mit dem Git-Filter nicht möglich ist

@calavera Ich verstehe deine Lösung nicht.

z.B

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

Wenn ich im Verzeichnis /tmp/test nachschaue, gibt es keine Dateien. Es sieht nicht so aus, als ob der Ordner /tmp/test überhaupt in den Container gemountet wird... Es wird vielmehr ein Container-Volume erstellt. Was ich nicht wirklich will.

Ich kann keine Dokumentation finden, die mir sagt, was gültige --opt-Optionen sind. Daher überlege ich wirklich, wie das funktionieren soll.

Bitte öffnen Sie dieses Problem erneut. Der neue lokale Treiber scheint das Problem des Mountens lokaler Hostverzeichnisse mit ausgewählten Benutzer-IDs überhaupt nicht zu lösen.

@calavera
Können Sie bitte kommentieren, wie wir das Problem lösen können, dass Dateien als Root mit lokalen Host-Volumes gelöscht werden? Ich habe gesehen, dass dieses Problem häufig auftritt, insbesondere wenn Docker für CI-Szenarien verwendet wird.

Wenn ich mir die verlinkte PR anschaue, sehe ich auf Anhieb nichts Offensichtliches, aber ich bin mir sicher, dass mir etwas fehlt 😄

Ich habe Variationen dieser Problemumgehung in meinen Containern verwendet, z. B. docbill/docker-force . Mir fällt jedoch ein, dass eine sauberere Lösung ein Behälter ist, der nur für die Kürbiswurzel zuständig ist ...

Die Verwendung von so etwas wie bindfs für local sollte helfen. Sie können es mit -o map=$(id -u)/root:@$(id -g)/ @root ausführen (vorausgesetzt, es gibt keinen Benutzernamensraum) und Sie sollten Dateien außerhalb des Containers als Ihre Dateien sehen, solange sie Eigentum von . sind darin verwurzeln.

@ktosiek Danke, das klingt nach Potenzial. Könnten Sie ein vollständiges Beispiel für eine docker run Befehls- oder Konsolensitzung posten?

Könnte jemand bitte ein Statusupdate zu diesem Problem posten: Wurde es als "wird nicht behoben" geschlossen oder wurde dies tatsächlich implementiert? Der Thread ist ziemlich lang, also verzeiht mir bitte, da ich die Auflösung nicht auf einen Blick sehen kann.

@quinncomendant siehe https://github.com/docker/docker/issues/7198#issuecomment -191990887
Melden Sie sich, wenn es nicht funktioniert.

Danke @LK4D4.

Zusammenfassend lässt sich sagen, dass das Problem mit einem Fix geschlossen wurde, der es ermöglicht, sich für den local Volume-Treiber zu entscheiden.

Soweit ich das beurteilen kann, gibt es keine Optionen zum Setzen von user:group eines _host-directory, das als Volume gemountet ist_ (bitte korrigieren Sie mich, wenn diese Option existiert - ich bin hierher gekommen, um es zu lernen).

@quinncomendant richtig; Beim Bindemounten eines Host-Verzeichnisses soll der Container die Dateien verwenden, die vorhanden sind, einschließlich der Berechtigungen. Wenn Sie diese Berechtigungen ändern möchten, müssen Sie dies auf dem Host tun, bevor Sie sie bind-mounten

@quinncomendant Oder einfacher ausgedrückt, dies wird nicht behoben .... Da die
Die bereitgestellte Lösung tut nicht wirklich etwas, um das Problem zu beheben
gemeldet, und es ist auch nicht geplant, dieses Problem zu lösen.

Am 6. Juli 2016 um 17:20 Uhr, Sebastiaan van Stijn [email protected]
schrieb:

@quinncomendant https://github.com/quinncomendant richtig; Wenn
Binden Sie ein Host-Verzeichnis ein, in dem der Container die Dateien verwenden soll, die
sind vorhanden, was die Berechtigungen einschließt. Wenn Sie diese ändern möchten
Berechtigungen müssen Sie dies auf dem Host tun, bevor Sie sie bind-mounten


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/docker/docker/issues/7198#issuecomment -230909967 oder stumm
der Faden
https://github.com/notifications/unsubscribe/ADBcWLihVjI1FoSMLKu7DyhwFOpGX0KKks5qTBwMgaJpZM4CQMjR
.

Dies scheint ein WON'T FIX Problem zu sein. Es scheint immer so, als würden die _Entwicklungs-Aspekte der Containerisierung weiterhin übersehen und erfordern immer noch, dass wir Hacks schreiben.

Ich bin speziell auf dieses Problem gestoßen, weil die von mir unterstützten Entwickler Befehle zum Generieren von Projektdateien aus einem Container und aus dem Host-gemounteten Volume ausführen (die Installation dieser Tools auf dem Host verfehlt den Zweck der Verwendung eines Containers vollständig, oder?).

Sie möchten diese Dateien schnell iterieren, aber wie andere in diesem Thread darauf hingewiesen haben, werden sie als die uid/gid ausgeschrieben, unter der der Container läuft, was erfordert, dass sie auf dem Host korrekt chowned werden, um weiter manipuliert zu werden (von einem IDE zum Beispiel).

In solchen Fällen muss es wirklich eine _dockerspezifische_ Möglichkeit geben, eine temporäre UID/GID einzufügen.

@boj Dies ist genau das Szenario, auf das ich bei der Entwicklung von Scuba gestoßen bin. Meine aktuelle Lösung erstellt beim Start einen Benutzer im Container mit derselben uid/gid wie der Hostbenutzer. Es ist nicht die einfachste Lösung, aber es funktioniert gut.

@JonathonReinhart Danke, du hast mich ein wenig inspiriert.

Am Ende habe ich einen Skript-Wrapper geschrieben, der wie folgt vom Host aufgerufen wird (in diesem Fall wird Django verwendet):

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

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

@boj Das potenzielle Problem bei dieser Lösung ( -u $(id -u):$(id -g) ) besteht darin, dass es keinen Eintrag in /etc/passwd oder /etc/group für diese uid/gid im Container gibt: https://github .com/JonathonReinhart/scuba/issues/11

@ JonathonReinhart zur Kenntnis genommen . In diesem speziellen Fall kümmere ich mich nur um die Dateien, die an den Host des Entwicklers geschrieben werden und dass sie die gleichen Berechtigungen wie der Host-Benutzer haben.

Keine Sorge, was zur Laufzeit tatsächlich passiert, das war alles, was ich wirklich brauchte.

@jonathonReinhart

Wenn die Software im Container einen Eintrag in /etc/passwd oder /etc/group benötigt, machen Sie diese im Image weltbeschreibbar und fügen Sie dort beim Start die erforderlichen Einträge hinzu.

Die von @ JonathonReinhart erwähnte

Anscheinend wird dies bereits in runc unterstützt (https://github.com/opencontainers/runc/blob/8c9db3a7a5145f6b26c8051af319eee6f72c9ca8/libcontainer/configs/config.go#L19-24). In Docker gibt es die userns-remap Konfiguration für den Deamon, hier müssten wir sie grundsätzlich feinkörniger haben (Container-Level statt Deamon-Level), gibt es Interesse / Plan, dies zu unterstützen?

Dieses docker-compose.yml funktioniert nicht:

version: '2'

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

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

Kann mir jemand sagen warum? Ich folge den offiziellen Richtlinien: https://docs.docker.com/engine/reference/commandline/volume_create/#/driver -specific-options

Ist es möglich, benannte Volumes vom Host anzuhängen? Mit driver_opts Sie uid (und vielleicht gid ?).

+1

+1

@lazyuser @xiaods Bitte hör auf mit den +1. Es bewirkt nichts anderes, als all diese ---> Teilnehmer zu spammen.

@bamarni Ja, ich denke, das neue User-Namespace-Feature kann dies lösen, aber wie Sie sagten, müsste es pro Container implementiert werden. Das Endergebnis wäre: Ein Container läuft als das, was er für "root" hält, ist aber tatsächlich die UID/GID, die auf der docker run Befehlszeile übergeben wird. Dateien würden dann aus dem Container "herauskommen", der dem entsprechenden Benutzer gehört.

@lazyuser @xiaods @JonathonReinhart du solltest lieber auf den +1-Button unter der

Oder klicken Sie einfach rechts auf abonnieren, wenn Sie nur Benachrichtigungen wünschen...

@ JonathonReinhart : definitiv, ich habe das Dokument noch einmal durchgesehen, aber leider war es aufgrund einer Einschränkung eine bewusste Entscheidung, den Mapping-Daemon-weit statt pro Container zu verwenden:

Hinweis: Die Beschränkung auf eine einzelne Zuordnung pro Daemon gilt vorerst, da Docker Image-Layer aus seinem lokalen Cache für alle Container freigibt, die auf der Engine-Instanz ausgeführt werden. Da der Dateibesitz für alle Container mit demselben Layer-Inhalt gleich sein muss, wurde beschlossen, den Dateibesitz beim Docker-Pull den Benutzer- und Gruppenzuordnungen des Daemons zuzuordnen, damit die Ausführung von Containern nach dem Herunterladen des Inhalts nicht verzögert wird. Dieses Design behält die gleiche Leistung für Docker Pull, Docker Push und Containerstart bei, die Benutzer erwarten, wenn Benutzernamespaces deaktiviert sind.

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

Lieber @JonathonReinhart , @pa-de-solminihac und @nalipaz ,
Vielen Dank für Ihre Bemühungen, mich und andere zu erziehen, keine Kommentare zu hinterlassen, die nichts mit dem Problem zu tun haben, indem Sie genau das tun! Zu Ihrer Information, Github erlaubt es nicht, nach Themen zu suchen, die man abonniert hat, ohne sie zumindest zu kommentieren. Weitere Informationen finden Sie unter https://github.com/isaacs/github/issues/283. Ironischerweise ist das Problem von Github fast so alt wie das von Docker, und beide scheinen ähnlich priorisiert zu sein.

An alle, sorry fürs Spammen. Das erste Mal war es ein Workaround für den oben genannten Github-Bug, und diesmal konnte ich einfach nicht widerstehen, die Ironie der Situation zu erwähnen.

Ich habe dies mit inotifywait gelöst. Sie müssen inotify-tools installieren, um es in Ihrem Docker-Image auszuführen. Es ist möglich, es stattdessen auf Ihrem Hostsystem auszuführen, aber ich wollte eine tragbare Lösung.

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

Dies funktioniert, indem inotifywait angewiesen wird, nach neuen Dateien oder Verzeichnissen zu suchen, die im Verzeichnis /mount erstellt wurden. Wenn es einen bemerkt, ändert es den Besitz auf denselben Benutzer und dieselbe Gruppe wie der /mount-Ordner. Ich habe die Integer-Darstellung von beiden verwendet, falls der Hostbenutzer/die Hostgruppe nicht im Container vorhanden ist. Innerhalb des Containers spielt es keine Rolle, wem er gehört, da alles als Root ausgeführt wird. Außerhalb des Containers zeigt das Host-Dateisystem denselben Besitz an wie das Verzeichnis, das unter /mount gemountet wurde.

Ich habe es bewusst so entworfen, dass nur das Eigentum an neu erstellten Dateien und Verzeichnissen festgelegt wird, um das Eigentum an bereits vorhandenen Dateien und Verzeichnissen zu erhalten. Es ist sicherer, als jedes Mal, wenn das Dateisystem gemountet wird, all das mit einer chown -R-Anweisung wegzublasen. Wenn einheitliche Berechtigungen für Ihr Projekt funktionieren und Sie eine einfachere Lösung wünschen, die effizienter läuft, sehen Sie sich inotify-hookable an .

Achtung: Da pro Unterverzeichnis eine inotify Watch eingerichtet wird, ist es möglich, dass die maximale Anzahl an inotify Watches pro Benutzer erreicht wird. Das Standardmaximum ist 8192; es kann durch Schreiben in /proc/sys/fs/inotify/max_user_watches erhöht werden.

@codekitchen-ws Eine weitere Warnung: Eine Datei könnte nach der Erstellung und vor dem Besitzerwechsel verschoben werden. Abhängig von der Shell sollten Sie auch "$f" in Anführungszeichen setzen (um Worttrennung im Pfad zu verhindern).

+1

@briansrepo Das ist ein interessanter Ansatz. Wenn dies in einer Dockerfile RUN Anweisung enthalten ist, wird diese zur Build-Zeit ausgeführt. Wie konnte es den docker run Benutzer zur Ausführungszeit kennen?

@btiernay Danke! Es verwendet nicht die UID des Benutzers, der das Image gestartet hat. Es kopiert speziell den Host-Benutzer und die Host-Gruppe des Host-Verzeichnisses, das unter /mount eingehängt ist. Es sieht sich keine anderen Dateien oder Unterverzeichnisse an. Es liegt am Benutzer, sicherzustellen, dass die Berechtigungen auf etwas gesetzt sind, auf das er auf dem Hostsystem schreiben kann.

Beispiel: Angenommen, das Hostverzeichnis /var/www/html gehört brian:www-data. Sie starten ein Image, das das Hostsystemverzeichnis /var/www/html im Imageverzeichnis /mount einhängt. Dann erstellen Sie /mount/index.html aus dem Image heraus. Wenn Sie das Eigentum von /var/www/html/index.html auf dem Hostsystem überprüfen, wird es Eigentum von brian:www-data.

Auf diesem Beispiel aufbauend, nehmen wir an, Sie haben ein Hostverzeichnis /var/www/html/upload im Besitz von www-data:www-data. Denken Sie daran, dass das gemountete Hostverzeichnis /var/www/html immer noch im Besitz von brian:www-data ist. Gehen Sie nun in das Image und erstellen Sie /mount/upload/file.pdf. Wenn Sie die Hostdatei /var/www/html/upload/file.pdf überprüfen, gehört sie brian:www-data , nicht www-data:www-data , da das gemountete Hostverzeichnis /var/www/html im Besitz von Brian: www-data. Sinn ergeben?

TL;DR: Sie übergeben den Benutzer:Gruppe, den Sie verwenden möchten, indem Sie das gemountete Hostverzeichnis an Benutzer:Gruppe übergeben.

@briansrepo danke für die Erklärung. Das macht alles Sinn, aber ich verstehe immer noch nicht, wie dies in einem RUN funktionieren kann. Ich würde denken, dass dies im Hintergrund ausgeführt werden muss, wenn der Container ausgeführt wird (dh docker run ).

@btiernay Ich mag diese Idee auch.
@briansrepo zumindest deckt es ab, was aus den Containern passiert.
Der Build-Prozess kann immer noch mit etwas wie angegangen werden

RUN usermod -u 1000 www-data

Dies sind jedoch immer noch Workarounds.

In meinem LEMP-Stack habe ich diese Nginx-Vorkonfiguration in meinem Basis-Dockerfile:

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

Dies ist ein Hack, bei dem jede neu erstellte Datei aus einer Host-SSH-Sitzung, die die UID, die Gid von 500 und nginx erhält, irgendwann keinen Zugriff auf diese Dateien hat (da der Benutzer oder die Gruppe mit der ID 500 nicht im Container vorhanden war). Sie können überprüfen, welche uid-, gid-Nummer Sie für Ihren www-data Benutzer erstellen müssen, wenn Sie neue Dateien aus einer SSH-Sitzung in das freigegebene Volume auf dem Host kopieren und später docker exec in diesen Container und Betrachten Sie die Dateien die UID, gid.

Das Problem, das ich gefunden habe, wenn ich neue Dateien in den freigegebenen Ordner auf dem Hostcomputer kopiert habe (auf den Sie über eine SSH-Sitzung zugegriffen haben, wie in einer CoreOS-Instanz auf DigitalOcean), hat Nginx keinen Zugriff auf diese neu erstellten Dateien. Wenn Sie also absolute Kompatibilität mit Berechtigungen wünschen, müssen Sie Ihre Webserver-Dateien beim Erstellen der Container in den Docker-Container freigeben (zumindest war dies vor 1 Jahr der Fall, als ich auf diese UID-, Gid-Probleme mit freigegebenen Volumes stoße). .

ODER Sie können den ssh-Dienst auch im Docker-Container installieren, der die Dateien für den nginx-Container freigibt. Wenn Sie auf diese Weise Dateien kopieren/ändern, erhalten sie die richtige UID, gid. Dies widerspricht jedoch den Docker-Best Practices, dass Sie docker inspect anstelle von SSH-Sitzungen verwenden sollten, da "Docker keine VM" ist (das wäre eine zu einfache Lösung, oder?).

Meiner Meinung nach sollte ein Docker-Container wie ein Dienst oder eine ausführbare Datei fungieren und meine Webserver-Dateien nicht als Geisel nehmen, wenn ich nicht möchte. Datenbank ist (manchmal) etwas anderes, aber ich verstehe nicht, warum es nicht möglich sein sollte, dieselbe Container-Infrastruktur des Heiligen Grals zu erreichen, in der alle Ihre statischen Webserver-Datenbankdateien außerhalb von Containern leben (aber Container können es) Ändern Sie sie (wie Löschen, Erstellen, Ändern) und Sie können sie auch ohne Berechtigungsprobleme des Hosts ändern.

Mit docker volume create --opt Sie uid, gid definieren, aber es stimmt nicht mit docker-compose : https://github.com/docker/compose/issues/3715

Wir brauchen wirklich eine plattformübergreifende Go-to-Lösung (nicht gosu), um uid/gid zuzuordnen. Allein dieses Problem verursacht enorme Schäden in der Wahrnehmung von Docker durch Anfänger.

Wir haben eine Problemumgehung für dieses Problem erstellt, die die Benutzer-/Gruppen- und Dateiberechtigungen eines Docker-Containers, die zur Build-Zeit festgelegt wurden, auf die UID/GID ändert, mit der der Container zur Laufzeit gestartet wurde.

Die Projekt- und Installationsanweisungen finden Sie unter: https://github.com/boxboat/fixuid

Beispiel: Docker-Container wurde mit Benutzer/Gruppe dockeruser:dockergroup als UID/GID 1000:1000 . Der Host wird als UID/GID 1001:1002 . Image wird mit docker run -u 1001:1002 . fixuid wird:

  • ändere dockeruser UID in 1001
  • ändere dockergroup GID in 1002
  • ändere alle Dateiberechtigungen für das alte dockeruser:dockergroup auf 1001:1002
  • aktualisiere $HOME im Container auf dockeruser $HOME
  • jetzt stimmen Container und Host-UID/GID überein und Dateien, die im Container auf Host-Mounts erstellt wurden, stimmen überein

Es kann als ENTRYPOINT oder als Teil eines Startskripts ausgeführt werden. Es wird im Container als Binärdatei im Besitz von root mit dem setuid-Bit installiert und eskaliert die Berechtigungen, um die entsprechenden Änderungen vorzunehmen. Es sollte nur in Entwicklungscontainern verwendet werden.

Wenn sich dies als nützlich erweist, kann die Docker-Engine möglicherweise einen Teil oder die gesamte Logik über Flags in docker run

Gelöst mit docker volume .

@hashar wie? kannst du ein beispiel geben bitte

Gibt es also noch keine andere Lösung, als gosu und ein Einstiegsskript zu verwenden?!

Im Moment sieht es so aus, als ob es dafür 2 Optionen als Workaround gibt, bis das Docker-Team ein offizielles Update dazu macht.

Schade, dass das immer noch ein Thema ist. Theoretisch gibt es userns-remap, aber es ist nicht benutzerfreundlich.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen