Grundlegendes zum Besitz von Benutzerdateien in Docker: So vermeiden Sie, dass Berechtigungen für verknüpfte Volumes geändert werden

75

Betrachten Sie die folgende triviale Docker-Datei:

FROM debian:testing
RUN  adduser --disabled-password --gecos '' docker
RUN  adduser --disabled-password --gecos '' bob 

in einem Arbeitsverzeichnis mit nichts anderem. Erstellen Sie das Docker-Image:

docker build -t test .

Führen Sie dann ein Bash-Skript für den Container aus und verknüpfen Sie das Arbeitsverzeichnis mit einem neuen Unterverzeichnis im Basisverzeichnis von bob:

docker run --rm -it -v $(pwd):/home/bob/subdir test 

Wem gehört der Inhalt des subdirContainers? Führen Sie auf dem Container Folgendes aus:

cd /home/bob/subdir
ls -l

ad wir sehen:

-rw-rw-r-- 1 docker docker 120 Oct 22 03:47 Dockerfile

Heiliger Rauch! dockerbesitzt den Inhalt! Zurück auf dem Host-Computer außerhalb des Containers sehen wir, dass unser ursprünglicher Benutzer das noch besitzt Dockerfile. Versuchen wir, den Besitz des bobHome-Verzeichnisses zu beheben . Führen Sie auf dem Container Folgendes aus:

chown -R bob:bob /home/bob
ls -l 

und wir sehen:

-rw-rw-r-- 1 bob bob 120 Oct 22 03:47 Dockerfile

Aber warte! außerhalb des Containers rennen wir jetztls -l

-rw-rw-r-- 1 1001 1001 120 Oct 21 20:47 Dockerfile

Wir besitzen keine eigene Datei mehr. Schreckliche Nachrichten!


Wenn wir im obigen Beispiel nur einen Benutzer hinzugefügt hätten, wäre alles reibungsloser verlaufen. Aus irgendeinem Grund scheint Docker ein Home-Verzeichnis zu erstellen, das dem ersten Nicht-Root-Benutzer gehört, auf den es trifft (selbst wenn dieser Benutzer in einem früheren Image deklariert ist). Ebenso ist dieser erste Benutzer derjenige, der den gleichen Eigentumsrechten wie mein Privatbenutzer entspricht.

Frage 1 Ist das richtig? Kann mich jemand auf eine Dokumentation verweisen, ich vermute nur, basierend auf dem obigen Experiment.

Frage 2 : Vielleicht liegt dies nur daran, dass beide den gleichen numerischen Wert im Kernel haben. Wenn ich auf einem System testen würde, auf dem mein Heimbenutzer keine ID 1000hatte, würden die Berechtigungen in jedem Fall geändert.

Frage 3 : Die eigentliche Frage lautet natürlich: Was mache ich dagegen? Wenn er auf dem angegebenen Hostcomputer bobangemeldet ist bob, sollte er in der Lage sein, den Container als auszuführen bobund keine Dateiberechtigungen unter seinem Hostkonto zu ändern. Derzeit muss er den Container tatsächlich als Benutzer ausführen docker, um zu vermeiden, dass sein Konto geändert wird.

Ich höre dich fragen, warum ich überhaupt so eine seltsame Docker-Datei habe. . Ich frage mich auch manchmal. Ich schreibe einen Container für eine Webanwendung (RStudio-Server), der es verschiedenen Benutzern ermöglicht, sich anzumelden, wobei einfach die Benutzernamen und Anmeldeinformationen des Linux-Computers als gültige Benutzernamen verwendet werden. Dies bringt mir die vielleicht ungewöhnliche Motivation, mehrere Benutzer erstellen zu wollen. Ich kann dies umgehen, indem ich den Benutzer nur zur Laufzeit erstelle und alles in Ordnung ist. Ich verwende jedoch ein Basis-Image, das einen einzelnen dockerBenutzer hinzugefügt hat, damit es interaktiv verwendet werden kann, ohne als Root ausgeführt zu werden (gemäß Best Practice). Dies ruiniert alles, da dieser Benutzer der erste wirdBenutzer und besitzt am Ende alles, so dass Versuche, sich anzumelden, wenn andere Benutzer fehlschlagen (die App kann nicht gestartet werden, da ihr Schreibberechtigungen fehlen). Das chownerste Ausführen des Startskripts löst dieses Problem, jedoch auf Kosten verknüpfter Volumes, die Berechtigungen ändern (offensichtlich nur ein Problem, wenn Volumes verknüpft werden).

cboettig
quelle
1001 sollte in / etc / passwd auf Bob abgebildet werden. Wenn ja, hat der Container / etc / password nicht gemountet. Auf Kernelebene trägt der Prozesskontext nur die ID / Nummer, nicht den Namen.
Ergebnisseway
Siehe auch: unix.stackexchange.com/a/154092/43610
Ryne Everett

Antworten:

28

Ist das korrekt? Kann mich jemand auf eine Dokumentation verweisen, ich vermute nur, basierend auf dem obigen Experiment.

Vielleicht liegt das nur daran, dass beide den gleichen numerischen Wert im Kernel haben, und wenn ich auf einem System getestet habe, auf dem mein Heimbenutzer nicht die ID 1000 hatte, werden die Berechtigungen in jedem Fall geändert?

Lesen Sie info coreutils 'chown invocation', was Ihnen möglicherweise eine bessere Vorstellung davon gibt, wie Dateiberechtigungen / -eigentum funktionieren.

Grundsätzlich ist jedoch an jeder Datei auf Ihrem Computer eine Reihe von Bits angeheftet, die ihre Berechtigungen und ihren Besitz definieren. Wenn Sie chowneine Datei erstellen, setzen Sie nur diese Bits.

Wenn Sie chowneine Datei an einen bestimmten Benutzer / eine bestimmte Gruppe mit dem Benutzernamen oder Gruppennamen senden, chownsuchen Sie /etc/passwdnach dem Benutzernamen und /etc/groupnach der Gruppe, um zu versuchen, den Namen einer ID zuzuordnen. Wenn der Benutzername / Gruppenname in diesen Dateien nicht vorhanden ist, schlägt dies chownfehl.

root@dc3070f25a13:/test# touch test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 root root    0 Oct 22 18:15 test
root@dc3070f25a13:/test# chown test:test test
chown: invalid user: 'test:test'

Sie können jedoch chowneine Datei mit IDs nach Belieben erstellen (natürlich innerhalb einiger oberer positiver Ganzzahlgrenzen), unabhängig davon, ob auf Ihrem Computer ein Benutzer / eine Gruppe mit diesen IDs vorhanden ist oder nicht.

root@dc3070f25a13:/test# chown 5000:5000 test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 5000 5000    0 Oct 22 18:15 test

Die UID- und GID-Bits werden in der Datei selbst festgelegt. Wenn Sie diese Dateien in Ihrem Docker-Container bereitstellen, hat die Datei dieselbe Eigentümer- / Gruppen-UID wie auf dem Host, wird jedoch jetzt /etc/passwdim Container zugeordnet wird wahrscheinlich ein anderer Benutzer sein, es sei denn, er gehört root (UID 0).

Die eigentliche Frage ist natürlich: Was mache ich dagegen? Wenn bob auf dem angegebenen Host-Computer als bob angemeldet ist, sollte er in der Lage sein, den Container als bob auszuführen und keine Dateiberechtigungen unter seinem Host-Konto zu ändern. Derzeit muss er den Container tatsächlich als Benutzer-Docker ausführen, um zu vermeiden, dass sein Konto geändert wird.

Es scheint, als müssten Sie bei Ihrer aktuellen Einrichtung sicherstellen, dass Ihre UIDs> Benutzernamen /etc/passwdauf Ihrem Host mit Ihren UIDs> Benutzernamen in Ihren Containern übereinstimmen, /etc/passwdwenn Sie mit Ihrem bereitgestellten Benutzerverzeichnis als demselben Benutzer interagieren möchten Das ist auf dem Host angemeldet.

Sie können einen Benutzer mit einer bestimmten Benutzer-ID mit erstellen useradd -u xxxx. Buuuut, das scheint eine chaotische Lösung zu sein ...

Möglicherweise müssen Sie eine Lösung finden, die das Home-Verzeichnis eines Hostbenutzers nicht bereitstellt.

Chris McKinnel
quelle
Vielen Dank für die ausführliche Antwort, das klingt für mich sicherlich nach der richtigen Erklärung. Wie Sie jedoch sagen, keine besonders zufriedenstellende Lösung - etwas überraschend, dass Docker dies nicht expliziter umgeht. Es scheint immens einschränkend zu sein, nichts im Home-Verzeichnis des Host-Benutzers zu mounten.
Cboettig
hokstad.com/docker/patterns Ich habe dies gelesen und festgestellt, dass dieser Typ Ihr ​​Problem löst, wie ich es oben vorschlage. Vielleicht ist es doch nicht so schlimm?
Chris McKinnel
Danke für den Link. Es sieht so aus, als ob dieser Ansatz die UID fest verdrahtet (in seinem Fall ohnehin auf den Standardwert), sodass das Problem weiterhin auftritt (z. B. ist der Container nicht portierbar, ohne dass ein Benutzer die Docker-Datei vorkonfiguriert und erstellt). Wenn Docker Namen anstelle von UID-Werten unterstützt, wird dieses Problem tatsächlich behoben. Weitere Informationen von Docker-Entwicklern zum Posten in der Docker-Google-Gruppe: groups.google.com/forum/#!topic/docker-user/VFdFuZ4Ze_A
cboettig
1
Ja, ich denke, das ist eigentlich doch keine schlechte Strategie. Müssen Sie die UID zuerst mit einem userdelobwohl freigeben . fwiw hier ist die Lösung, die ich in meiner aktuellen Docker-
Datei
63

Zwei Optionen, die ich gefunden habe:

CHOWN alle Dinge (nach Ihrer Arbeit)

Ich habe es getan docker run -v `pwd`/shared:/shared image, und der Container hat Dateien erstellt pwd/shared, die dem Docker-Prozess gehören. Ist /sharedjedoch immer noch im Besitz von mir. Also mache ich es innerhalb des Docker-Prozesses

chown -R `stat -c "%u:%g" /shared` /shared

stat -c "%u:%g" /sharedkehrt 1000:1000in meinem Fall als uid:gidBenutzer zurück. Obwohl sich 1000im Docker-Conatainer kein Benutzer befindet, ist die ID vorhanden (und stat /sharedsagt nur "unbekannt", wenn Sie nach dem Benutzernamen fragen).

Wie auch immer, chowngehorsam überträgt das Eigentum an den Inhalten von /sharedauf 1000:1000(was, soweit es betrifft, nicht existiert, aber außerhalb des Containers bin ich es). Also besitze ich jetzt alle Dateien. Der Container kann immer noch Dinge ändern, wenn er möchte, weil es aus seiner Sicht so ist root.

Und alles ist gut mit der Welt.

docker run -u Alle erstellten Dateien haben automatisch den richtigen Eigentümer

Eine andere Möglichkeit, dies zu tun, ist das -uFlag beim Andockenlauf.

docker run -v `pwd`/shared:/shared -u `stat -c "%u:%g" /shared` ubuntu bash

Auf diese Weise befindet sich der Docker-Benutzer im Container youruid:yourgid.

Allerdings: Dies bedeutet, dass Sie Ihre Root-Berechtigung innerhalb des Containers ( apt-get installusw.) aufgeben müssen . Es sei denn, Sie erstellen einen Benutzer mit dieser neuen UID und fügen sie der rootGruppe hinzu.

Jared Forsyth
quelle
1
Ja, ich neige dazu, auch viel Gebrauch zu machen chown. Ich neige auch dazu, zu verwenden -u 1000. Ich denke nicht, dass die Verwendung %uso viel hilft, denn wenn Ihr Benutzer eine UID hat, die nicht auf dem Container vorhanden ist, wird es trotzdem nur einen Fehler geben.
Cboettig
Es ist eigentlich kein Fehler - beschwert sich nur bei stderr :)
Jared Forsyth
Beachten Sie, dass aufgrund wie Docker arbeitet, die UIDund GIDdurch die in Docker weitergegeben werden -uOption muss innerhalb des Docker Container existieren selbst (dh die IDs, nicht die damit verbundenen Namen).
code_dredd
4

In diesem Beitrag habe ich untersucht, wie ich den Besitz aller Dateien (im Besitz von root), die aus einem Docker-Container stammen, der als root ausgeführt wird , für meinen nicht privilegierten Benutzer auf dem Host wiederherstellen kann .

Ich brauchte den Prozess im Container, um als Root ausgeführt zu werden, daher kann ich -u beim Andocken nicht verwenden.

Ich bin nicht stolz auf das, was ich getan habe, aber am Ende meines Bash-Skripts habe ich Folgendes hinzugefügt:

docker run --rm -it \
    --entrypoint /bin/sh \
    -e HOST_UID=`id -u` \
    -v ${HOST_FOLDER_OWNED_BY_ROOT}:/tmp \
    alpine:latest \
    -c 'chown -R ${HOST_UID}:${HOST_UID} /tmp/'

Lassen Sie uns einige der Zeilen aufschlüsseln:

  • Führen Sie / bin / sh im Container aus:

--entrypoint / bin / sh

  • Übergeben Sie die UID des aktuellen Benutzers als Umgebungsvariable an den Container:

-e HOST_UID = `id -u`

  • Hängen Sie den Ordner, den Sie wieder besitzen möchten , unter diesen neuen Containern wieder in Ihren Benutzer ein ( gefüllt mit Dateien im Besitz von root, die vom vorherigen Container ausgegeben wurden, der als root ausgeführt wurde ) /tmp:

-v $ {HOST_FOLDER_OWNED_BY_ROOT}: / tmp

  • Führen Sie chownrekursiv mit der UID des Hostbenutzers über das Zielverzeichnis aus (im Container eingebunden in /tmp):

-c 'chown -R $ {HOST_UID}: $ {HOST_UID} / tmp /'

Auf diese Weise habe ich die Dateien an meinen aktuellen Benutzer zurückgegeben, ohne die Berechtigungen für root oder sudo "eskalieren" zu müssen.

Es ist schmutzig, aber es hat funktioniert. Hoffe ich habe geholfen.

BBerastegui
quelle