Moby: Fügen Sie die Möglichkeit hinzu, das Volume als ein anderer Benutzer als root zu mounten

Erstellt am 17. Okt. 2013  ·  157Kommentare  ·  Quelle: moby/moby

Anwendungsfall: Mounten Sie ein Volume vom Host zum Container zur Verwendung durch Apache als www-Benutzer.
Das Problem ist derzeit, dass alle Mounts als Root innerhalb des Containers gemountet werden.
Zum Beispiel dieser Befehl
docker run -v /tmp:/var/www ubuntu stat -c "%U %G" /var/www
gibt "root root" aus

Ich muss es als Benutzer www innerhalb des Containers mounten.

areapi arekernel arevolumes exexpert kinenhancement

Hilfreichster Kommentar

Kann ich nein sagen - Benutzer zwingen, ein Hilfsskript hinzuzufügen, das dies tut

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

(danke @bfirsh für dein zB)

ist ziemlich schrecklich.

Das bedeutet, dass der Container als root gestartet werden muss, anstatt als beabsichtigter redis -Benutzer ausgeführt zu werden. (wie @aldanor anspielte)

und es bedeutet, dass ein Benutzer so etwas nicht tun kann:

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

Alle 157 Kommentare

Wenn Sie das Volume (auf der Hostseite) vor dem Bind-Mount chown verwenden, wird es funktionieren.
In diesem Fall könnten Sie Folgendes tun:

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

(Angenommen, 101:101 ist die UID:GID des Benutzers www-data in Ihrem Container.)

Eine andere Möglichkeit ist, den Bind-Mount durchzuführen, dann chown innerhalb des Containers.

@mingfang Wird Chown bei dir nicht funktionieren?

Es wäre nützlich, dafür eine Abkürzung zu haben. Ich schreibe oft run -Skripte, die nur die Berechtigungen für ein Volume festlegen:

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

Was ist, wenn Sie nicht chown die Rechte daran haben?

Würde ein Hilfsskript, das das Volume chown auslöst, dieses Problem lösen? Dieses Skript kann das ENTRYPOINT Ihres Dockerfiles sein.

Kann ich nein sagen - Benutzer zwingen, ein Hilfsskript hinzuzufügen, das dies tut

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

(danke @bfirsh für dein zB)

ist ziemlich schrecklich.

Das bedeutet, dass der Container als root gestartet werden muss, anstatt als beabsichtigter redis -Benutzer ausgeführt zu werden. (wie @aldanor anspielte)

und es bedeutet, dass ein Benutzer so etwas nicht tun kann:

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

Es gibt _eine_ Möglichkeit, es zum Laufen zu bringen, aber Sie müssen sich im Voraus in Ihrem Dockrfile vorbereiten.

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

(Ich habe dieses Beispiel nicht getestet, ich arbeite an einem Chromium-Container, der dann auf einem _separaten_ X11-Container anzeigt, dass .... )

Und natürlich funktioniert diese Methode nur für direkte neue Volumes, nicht für Bindungen
gemountet oder Volumes – von Volumes. ;)

Darüber hinaus haben mehrere Container, die volumes-from verwenden, unterschiedliche UID/GID für denselben Benutzer, was die Sache ebenfalls kompliziert.

@SvenDowideit @tianoon diese Methode funktioniert auch nicht. Vollständiges Beispiel:

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

Zwei Läufe, mit und ohne -v-Volume:

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$ 

Wir stoßen auf ein Problem, das dadurch gelöst werden würde (glaube ich). Wir haben eine NFS-Freigabe für die Home-Verzeichnisse unserer Entwickler. Entwickler möchten /home/dev/git/project in Docker mounten, können dies jedoch nicht, da wir Root Squash aktiviert haben.

Dies verbietet root den Zugriff auf /home/dev/git/project . Wenn ich also versuche, Docker-Mounting /home/dev/git/project auszuführen, erhalte ich einen lstat permission denied -Fehler.

@frankamp Dies liegt daran, dass Docker derzeit bevorzugt, Host-Dinge nicht zu ändern, die nicht unter Dockers eigener Kontrolle liegen.

Ihre "VOLUME"-Definition wird von Ihrem -v pwd`:/var/lib/reds` überschrieben.
Aber in Ihrem 2. Durchlauf verwendet es ein Docker-gesteuertes Volume, das in /var/lib/docker erstellt wird. Wenn der Container startet, kopiert Docker die Daten aus dem Image in das Volume und chown das Volume mit der uid:gid des Verzeichnisses, für das das Volume angegeben wurde.

Ich bin mir nicht sicher, ob hier viel getan werden kann, und leider unterstützen Bind-Mounts (soweit ich das beurteilen kann) das Mounten als eine andere UID/GID nicht.

Meine Lösung dafür war, das zu tun, was SvenDowideit oben getan hat (neuen Benutzer erstellen und vorne in Dockerfile chown), aber dann, anstatt das Host-Volume zu mounten, einen Nur-Daten-Container zu verwenden und das Host-Volume zu kopieren, das ich mounten wollte Container mit tar cf - . | docker run -i --volumes-from app_data app tar xvf - -C /data . Dies wird etwas einfacher, sobald https://github.com/docker/docker/pull/13171 zusammengeführt ist (und docker cp funktioniert in beide Richtungen), aber vielleicht könnte es eine Alternative zu -v host_dir:container_dir werden -vc host_dir:container_dir , (vc für volume-copy), wobei der Inhalt von host_dir in den Datencontainer kopiert würde. Obwohl ich nicht sagen kann, dass ich verstehe, warum/wie die kopierten Dateien die Berechtigungen des Containerbenutzers erben, ist dies die einzige vernünftige Lösung, die ich gefunden habe, die die Portabilität nicht zerstört.

Was ist mit acl?

Gibt es eine Lösung oder Problemumgehung? Ich habe das gleiche Problem mit OpenShift, der bereitgestellte Ordner gehört root:root und vorgefertigte Images funktionieren nicht.

Ich suche auch nach einem Workaround. Wenn alle gemounteten Volumes im Besitz von root sind, ist es unmöglich, Ihre Docker-Container mit einem anderen Benutzer als root auszuführen.

Nun, Sie können s6-overlay ausprobieren. Es enthält Funktionen, die speziell darauf ausgerichtet sind, diese Art von Problemen zu umgehen.

@dreamcat4 : Danke für den Hinweis. Das Festlegen von Besitz und Berechtigungen scheint eine interessante Problemumgehung zu sein, aber müsste ich meinen Docker-Container nicht als Root ausführen, damit das funktioniert?

@brikis98 Ja das stimmt. Allerdings hat s6-overlay noch ein weiteres Feature, mit dem Sie die Berechtigungen beim Start Ihrer Server / Daemons wieder zurücksetzen können.

@dreamcat4 Ah, verstanden, danke.

Ich habe die gleiche uid/gid innerhalb und außerhalb eines Containers und das bekomme ich:

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 könntest du bitte ein separates Thema eröffnen?

kein Problem, aber ist das hier nicht relevant?

@dunklermatter dies ist eine Feature-Anfrage, kein Fehlerbericht, das Mischen Ihres Falls mit anderen Fällen macht es schwierig, der Diskussion zu folgen, außerdem hängt Ihr Problem möglicherweise nicht direkt damit zusammen

@thaJeztah Nun , wie @frankamp und andere es getan haben, habe ich einfach demonstriert, was nach dem Ausführen von chmod usw. in der Dockerfile passiert. Ich werde es als Fehlerbericht einreichen, aber es ist für diese Diskussion relevant.

Ähnlich wie @ebuchman vorgeschlagen hat, könnten Sie, ohne ein Host-Volume zu kopieren, zuerst einen Nur-Daten-Container erstellen, der a
chown 1000:1000 /volume-mount als root, wenn es gestartet wurde.
ZB in docker compose v2 Syntax

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"

Auf diese Weise kann Ihr Container als Nicht-Root-Benutzer ausgeführt werden. Der Nur-Daten-Container wird nur einmal ausgeführt.
Angenommen, Sie kennen die uid und gid, die my-beautiful-service im Voraus verwendet. Normalerweise sind es 1000.1000.

Da Sie (in 1.11) Mount-Optionen für ein Volume angeben können, das in Ihrem docker volume create verwendet werden soll, würde ich sagen, dass dies ziemlich nahe daran zu sein scheint, bereit zum Schließen zu sein.

Sie können uid/gid nicht einfach direkt angeben, da dies nicht mit Bind-Mounts unterstützt wird, aber viele Dateisysteme, die Sie mit den neuen Mount-Optionen verwenden können, können mit uid/gid-Optionen arbeiten.

Ich denke, das Problem besteht immer noch in Fällen, in denen Sie ein CIFS-Laufwerk in Ihrem Container bereitstellen möchten, aber vielleicht sollte das ein anderes Ticket sein?

@michaeljs1990 Sie können dies tun, nur nicht pro Container (es sei denn, Sie erstellen separate Volumes für jede gewünschte uid/gid-Kombination).

@cpuguy83 , könnten Sie bitte klarstellen, wie man docker volume create verwenden muss, um dieses Problem zu vermeiden?

Ich bin gerade heute mit Docker 1.11 auf dieses Problem gestoßen und musste einige schmerzhafte Neuausrichtungen vornehmen, um das Docker-Image davon zu überzeugen, dass ich in Dateien auf einem bereitgestellten Laufwerk schreiben kann. Es wäre wirklich schön, wenn ich das nie wieder tun müsste, geschweige denn versuchen würde, es jemand anderem zu erklären.

Ich bin mir nicht sicher, ob Sie das fragen, aber ...

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

Erstellen Sie das obige Image mit dem Namen "test".

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

Sowohl /hello als auch /hello/world im obigen Beispiel würden 1000:1000 gehören

Ich verstehe. Also habe ich etwas Ähnliches gemacht, aber ein bisschen anders, weshalb es sich vielleicht lohnt, es zu teilen. Im Grunde habe ich der Docker-Datei einen Benutzer hinzugefügt, der meine UID, GID, meinen Benutzernamen und meine Gruppe für den Benutzer außerhalb des Containers geteilt hat. Alle <...> sind Dinge, die durch relevante Werte ersetzt werden.

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

Danach kann entweder mit USER oder zu einem späteren Zeitpunkt mit su umgeschaltet werden (zB Entrypoint-Skript oder bei Verwendung einer Shell). Dadurch konnte ich auf das bereitgestellte Volume schreiben, da ich derselbe Benutzer war, der erstellt hat. Man könnte zusätzlich chown innerhalb des Containers verwenden, um sicherzustellen, dass man Berechtigungen für relevante Dinge hat. Auch die Installation sudo ist im Allgemeinen ein kluger Schachzug, wenn Sie dies tun.

Obwohl es das Problem löst, weiß ich nicht, ob ich es liebe, da dies für jeden Benutzer getan werden müsste. Außerdem habe ich Sachen hartcodiert (igitt!), aber vielleicht könnten Vorlagen verwendet werden, um das ein bisschen reibungsloser zu machen. Ich frage mich, ob dieses Shim irgendwie in docker run absorbiert werden könnte. Wenn es eine bessere Möglichkeit gibt, dies bereits zu tun, wäre ich sehr daran interessiert zu wissen, was es ist.

Es gibt eine Option zum Zuordnen von Host-Benutzer-UIDs/GIDs zu Container-Benutzer-UIDs/GIDs mit --userns-remap . Ich persönlich habe es nicht ausprobiert. Siehe eine gute Diskussion zu diesem Thema http://stackoverflow.com/questions/35291520/docker-and-userns-remap-how-to-manage-volume-permissions-to-share-data-betwee .

@cpuguy83 :

Sie können uid/gid nicht einfach direkt angeben, da dies nicht mit Bind-Mounts unterstützt wird, aber viele Dateisysteme, die Sie mit den neuen Mount-Optionen verwenden können, können mit uid/gid-Optionen arbeiten.

An welche Dateisysteme denken Sie, die uid/gid-Argumente akzeptieren können? Ich weiß, dass FAT das kann, aber das fühlt sich genauso abgehackt an wie alles andere, was in diesem Thread vorgeschlagen wird.

Docker hat meiner Meinung nach zwei Möglichkeiten:

  1. Offizielle Unterstützung für das Mounten von Volumes als bestimmter Benutzer/Gruppe (unter Verwendung des im Container definierten Benutzer-/Gruppennamens, ohne dass der Host dieses Wissen über die Interna des Containers haben muss).
  2. Oder ... entfernen Sie die Direktive USER (und die zugehörigen Laufzeit-Flags).

Die Möglichkeit, als Nicht-Root-Benutzer ausgeführt zu werden, während nur Volumes eingebunden werden können, die Root gehören, ist eine Fehlfunktion. Die gemeinsame Nutzung von uid/gid zwischen Host und Container ist ein weiterer Fehler.

@mehaase- Volumes übernehmen das Eigentum an allem, was sich bereits im Pfad im Container befindet. Wenn der Speicherort im Container Root gehört, erhält das Volume Root. Wenn der Speicherort im Container jemand anderem gehört, erhält das Volume diesen.

Eine Art Workaround dafür wäre toll. Sofern der Container dies nicht ausdrücklich erwartet, ist es _sehr_ schwierig, Volumes zu Standardcontainern wie Elasticsearch, Redis, CouchDB und vielen anderen hinzuzufügen, ohne ein benutzerdefiniertes Dockerfile zu schreiben, das die Berechtigungen festlegt. Dies macht den Befehl docker run -v oder die Direktive volume: in docker-compose meist nutzlos.

@chrisfosterelli warum nutzlos? Ich denke nicht, dass es ungewöhnlich ist, den Besitz von Dateien/Verzeichnissen festzulegen, die Sie voraussichtlich verwenden werden.

@ cpuguy83 Weil es anscheinend nicht möglich ist, den Besitz festzulegen, ohne eine benutzerdefinierte Dockerfile zu verwenden, die Berechtigungen und Volumes festlegt, weshalb sie für die Definition von Volumes nicht nützlich sind. Ich binde keine Container an mein Host-Dateisystem, falls dies relevant ist.

@chrisfosterelli Aber für alle diese Standard-Dockerfiles sollten die Berechtigungen bereits festgelegt sein.

Ich denke, was @chrisfosterelli zu sagen versucht, @cpuguy83 , (und bitte korrigieren Sie mich, wenn ich falsch liege, @chrisfosterelli) ist, dass klar geworden ist, dass diese Variablen (UID, GID usw.) dynamisch sind und auf festgelegt werden müssen Laufzeit (insbesondere in Bezug auf Dateien, die intern und von gemounteten Volumes gehören), aber uns fehlt derzeit eine Möglichkeit, dies zu tun. Bisher scheint die Antwort zu sein, dass sie nicht laufzeitabhängig sein sollten, aber das ignoriert das grundlegende Usability-Problem, das durch einen solchen Vorschlag aufgeworfen wird. Nochmals, wenn ich irgendetwas falsch verstehe, können Sie mich gerne korrigieren.

@jakirkham Ich muss nicht verstehen, was das Usability-Problem ist.
Die Dateien befinden sich im Image, sie sollten den Besitz und die Berechtigungen haben, die für die Ausführung der Anwendung erforderlich sind. Mit der Lautstärke an sich hat das nichts zu tun. Die Lautstärke nimmt nur das an, was im Bild eingestellt wurde.

@cpuguy83 Ich habe ein bisschen mehr gegraben und es darauf isoliert: Angenommen, ich habe einen Elasticsearch-Container, der beim Start ein Verzeichnis /data erstellt (wenn keine Daten vorhanden sind), und dann docker run -v /data elasticsearch verwenden . Das Verzeichnis /data wird Eigentum von root:root und der Daemon, der als elasticsearch innerhalb des Containers ausgeführt wird, kann nun nicht mehr gestartet werden, da er nicht in /data schreiben kann.

Es wäre ideal, wenn ich dieses Volume so einstellen könnte, dass es Elasticsearch gehört, ohne dass eine benutzerdefinierte Dockerdatei erforderlich ist ... obwohl Sie wahrscheinlich argumentieren könnten, dass diese Art von Problem im Upstream-Image behoben werden sollte.

@chrisfosterelli In den Kernel-Mailinglisten wird darüber geredet, dass ein Overlay wie ein Treiber den Besitzer wechseln kann, aber ohne so etwas können wir nicht viel tun. Ich bin neugierig, können Sie einfach alle Dateien in Ihrer Volume-Welt lesen und schreiben und umasks entsprechend einstellen, damit neue Dateien auch vorhanden sind? (Habe ich noch nicht probiert).

@justincormack Ich glaube schon, aber ich denke, das funktioniert nicht, wenn ich erwarte, dass der Container die Daten im Volume erstellt (und nicht der Host). Ich verstehe, dass dies ein seltsames Problem ist, daher behebe ich es derzeit, indem ich es in der Upstream-Dockerdatei selbst im Verzeichnis mkdir -p && chmod behebe.

@chrisfosterelli , deshalb habe ich gesagt, setze die umask, wenn deine umask 000 (im Container) ist, werden alle neuen Dateien mit 666 oder 777 Berechtigungen erstellt, und wenn die Einhängepunkt ist zu Beginn 777 , das sollte in Ordnung sein? Wenn die Berechtigungen immer World Read und Write sind, sollten UID und GID keine Rolle spielen?

@justincormack Ja, das klingt richtig ... wie kann ich das tun, während ich einen Docker-Container mit einem nicht vom Host bereitgestellten Volume erstelle?

@chrisfosterelli hmm, das ist eine gute Frage. Es sieht so aus, als ob die Berechtigungen für ein neues Volume die Standard-Umask sind, also könnten Sie versuchen, den Docker-Daemon mit einer 000 -Umask auszuführen und sehen, ob das Volume dann weltweit beschreibbar ist. Vielleicht sollten wir einige Berechtigungsoptionen für docker volume create haben.

(Sie könnten es mit einem Root-Container reparieren, der chmod gemacht und auch beendet hat, aber das ist hässlich)

Auf erstellen ist nicht gut. Das Problem ist, wenn der Container den Pfad nicht hat, wird der Pfad mit root erstellt. Dies könnte wohl so erfolgen, wie der übergebene Benutzer ist.

@ cpuguy83 Ich denke, es wäre sinnvoller, es zu erstellen, wenn der Benutzer mit -u übergeben wird, da dies wahrscheinlich der Benutzer wäre, der versucht, das Volume sowieso aus dem Container heraus zu schreiben, oder?

Ich konnte mit den folgenden Schritten als Benutzer meiner Wahl mounten:

  • Erstellen Sie den Benutzer in Docker mit derselben UID/GID wie der Benutzer, dem die Dateien auf dem Host gehören.
  • Erstellen Sie die Einhängepunkte im Voraus und chown sie dem Zielbenutzer im Container

Zitat @chrisfosterelli :

Ich habe ein bisschen mehr gegraben und es darauf isoliert: Sagen wir, ich habe einen Elasticsearch-Container, der beim Start ein Verzeichnis /data erstellt (wenn keine Daten vorhanden sind), dann verwende docker run -v /data elasticsearch. Das Verzeichnis /data wird root:root und der Daemon, der als Elasticsearch im Container ausgeführt wird, kann jetzt nicht gestartet werden, da er nicht in /data schreiben kann.

Das ist ein tolles Beispiel! Ich habe ein ähnliches Beispiel mit dem Solr-Bild. Solr benötigt einen oder mehrere "Kerne", von denen jeder eine Sammlung zusammengehöriger Konfigurationsdateien und Indexfragmente ist. Jeder Kern wird in einem Verzeichnis mit einem benutzerdefinierten Namen abgelegt. Wenn ich zum Beispiel einen Kern namens products erstellen möchte, wäre der Pfad /opt/solr/server/solr/products . Der Name des Kerns wird von mir gewählt, daher kann der Solr-Image-Betreuer dieses Verzeichnis nicht im Image vorab erstellen.

Ich möchte, dass meine Indexdaten gespeichert werden, damit ich mein Image auf ein neueres Solr aktualisieren kann, ohne alle meine Dokumente neu indizieren zu müssen, aber wenn ich ein Volume auf /opt/solr/server/solr/products , dann gehört es root und Solr (läuft als solr ) kann eigentlich nichts darauf schreiben. Das übergeordnete Verzeichnis /opt/solr/server/solr enthält andere Dateien, daher kann ich auch dort kein Volume mounten. (Im neuesten Docker-Jargon glaube ich, dass meine Volumes "benannte Volumes" genannt werden, dh Volumes, die nicht an einem bestimmten Pfad auf dem Host gemountet sind, aber vollständig von Docker für mich verwaltet werden.)

Ich habe darüber mit dem Solr-Image-Betreuer gesprochen und es gibt einige Problemumgehungen (und er hat einige Änderungen am Image vorgenommen, um zu helfen), aber es ist alles ziemlich hackig und erfordert von Fall zu Fall Änderungen am Upstream-Image. Die in diesem Thread besprochene Funktion würde _alle Images_ erweiterbarer machen, ohne dass eine neue Docker-Datei erstellt werden müsste.

@ctindel vielleicht ... wenn das Verzeichnis noch nicht existiert.

@ cpuguy83 Das stimmt, ich stimme zu. Das war definitiv mein Anwendungsfall. Es scheint keinen Sinn zu machen, das Verzeichnis als root zu erstellen, wenn es nicht existiert, wenn eine Benutzer-ID explizit zum Ausführen des Containers angegeben wurde.

@ cpuguy83 es funktioniert nur für benannte Volumes.

@kamechen Was funktioniert einfach?

@cpuguy83 Wenn Sie ein benanntes Volume verwenden, werden die Dateien unter dem Benutzer bereitgestellt, den Sie benötigen

@eciuca Nun ... es kommt darauf an. Wenn das benannte Volume leer war oder die Daten im benannten Volume von demselben Benutzer erstellt wurden, den Sie zufällig benötigen.

Gab es jemals eine Lösung für das von @andrewmichaelsmith aufgeworfene Problem?

Wir stoßen auf ein Problem, das dadurch gelöst werden würde (glaube ich). Wir haben eine NFS-Freigabe für die Home-Verzeichnisse unserer Entwickler. Entwickler möchten /home/dev/git/project in Docker mounten, können dies jedoch nicht, da wir Root Squash aktiviert haben.

Dies verbietet root den Zugriff auf /home/dev/git/project. Wenn ich also versuche, Docker-Mounting /home/dev/git/project auszuführen, erhalte ich einen Fehler mit lstat-Berechtigung verweigert.

Ich denke, es ist möglich, dies mit bindfs zu umgehen.
Verwenden Sie -v ... von Docker, um das Volume an einem temporären Speicherort bereitzustellen, und dann bindfs, um es dort bereitzustellen, wo es als anderer Benutzer benötigt wird.

@piccaso , so wie ich @andrewmichaelsmith verstanden habe, besteht das Problem darin, dass der Bind-Mount auf der Hostseite aufgrund von Rootsquash fehlschlägt. Aber bindfs könnte eigentlich immer noch als Workaround verwendet werden, aber diesmal auf der Host-Seite. Zuerst mounten Sie auf dem Host die nfs-Freigabe per Bind-Mount an einem temporären Speicherort als Nicht-Root-Benutzer mit FUSE, und dann mounten Sie diesen temporären Ordner im Docker mit -v ... .

Beachten Sie, dass bindfs (zumindest mit FUSE) ziemlich viel CPU-Overhead hat.

Ja, bindfs ist sehr unerwünscht. Es ist sogar langsamer als die CoW-Dateisysteme.
Es wird einige Arbeit im Kernel geleistet, um UID/GID-Verschiebung beim Mounten zu ermöglichen, was hilfreich sein kann.

Es wird einige Arbeit im Kernel geleistet, um UID/GID-Verschiebung beim Mounten zu ermöglichen, was hilfreich sein kann.

Dies wird wahrscheinlich auch nur dazu beitragen, den Anwendungsfall anzusprechen, in dem ich uid/gid innerhalb des Containers neu zuordnen möchte. Der Mount selbst, wie er vom Docker-Daemon ausgeführt wird, würde weiterhin als root auf dem Host ausgeführt werden. Mein Verständnis ist, dass mit dem Kernel Bind-Mounts nur als Root erstellt werden können. Ich bin mir nicht sicher, ob es Arbeit gibt, dies zu ändern, damit Mounts von Nicht-Root-Benutzern ausgeführt werden können (ich weiß zu wenig darüber, wie Linux mit Mounts umgeht, um zu beurteilen, ob das überhaupt Sinn macht).

@NikolausDemmel Ich bezweifle, dass sich das ändern wird. Der Systemaufruf mount erfordert CAP_SYS_ADMIN, was nicht etwas ist, das einem Nicht-Root-Benutzer gegeben wird, oder sogar etwas, das wir dem Root-Benutzer eines Containers geben.

@ cpuguy83 Danke für die Klarstellung. Das bedeutet, dass das Mounten von Docker-Volumes in Hostordnern, die NFS-Mounts mit Root-Squash sind, in absehbarer Zeit nicht funktioniert (aufgrund von Einschränkungen des Mount-Systemaufrufs, wie Sie sagen), abgesehen von der Verwendung von Problemumgehungen wie FUSE mit bindfs .

Entschuldigung, das war etwas OT, da OP nach der Änderung von UID/GID im Container gefragt hat. Aber es ist irgendwie die andere Seite der Medaille und es war in der obigen Diskussion aufgekommen. Wollte nur diese Unterscheidung verdeutlichen.

Ich verwende Docker für Mac und habe ein Volume gemountet, aber ich kann anscheinend nicht die Berechtigungen für den Webdienst erhalten, um auf die Dateien zuzugreifen. Wie würde ich das beheben? Ich habe versucht, Perms zu ändern und die Gruppe auf Staff zu setzen, aber es scheint, dass Alpine keine Staff-Gruppe hat.

Tut mir leid, wenn dies nicht der beste Ort dafür ist, ich habe seit Tagen Probleme und könnte mir keinen besseren Ort vorstellen.

@NikolausDemmel : Wir versuchen, Docker für einige Bioinformatik-Arbeiten zu verwenden. Wir haben mehrere riesige Dateisysteme, die über NFS mit Root-Squash gemountet wurden. Wir lesen riesige Sequenzdaten (fastq) ein und schreiben dann eine etwas kleinere BAM-Datei mit den genomischen Lesevorgängen, die auf den Datenspeicher ausgerichtet sind. Derzeit können wir Docker verwenden, indem wir das benutzerdefinierte Image erstellen, um einen Benutzer im Container zu erstellen, und am Ende USER verwenden, damit es funktioniert, aber dies ist aus mehreren Gründen problematisch:

  1. Wenn wir das Docker-Image einer anderen Person verwenden möchten, müssen wir es mit einer benutzerdefinierten Docker-Datei neu erstellen
  2. Wir müssen entweder ein benutzerdefiniertes Docker-Image für jeden lokalen Benutzer erstellen, oder wir verwenden ein einzelnes „Dienst“-Konto und können nicht zwischen den Aktivitäten des Benutzers im FS unterscheiden.

Können die Bindfs oder userNS uns das umgehen lassen?

Ich glaube, ich stoße auf das gleiche Problem, mein Anwendungsfall ist:
Docker-Images enthalten unsere portablen Build-Tools für ein bestimmtes Projekt. Wir verwenden Volume-Mounting mit relativen Pfaden, entweder mit etwas wie docker run -v ./:/src/ image oder dem Äquivalent in einer Docker-Compose-Datei. Ein Build wird automatisch gestartet und neue Dateien werden in einem Unterordner des verknüpften Volumes generiert.
Manchmal verwenden wir gerne diese vom Host erstellten Dateien, aber die Tatsache, dass sie immer noch dem Benutzer in Docker gehören, und nicht dem Host-Benutzer, der Docker ausgeführt hat, macht die Dinge tendenziell schwierig.

Mache ich hier etwas besonders falsch?

@rlabrecque siehe meinen früheren Beitrag über den Abgleich der ID des Docker-Benutzers mit der des Hosts. Ich habe diesen Ansatz verwendet und er funktioniert wirklich gut für uns. Führen Sie im Grunde HOST_UID=$(id -u) und HOST_GID=$(id -g) aus und generieren Sie eine Docker-Datei, die $HOST_GID und $HOST_UID in den folgenden beiden Befehlen erweitert:

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

Verwenden Sie das generierte Dockerfile mit den ausgefüllten IDs, um Ihr Image zu erstellen.

@haridsv Ich habe etwas Ähnliches gemacht und es funktioniert hervorragend unter Linux. Aber das scheint bei mir unter Windows nicht zu funktionieren: Die Dateien im Mount gehören immer noch root.

Ich habe das 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 portable 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 Ganzzahldarstellung von beiden verwendet, falls der Hostbenutzer/die Hostgruppe nicht im Container vorhanden ist. Innerhalb des Containers ist es egal, wem er gehört, da alles als root läuft. Außerhalb des Containers zeigt das Host-Dateisystem denselben Besitz wie das Verzeichnis, das unter /mount gemountet wurde.

Ich habe es bewusst so entworfen, dass es nur die Eigentumsrechte an neu erstellten Dateien und Verzeichnissen festlegt, um die Eigentumsrechte an bereits vorhandenen Dateien und Verzeichnissen zu erhalten. Es ist sicherer, als all das jedes Mal, wenn das Dateisystem gemountet wird, 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-Überwachung eingerichtet wird, ist es möglich, dass die maximale Anzahl an Inotify-Überwachungen pro Benutzer erreicht wird. Das Standardmaximum ist 8192; Sie kann durch Schreiben in /proc/sys/fs/inotify/max_user_watches erhöht werden.

Wir haben ein hostseitiges Skript verwendet, um chown das Volume zu bengen, das gemountet wurde, wodurch das Image nicht neu erstellt werden muss:

#!/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

Was ist mit der Verwendung von Dateisystem-ACLs im Hostverzeichnis? Auf diese Weise können Sie das Dateisystem anweisen, bestimmte Berechtigungen auf neu erstellte Dateien im Verzeichnis anzuwenden. Wenn Sie die ACL auf Hostebene festlegen, geschieht dies auch, wenn Sie die Daten aus dem Container ändern.

@thaJeztah @justincormack @cpuguy83

@kamechen scheint Recht zu haben, dass die genannten Bände "einfach funktionieren". Bei den benannten Volumes "schlagen" die vorhandenen Berechtigungen nach hinten los und ändern die Volume-Berechtigungen, was ich persönlich für einen Fehler halte (#28041).

@thegecko , warum gehen Sie diesen Ansatz nicht weiter und erstellen keine Benutzer innerhalb eines Einstiegspunkts?

Hier ist mein Beispiel, es erkennt einen Besitzer des gemounteten Verzeichnisses, erstellt einen Benutzer mit derselben UID und führt den Befehl wie unter diesem Benutzer aus:

Dockerfile

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

entrypoint.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)\""

Wenn ich sudo docker build -t test . && sudo docker run --rm -v /tmp/docker-test/:/project test:latest starte, gibt es Folgendes aus:

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"

Hat sich jemand mit diesem Problem befasst? Wenn Sie sicherstellen, dass Ihre Volumes dieselbe gid und uid wie Ihre Container haben, wird es schwieriger, Ihre Container so zu verwalten, dass sie nicht root verwenden. Die Best Practices von Docker empfehlen, Dienste nach Möglichkeit nicht mit Root auszuführen, aber muss nicht die gid und uid auf dem Host sowie die Container eingerichtet werden, die die Benutzerfreundlichkeit beeinträchtigen, die Docker so beliebt gemacht hat?

@AndreasBackx Die Verwendung von Volumes funktioniert nur unter der Annahme, dass das Image Daten in dem Pfad enthält, in den Sie einsteigen.
Bei der Verwendung von Bindungen wird die UID/GID des Hostpfads verwendet.

Es gibt derzeit keine Möglichkeit (wie in keiner Kernel-Unterstützung), die UID/GID einer Datei/eines Verzeichnisses auf etwas anderes abzubilden oder zu ändern, ohne das Original zu ändern, es sei denn, es wird etwas wie FUSE verwendet, das schrecklich langsam ist.

Aber gehen wir einen Moment zurück.
Docker macht es hier nicht wirklich schwieriger.
UID/GID im Container ist die gleiche wie UID/GID auf dem Host. Auch wenn Benutzer-/Gruppennamen nicht übereinstimmen, kommt es hier auf UID/GID an.
Genau wie ohne Docker müssen Sie sich eine UID/GID einfallen lassen, die Sie für Ihre Dienste verwenden möchten, und sie außerhalb der Konvention verwenden.
Denken Sie daran, dass eine uid/gid nicht in /etc/passwd oder /etc/group existieren muss, damit der Dateibesitz darauf festgelegt wird.

@ cpuguy83 danke für die Erklärung.

Ich bin heute auf dieses Problem gestoßen, als ich eine node -Pipeline erstellte. Meine Host-Benutzer-UID ist 1000, und das node -Image erstellt einen benutzerdefinierten Benutzer mit dieser bestimmten UID . Es gibt sogar ein Problem damit

Ich würde den Knotenbenutzer verwenden und weitermachen, aber es fühlt sich ein bisschen schmutzig an. Ich teile wirklich, was Sie über @cpuguy83 über "Lass uns einen Moment zurücktreten" geschrieben haben, aber manchmal könnte es zu einem schwer zu lösenden Problem werden.

Ich habe gerade herausgefunden, dass die Option -o auf usermod doppelte IDS zulässt, scheint eine legitime Option zu sein.

RUN usermod -o -u 1000 <user>

Unsicher, warum dies nicht auf vernünftige Weise behoben wurde.

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

Einloggen um zu sehen:

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

Das Dockefile tut dies speziell

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

Es macht keinen Sinn, dass dieses Volume als root gemountet wird, wenn weder der Benutzer im Container ausgewählt ist, noch der Benutzer, der den Befehl ausführt, ausgewählt ist. Ich könnte verstehen, ob der RUN-Befehl als der Benutzer gemountet wurde, der den Befehl ausführt, oder als der Benutzer, dem das Verzeichnis gehört, oder sogar als der Benutzer, der in der Docker-Datei angegeben ist.

Keines davon ist root, daher scheint das Mounten als root ein Fehler zu sein.

Auch gerade überprüft, ein Volume erstellen und dann mounten, es funktioniert. Also immer noch ein Bug.

@disarticulate Wenn Sie möchten, dass der Hostpfad etwas anderes als root ist, sollten Sie den Hostpfad ändern.

Ich glaube nicht, dass dies schon einmal erwähnt wurde, aber dieser Fehler ist besonders ärgerlich, wenn Sie sich darauf verlassen, dass Docker das Host-Volume für Sie erstellt. Docker scheint das Host-Volume immer mit root zu erstellen, selbst wenn das Verzeichnis, über das Sie mounten, einen anderen Besitzer hat.

Es scheint, dass das Richtige hier darin besteht, das Volume mit Eigentumsberechtigungen zu erstellen, die zu USER des Images gehören.

@jalaziz was soll es tun, wenn der Benutzer des Containers nicht auf dem Host vorhanden ist? Einer der Hauptvorteile von Containern besteht darin, dass Sie ihre Abhängigkeiten (einschließlich Benutzer) nicht für den Host offenlegen müssen.

@taybin Ich würde erwarten, dass Docker nur den Ordner mit der uid: gid des Benutzers des Containers erstellt ODER wenn der Ordner im Container vorhanden ist, würde es den Hostordner mit derselben uid: gid und Maske erstellen.

HINWEIS: Ich erwarte keine Docker-Änderungsberechtigungen, wenn der Ordner bereits auf dem Host vorhanden ist.

@taybin Genau wie @frol beschrieben. Es sollte nur die uid:gid aus dem Container verwenden.

Dies offenbart jedoch mein allgemeines Problem mit dem aktuellen Ansatz. Ich muss die uid kennen, die der Container verwendet, um Schreibvorgänge zuzulassen und Berechtigungen für Hostverzeichnisse basierend auf dieser uid:gid festzulegen. Wenn ein Upstream-Autor jemals die UID ändert, werden die Berechtigungen ungültig. Es wirkt alles sehr zerbrechlich.

In meinem Fall hatte ich nicht unbedingt die explizite Kontrolle darüber, welches Docker-Image verwendet wurde (ich konnte eine Docker-Datei nicht einfach nach meinen Wünschen bearbeiten).

Also, ich habe das versucht:

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

Dadurch wird ein Ordner namens ./built-app erstellt. Der Eigentümer war jedoch immer noch root mit strengen Berechtigungen.

Mein Workaround war folgender:

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

Das hat immer noch root Besitzer, aber lockere Berechtigungen. Dann konnte mein Host-Betriebssystem (Ubuntu) ohne sudo-Berechtigungen auf ./built-app zugreifen.

@rms1000watt hast du den folgenden Befehl ausprobiert?

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

Das sollte funktionieren, da es UID und GID Ihres Hosts direkt für die Dateien selbst verwenden würde. Die Verwendung chmod -R 777 ist im Allgemeinen eine schlechte Praxis.

@saada Hoppla ! Guter Anruf. Ich versuche es mal.

Ich könnte meinen Ansatz erreichen, indem ich dies lese und verstehe, wie _UID und GID in Docker-Containern funktionieren_
https://medium.com/@mccode/understanding -how-uid-and-gid-work-in-docker-containers-c37a01d01cf

Grundsätzlich gibt es einen einzelnen Kernel und einen einzelnen, gemeinsam genutzten Pool von UIDs und GIDs, was bedeutet, dass der Stamm Ihres lokalen Computers derselbe ist wie der Stamm Ihres Containers, beide haben dieselbe UID


Ich habe einen Apache-Server und möchte meine Webapp-Dateien mit dem Apache-Container teilen, um sie auf dem Host zu ändern (Entwicklung, sie mit einem Texteditor ändern) und die Ergebnisse eines Prozesses anzeigen, der im Container ausgeführt wird. Manchmal schreibt dieser Prozess neue Dateien und wenn ich das Standardverhalten mit den Rechten nicht ändere, werden Dateien vom Root-Benutzer generiert und mein lokaler Benutzer kann sie nicht mehr ändern.

Was ich getan habe, war, ein benutzerdefiniertes Bild zu generieren, das dies in meiner Dockerdatei hinzufügt:

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

Um mein docker-compose.yml für jeden portierbar zu machen, werden vielleicht einige Parameter in den Build-Prozess eingefügt.

Hier ist ein Containermuster zum Zuweisen der Benutzer-ID/Gruppen-ID zur Laufzeit auf eine Weise, die leicht portierbar ist. https://github.com/Graham42/mapped-uid-docker

Der Weg, den ich befolgt habe:

1- Erstellen Sie das Verzeichnis auf dem Hostserver
2- Ändern Sie die Berechtigungen des Benutzers mit der Benutzer-ID und der Gruppen-ID = 1000
3- Führen Sie docker-compose up aus
Habe den Behälter überprüft und alles ist in Ordnung.

Hinweis: Ich habe den Root-Benutzer auf dem Hostserver verwendet und gehe davon aus, dass ich das Volume mounten könnte, wenn ich einen Nicht-Root-Benutzer mit UID = 1000 verwenden würde, ohne mir Gedanken über die Berechtigung machen zu müssen, aber ich habe es noch nicht getestet. Ist jemand ähnlich vorgegangen?

Typisches Problem:

  • docker swarm, also ist CAPP_ADD nicht verfügbar, bind-mount ist keine Lösung
  • Zwei Container mit zwei verschiedenen Images teilen sich dasselbe Volume, also unterschiedliche Benutzer-/Gruppendatenbanken auf beiden
  • zB muss man Zugriffsrechte haben www-data (dh Let's Encrypt Certificate Downloader)
  • der andere verwendet auch www-Daten (dh nginx)
  • aber ein dritter benötigt Zugriff vom Benutzer openldap (dh openldap server)
  • so einfach ist chmod auch keine lösung

Das heißt, ich habe einen Webserver, der SSL-Zertifikate für seine Domains von let's encrpt erhält, und einen OpenLDAP-Server für dieselbe Domain, auf dem ich die Zertifikate wiederverwenden möchte.

Es gibt andere Kombinationen, bei denen genau das gleiche Problem auftritt.

Irgendeine Idee, wie man das löst?

Wie würden Sie das ohne Docker lösen? Dies ist nicht Docker-spezifisch
Problem.

Am Freitag, 12. Januar 2018 um 10:24 Uhr, Marc Wäckerlin [email protected]
schrieb:

Typisches Problem:

  • docker swarm, also ist CAPP_ADD nicht verfügbar, bind-mount ist kein
    Lösung
  • zwei Container mit zwei verschiedenen Bildern teilen sich also dasselbe Volumen
    unterschiedliche Benutzer-/Gruppendatenbanken auf beiden
  • zB muss man Zugriffsrechte auf www-data haben (dh let's encrypt
    Zertifikat-Downloader)
  • der andere verwendet auch www-Daten (dh nginx)
  • aber ein drittes erfordert Zugriff vom Benutzer openldap (dh openldap
    Server)
  • so einfach ist chmod auch keine lösung

Das heißt, ich habe einen Webserver, der SSL-Zertifikate für seine Domains bekommt
von let's encrpt und einem OpenLDAP-Server für die gleiche Domain, wo ich will
um die Zertifikate wiederzuverwenden.

Es gibt andere Kombinationen, bei denen genau das gleiche Problem auftritt.

Irgendeine Idee, wie man das löst?


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/moby/moby/issues/2259#issuecomment-357267193 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AAwxZgyvdCwGGVkUqCxK9nDFw1zxSKjUks5tJ3kXgaJpZM4BGxv9
.

--

  • Brian Goff

Auch ohne Swarm konnte ich es im Docker lösen: bind-mount.

Es ist ein Docker-Swarm-spezifisches Problem, da es kein CAP_ADD gibt.

@mwaeckerlin Bind-Mounts können nicht verschiedenen Benutzer-IDs zugeordnet werden.
Aber auch mit Schwarm kann man Mount binden.... warum wird CAP_ADD benötigt?

Ohne CAP_ADD schlägt das Mounten im Docker fehl.

Aber durch das Schreiben meines Kommentars habe ich gerade eine mögliche Lösung erhalten, aber leider muss das Dockerfile in beiden Bildern geändert werden, sodass es nicht für Bibliotheken oder andere Bilder von Drittanbietern funktioniert:

  • Erstellen Sie eine Gruppe mit einer explizit angegebenen gemeinsamen Gruppen-ID in allen Dockerfiles
  • Rechte an die Gruppe vergeben

@mwaeckerlin Warum müssen Sie im Container montieren?

Weil ich mit der Docker-Option -v keinen Benutzer/Gruppe angeben kann.

Die oben angegebene Idee war: Bind-mount innerhalb des Containers, dann chown auf das Ziel sollte die Quelle nicht ändern.

@mwaeckerlin Wenn du es änderst, wird es überall geändert. Das ist der Kern des Problems in dieser Ausgabe.
Chowning/Chmoding einer an Bind gemounteten Datei/Verzeichnis ändert beide Stellen.

Es besteht auch keine Notwendigkeit, innerhalb des Containers montieren zu können, Sie können --mount type=bind,source=/foo,target=/bar

Ja, ich habe es gerade außerhalb von Docker getestet, also ist die obige Idee falsch.

Das Hauptproblem, das ich oft in Docker sehe, ist, dass die Benutzer und Gruppen in verschiedenen Bildern nicht identisch sind, selbst wenn derselbe Benutzername oder Gruppenname in beiden vorhanden ist, haben sie oft unterschiedliche IDs.

Hier würde zumindest in einigen Fällen so etwas helfen: --mount type=bind,source=/foo,target=/bar,user=me,group=mine

Irgendwelche Empfehlungen oder Best Practices zu diesem Thema: Shared Volume User von verschiedenen Benutzern in verschiedenen Images im Docker Swarm?

  1. Teilen Sie keine Volumes
  2. Synchronisieren Sie Ihre uid/gids
  3. Stellen Sie sicher, dass die Berechtigungen für alle Freigaben ausreichend sind
  4. Verwenden Sie Sicherungshalterungen auf dem Host, um für jeden Container an verschiedene UID/GID zu binden

Können Sie Punkt 4 näher erläutern?
Vielleicht ein praktisches Beispiel, wie man das macht?

Am Freitag, den 12. Januar 2018 um 17:27 Uhr schrieb Brian Goff, [email protected] :

>

  1. Teilen Sie keine Volumes
  2. Synchronisieren Sie Ihre uid/gids
  3. Stellen Sie sicher, dass die Berechtigungen für alle Freigaben ausreichend sind
  4. Verwenden Sie Sicherungshalterungen auf dem Host, um jeweils an unterschiedliche UIDs/GIDs zu binden
    Container


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/moby/moby/issues/2259#issuecomment-357282169 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AHSjvgjb0BFbJhZ1VWM-pLGfa7tRBvDNks5tJ4VPgaJpZM4BGxv9
.

Verwenden Sie etwas wie https://bindfs.org/ - es gibt sogar mindestens ein Docker-Volume-Plugin, das es bereits implementiert (https://github.com/lebokus/docker-volume-bindfs ist das erste Ergebnis, das ich über Google gefunden habe) .

Ich kann die Berechtigung nach dem Mounten des Volumes nicht ändern, bekommt das irgendjemand?

eine Problemumgehung:
Hinzufügen zu Dockerfile
RUN echo "if [ -e container_volume_path ]; then sudo chown user_name container_volume_path; fi" >> /home/user_name/.bashrc
Der Besitz von container_volume_path wird geändert, nachdem das Volume bereitgestellt wurde.

Die Möglichkeit, uid und gid zuzuordnen, scheint ein mysteriöses fehlendes Element bei der Handhabung von Docker-Volumes zu sein. Der Weg mit der geringsten Überraschung wäre, es einzuschließen, und die vorgeschlagenen Korrekturen sind umständlich und schwerer zu entdecken, während sie keinen Vorteil für bewährte Verfahren bieten:

Betreff:
1) Volumes nicht teilen

  • Gut, aber unwesentlich für die Diskussion über die Abbildung von uid/gid
    2) Synchronisieren Sie Ihre UID/GIDs
  • Das ist, was die Funktionalität tun soll, aber ohne einen Chown in einer Dockerfile zu erzwingen
    3) Stellen Sie sicher, dass die Berechtigungen für alle Freigaben ausreichend sind
  • Dies beruht wiederum auf dem in einer Dockerfile definierten Verhalten, wenn es sich um eine einfache Zuordnung handeln könnte
    4) Verwenden Sie Sicherungshalterungen auf dem Host, um verschiedene uid/gids für jeden Container zu binden
  • Guter Rat, das sieht auch nach Yak-Rasur aus.

@colbygk

wenn es sich um ein einfaches Mapping handeln könnte

Das ist das Problem, es ist nicht möglich, ein "einfaches Mapping" durchzuführen, da es auf der vfs-Ebene nicht unterstützt wird.
Einige Dateisysteme bieten die Möglichkeit, Eigentumsrechte abzubilden (z. B. bindfs oder nfs), aber die Implementierung im allgemeinen Fall ist derzeit nicht möglich.

Ich benötige freigegebene Volumes zB in folgender Situation:

Gemeinsame Zertifikate

  • Container 1 ist ein Reverse-Proxy, der let's encrypt für alle gehosteten Domänen verarbeitet
  • Container 2 ist ein LDAP-Server, der auch das Zertifikat seiner Domäne bereitstellen muss

Lösung: Der Image-Container 2 erbt vom gleichen Image wie Container 1, das gemeinsame Basis-Image erstellt eine gemeinsame Gruppe, dann haben beide Container den gleichen Gruppenzugriff

Dockerfile der gemeinsamen Basis :

RUN groupadd -g 500 ssl-cert

letsencrypt-config.sh im let's encrypt-Bild :

chgrp -R ssl-cert /etc/letsencrypt

Dockerfile von mwaeckerlin/reverse-proxy :

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

Dockerfile von mwaeckerlin/openldap :

RUN usermod -a -G ssl-cert openldap

Das ist es.

All dies veranschaulicht, wie Benutzerperms während des Einstiegspunkts oder während des Build-Prozesses geändert werden können, damit der gesamte Docker unter einem anderen Benutzer ausgeführt wird.

Aber vielleicht übersehe ich einen wichtigen Punkt, nachdem ich in den letzten 3 Tagen im Internet gesucht habe.
Keine der oben genannten oder anderweitig verlinkten Empfehlungen und (Workarounds) funktionieren in irgendeiner Weise.

Alle in einem Container gemounteten Volumes gehören immer root:root innerhalb des Containers. Unabhängig davon, ob ich den Besitzer im Voraus auf dem Host mit passender UID/GID ändere oder nicht.

Ich kann das Gefühl nicht loswerden, dass ich dumm bin, wenn ich versuche, etwas sehr Grundlegendes zu tun – aus meiner Sicht.

  • Windows 10 Pro 1803 (17134.112)
  • Docker für Windows 18.03.1-ce-win65 (17513)
  • Windows WSL mit Hyper-V und Ubuntu

Ich versuche, einen einfachen Apache2-Container zu starten, in dem der Dokumentenstamm auf dem Host gemountet ist, damit ich in der Lage bin, PHP-Quellcode zu entwickeln, während ich ihn sofort auf dem Docker-Container teste.

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

Innerhalb des Docker-Containers gehört das Verzeichnis _/var/www/html_ immer _ root:root_ , sodass meine PHP-App niemals in der Lage sein wird, Daten in diesem Ordner zu öffnen oder zu schreiben.
Es hat noch nichts funktioniert... :(

Für diejenigen, die nach einer einigermaßen eleganten Lösung suchen, sehen Sie sich an, was @elquimista hier vorgeschlagen hat . Ich habe dies getestet und funktioniert gut

Wir haben mit Glück https://github.com/boxboat/fixuid#specify -paths-and-behavior-across-devices verwendet. Darüber hinaus richtet es einen Benutzer innerhalb des Containers ein, der mit einem Benutzer auf dem Host übereinstimmt.

Hier ist eine Beispielkonfiguration aus dem Bild:

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

und laufen:

$ 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

Beachten Sie, dass dies auch ein Ärgernis ist, wenn Speichersysteme verwendet werden, die keine Unix-Berechtigungen und -Eigentumsrechte unterstützen. In diesem Fall muss der Speicher so gemountet werden, dass er die richtige UID für die Verwendung im Container erhält, da jeder Versuch, die Dateien zu chownen, einfach fehlschlägt. Wenn es eine Möglichkeit gäbe, Docker anzuweisen, die Dateien als Eigentum einer bestimmten UID darzustellen, unabhängig vom Eigentum außerhalb des Containers, würde dies die Dinge vereinfachen.

@tlhonmey

Wenn es eine Möglichkeit gäbe, Docker anzuweisen, die Dateien als Eigentum einer bestimmten UID darzustellen

Gibt es nicht, nicht ohne ein benutzerdefiniertes Dateisystem (z. B. wie bindfs).

@tlhonmey Ja, ich konnte das Problem von "Speichersystemen, die keine Unix-Berechtigungen unterstützen" mit einigen Symlinks umgehen.

Grundsätzlich würde ich beim Mounten von NTFS-Laufwerken Dinge in -v ./HostNtfsStuff:/data/ntfsMount ablegen und dann einen Symlink erstellen und das ln -s -T /data/ntfsMount /var/lib/myApp && chown -Rh myApp:myApp /var/lib/myApp/ chown

Sie können auch testen: su myApp -c 'echo foo > /var/lib/myApp/bar' && cat /data/ntfsMount/bar

Meine Verwendung war für Windows-Entwickler, um MySQL-Container auszuführen und auf gemounteten Volumes zu bestehen, aber es gilt für viele Apps.

Die Lösung besteht also darin, eine Reihe von uid:gid- Paaren manuell zu verwalten und zu hoffen, dass sie nicht auf dem Host oder einem Hilfsskript kollidieren, oder:

Es gibt _eine_ Möglichkeit, es zum Laufen zu bringen, aber Sie müssen sich im Voraus in Ihrem Dockrfile vorbereiten.

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

(Ich habe dieses Beispiel nicht getestet, ich arbeite an einem Chromium-Container, der dann auf einem _separaten_ X11-Container anzeigt, dass .... )

Ich habe die letzte Technik bis heute verwendet, als ich versuchte, das Containervolumen zu binden, und es brach. Anscheinend kannst du das nicht. Das Volume wird als Root erstellt und die darin enthaltene App kann nicht als Benutzer darauf schreiben. Die in der VOLUME -Dokumentation beschriebene automatische Bestückung scheint auch mit dem Bind-Mounting nicht zu funktionieren.

Ich habe dies beim Lesen von Dockerfile Best Practices gesehen und das Hilfsskript ist das, was sie empfehlen:

#!/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 "$@"

Also ein rekursiver Befehl, um sicherzustellen, dass Sie bei jedem Start das Eigentum haben, und führen Sie dann Ihre App als Benutzer aus. exec erzwingt auch PID 1, damit die Signale funktionieren. Und wenn ich das Volume mit so etwas wie einem Hilfsskript zur Verwendung außerhalb des Containers für die resultierenden Daten füllen möchte, muss es wahrscheinlich auch in das Hilfsskript aufgenommen werden. Ich frage mich jedoch, ob es einen Leistungseinbruch beim Containerstart gibt, wenn Ihre App Tonnen von Dateien auf einem Volume speichert, insbesondere wenn der Speicher nicht lokal ist.

Es scheint, als könnte es eine bessere Lösung geben. Vielleicht so etwas wie das Zuordnen von Container-UID und -GID zu einem bestimmten Benutzernamen und einer bestimmten Gruppe auf dem Host. Kann Docker einen Blick auf /etc des Containers werfen und dies vielleicht herausfinden?

Sie können UIDs/GIDs nicht auf Dateisystemebene zuordnen, zumindest nicht ohne Sicherung.

Sie können UIDs/GIDs nicht auf Dateisystemebene zuordnen, zumindest nicht ohne Sicherung.

Irgendwie was ich befürchtet hatte. Irgendeine Idee, was die Leistungseinbußen sein könnten, wenn Docker eine solche Sicherung verwendet?

@mdegans

Also ein rekursiver Befehl, um sicherzustellen, dass Sie bei jedem Start die Eigentümerschaft haben,

Sie müssen nicht bei jedem Start ein chown machen. Überprüfen Sie stattdessen den Eigentümer des Datenverzeichnisses und führen Sie das rekursive chown nur aus, wenn es nicht korrekt ist. So was:

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

Idealerweise passiert dies also nur beim ersten Start.

Und seien Sie sehr vorsichtig, wenn Sie einen Container mit einem solchen Einstiegspunktskript ausführen. Wenn Sie (zB) Ihr Home-Verzeichnis in den Container einhängen, werden alle Ihre Dateien nach Postgres verschoben

In einem guten Docker-Image-Design ist der Laufzeitbenutzer nicht root und kann daher keine chown -Dateien …!

In einem guten Docker-Image-Design ist der Laufzeitbenutzer nicht root und kann daher keine Dateien chown …!

Richtig, aber es sollte nichts einen Wechsel zu und von root , was oft erforderlich ist ... genauso wie Sie normalerweise nichts als root sollten, bis Sie es brauchen, aber wenn Sie dies tun, können Sie einen oder mehrere der folgenden Schritte ausführen:

  • sudo
  • su
  • USER root

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

Meiner bescheidenen Meinung nach ist es Sache des Benutzers des Docker-Images, sicherzustellen, dass er/sie die Berechtigung für das bereitgestellte Volume richtig setzt.

Es ist sehr ähnlich zu dem, was wir traditionell gemacht haben, bevor Container eine Sache waren, zB als ich nginx ausführen wollte und sicherstellen musste, dass das statische HTML-Verzeichnis dem richtigen Benutzer gehörte. Um zu wissen, dass ich meine nginx.conf-Datei öffnen müsste, überprüfen Sie den Benutzer der Arbeiter und legen Sie die Berechtigungen entsprechend fest. Eigentlich wurde dies alles in der nginx-Dokumentation beschrieben.

Dies ist nur ein Unix-Berechtigungsproblem, nichts Neues mit Docker hier. Vielleicht ist die Lösung für dieses Problem also eine bessere Dokumentation für jedes Docker-Image darüber, was das Eigentum an gemounteten Volumes sein sollte. Ich erinnere mich nicht, dass der nginx-Startup-Daemon sichergestellt hat, dass das Verzeichnis den richtigen Besitz hat. Es würde einfach fehlschlagen, wenn es nicht korrekt eingerichtet wäre.

Dies ist jedoch wahr, da wir jetzt potenziell innerhalb des Containers definierte Benutzer haben und nicht außerhalb, dass die Dinge anders aussehen (und sie nicht sind). Aber die UID innerhalb und außerhalb sind äquivalent, sodass der Benutzer foobar mit UID 2000 möglicherweise innerhalb eines Containers existiert und nicht außerhalb, aber UID 2000 kann weiterhin für Dateien und Verzeichnisse außerhalb festgelegt werden. Wir müssen unser Denken in Bezug auf UID/GID ändern und nicht mehr in den menschenfreundlichen Namen, mit denen wir uns bisher beschäftigt haben.
Es macht die Dinge möglicherweise auch schwieriger, wenn Sie ein Volumen zwischen 2 Containern teilen müssen, die von 2 verschiedenen Autoren geschrieben wurden. Es ist möglich, dass das Festlegen von Berechtigungen mit dem traditionellen Unix-System (von Benutzern, Gruppen und anderen) nicht ausreicht, um das Problem zu lösen (keine gemeinsame UID oder GID). Ich gebe zu, dass ich POSIX ACL viel häufiger verwende, seit ich Docker verwende. Ich kann daher 3 verschiedenen Benutzerberechtigungen für dieselbe Datei zuweisen. B. ein Containerschreiber mit rw-Berechtigung, ein Containerleser mit r-Berechtigung und ein Hostbenutzer mit r-Berechtigung.

Eine weitere Option: Eine gemeinsame GID kann mit dem setgid-Flag für freigegebene Verzeichnisse erzwungen werden. Die Dateimaske kann mit ACL erzwungen werden.

Bevor Sie irgendetwas im Docker-Container tun, führen Sie Folgendes aus:

```
umaske 0000
````

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

Kommen Sie zu spät zu diesem Thread, um zu bestätigen, wie hilfreich diese Funktion wäre.

Um ehrlich zu sein, setze ich Container jetzt seit etwa einem Jahr ein und sehe, dass dies überall zu einem echten Problem wird. Eine Lösung auf dieser Ebene anzubieten, scheint hier die einzig vernünftige Wahl zu sein.

So wie es heute aussieht, hat sich eine beträchtliche Anzahl von Docker-Images dafür entschieden, ihre Einstiegspunkte weiterhin als root auszuführen, damit sie Verzeichnis- und Dateiberechtigungen booten können, nur um Berechtigungen zu löschen, bevor der Anwendungsprozess ausgeführt wird.

Ein echtes Problem tritt auf, wenn Sie feststellen, dass nicht jeder auf diese Praxis zurückgreifen kann. Bei einigen gängigen Plattformen wie Kubernetes oder OpenShift können einige dieser Umgebungen so konfiguriert sein, dass sie keine privilegierten Container zulassen … aus … Sicherheit. Aus dem Kopf heraus kann ich unmöglich verstehen, wie ein großes Finanzinstitut überhaupt in Erwägung ziehen würde, eine Container-Plattform einzuführen, die sensible Informationen ohne diese Art von Einschränkung verarbeitet.

Die durch die _Entrypoint-as-Root_-Praxis aufgeworfenen Sicherheitsbedenken haben dazu geführt, dass eine große Anzahl von Kubernetes-Helm-Charts initContainers bereitstellt, die chown - und chmod -Volumes bereitstellen können, bevor der Anwendungscontainer gestartet wird . Dies mag wie ein netter Weg erscheinen, aber glauben Sie mir, wenn ich das sage: Das ist es nicht .

Insbesondere Helm-Diagramme sind mit hartcodierten uids und gids übersät, da diese heimlich aus der Anwendungslaufzeit gerissen werden müssen. Diese Informationen sind im Container verborgen und während der Bereitstellung nicht sofort verfügbar.

Obwohl es eine Reihe von Möglichkeiten gibt, das Problem zu umgehen, plagt es weiterhin alle Bereitstellungskonfigurationen als _Hack, um die Dinge zum Laufen zu bringen_. Die Anzahl der davon betroffenen Bereitstellungen nimmt rapide zu und die Techniken, auf die die Menschen zurückgreifen, stehen im Widerspruch zu allen anderen Vorteilen, die Container mit sich bringen.

Ich hoffe, es gibt eine Möglichkeit, dies als Teil der OCI-Spezifikation zu implementieren, damit andere Lösungen, die auf Docker angewiesen sind, es verwenden können, um elegant eine vollständig automatisierte Bereitstellung bereitzustellen.

Dann stellt sich die Frage: Wo sonst im Internet entwickeln sie die gemeinsame OCI-Spezifikation, wo sollte diese Diskussion geführt werden? Angenommen, dies ist nicht der beste Weg, um diese Funktion in Docker zu integrieren (letztlich durch eine Anforderung für die Einhaltung einer gemeinsam vereinbarten Standardübernahme in der Zukunft).

Denn das Problem wird definitiv nie von alleine verschwinden, und die Lösung erfordert einige sehr grundlegende Änderungen.

initContainers, die Volumes ändern und ändern können, bevor der Anwendungscontainer gestartet wird. Dies mag wie ein netter Weg erscheinen, aber glauben Sie mir, wenn ich das sage: Das ist es nicht.

FWIW; Diese Funktion wäre nur in Situationen erforderlich, in denen Dateien von mehreren Namespaces gemeinsam genutzt werden (entweder Dateien, die (vorher) auf „dem Host“ vorhanden sind, oder ein gemeinsamer Dateispeicherort, der von mehreren Containern gemeinsam genutzt wird, die als unterschiedliche Benutzer ausgeführt werden). In Situationen, in denen Dateien auf dem Host vorab erstellt werden, kann dies abgemildert werden, indem sichergestellt wird, dass diese Dateien über die richtigen Eigentümer und Berechtigungen verfügen, bevor sie für den Container freigegeben werden. Tatsächlich unterscheidet sich das nicht von (z. B.) dem Ausführen von nginx auf dem Host und dem Sicherstellen, dass Dateien im Webroot die richtigen Berechtigungen haben.

Wenn Sie Container teilen, die unter einem anderen Benutzer ausgeführt werden, führen Sie entweder beide Container mit demselben uid (oder gid ) aus und legen Sie die richtigen Gruppenberechtigungen fest, ähnlich wie dies bei der Ausführung von zwei Containern funktionieren würde nicht containerisierte Prozesse, die Zugriff auf dieselben Ressourcen haben müssen).

Einige dieser Umgebungen sind möglicherweise so konfiguriert, dass sie keine privilegierten Container zulassen ... aus Sicherheitsgründen. Aus dem Kopf heraus kann ich unmöglich verstehen, wie ein großes Finanzinstitut überhaupt in Erwägung ziehen würde, eine Container-Plattform einzuführen, die sensible Informationen ohne diese Art von Einschränkung verarbeitet.

Nur um Verwirrung zu vermeiden; Ein Container, der als root ausgeführt wird, ist nicht dasselbe wie ein „privilegierter“ Container ( --privileged oder Optionen, wie z. B. --cap-add gesetzt). Privilegierte ( --privileged ) Container sind hochgradig unsicher, wohingegen ein Container, der als root ausgeführt wird, vollständig eingeschlossen ist und nicht ausbrechen kann ; Ihn per Bind gemountete Dateien/Verzeichnisse zu übergeben, stanzt Löcher hinein, also gibt _will_ ihm Zugriff auf die Dateien/Verzeichnisse, die Sie als Bind-Mount übergeben.

Insbesondere Helm-Charts sind mit fest codierten UIDs und GIDs übersät, da diese heimlich aus der Anwendungslaufzeit gerissen werden müssen. Diese Informationen sind im Container verborgen und während der Bereitstellung nicht sofort verfügbar.

Frage mich: ob diese uids/gids nicht bekannt sind; Wie würde die UX aussehen? (Da ich eine Zuordnungs-UID/GID bereitstellen müsste, um eine Host-UID/GID einer (unbekannten) Container-UID/GID zuzuordnen?

Dann stellt sich die Frage: Wo sonst im Internet entwickeln sie die gemeinsame OCI-Spezifikation, wo sollte diese Diskussion geführt werden?

Ich glaube nicht (auf den ersten Blick), dass eine Änderung der OCI-Spezifikation erforderlich ist; dies kann außerhalb der OCI-Spezifikation gelöst werden; Das Hauptproblem besteht darin, dass Mechanismen zum Zuordnen von UIDs/GIDs derzeit im Kernel fehlen (oder existieren (wie shiftfs ), aber nicht allgemein verfügbar sind).

Dies ist ein klassisches Fünfeck von Verantwortungsübergabe / jemand anderes kann oder sollte dieses Problem lösen. Entweder es ist die:

  • Nutzer
  • Die spezifische Implementierung der Docker-/Containerisierungsplattform
  • OCI-Spez
  • Kernel
  • Dateisystem

Das Problem wurde bereits effektiv angesprochen: dass es sowohl umständlich als auch weniger sicher ist, wenn der Benutzer dies tun muss. Der Folgeeffekt, dass Benutzer Hacks pro Bild machen, ist jedoch ebenfalls wichtig:

Das heißt, Sie können Bilder von verschiedenen Benutzern nicht so einfach miteinander bearbeiten und teilen / mischen, um zusammenzuarbeiten. Also entweder:

  • Unterbricht das Community-Sharing (ziemlich viel). Denn unterschiedliche Nutzer definieren aus demselben globalen Namespace-Pool ihre UIDs und Gids für ihre individuell entwickelten Images
  • Zwingt Benutzer, ihren eigenen Ad-hoc-Standard zu entwickeln und zu hoffen, dass andere einer Konvention folgen, die sie selbst gewählt haben
  • Zwingt Benutzer, root für alles zu verwenden. Was mit Sicherheit weniger sicher ist. Weil Sie eine zusätzliche Ebene des privilegierten Eskalationsschutzes entfernen, die Sie sonst gehabt hätten. Und macht Container-Breakout-Schwachstellen viel einfacher auszunutzen, da sich der Benutzer von Anfang an bereits root innerhalb des Containers befindet. Ganz zu schweigen von der Möglichkeit, andere Dienste innerhalb desselben Containers auszuführen, was auch eine andere Möglichkeit ist, seitwärts zu gehen, bevor es nach oben geht.

Es ist also ein Handel. Die oben genannten sind die aktuellen Kompromisse. Während Sie verschiedene Kompromisse eingehen müssten, um die Verantwortung an eine oder mehrere der anderen oben aufgeführten Stellen zu übertragen.

Übrigens haben wir in Bezug auf eine genauere Betrachtung einer dateisystembasierten Lösung diesen "möglicherweise nützlichen" Kommentar von Spider-Links gefunden:

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

Das hat mehrere unterschiedliche Verweise auf dieselbe allgemeine Funktion (auf andere Projekte / Orte), einschließlich auf ein verteiltes Dateisystem (bekannt als „Lustre“), und andere Probleme in Bezug auf ZFS. Nun, ich nutze zufälligerweise selbst ZFS hier drüben.

Dann auch eine weitere Kopie des gleichen Fehlers auf Ubuntu / Launchpad gefunden. Bezug auf das gleiche ZOL #4177-Problem,

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

Was besagt, dass der fragliche Fehler in der zfs-Version 0.6.5.7+ SO behoben wurde. Bedeutet dies, dass wir potenziell zfs und ACLs als eine Art Sicherungsspeicher für die Neuzuordnung von uids und gids irgendwie verwenden können? Nun, das ist etwas, von dem ich noch nie gehört habe.

Oh, vielleicht funktioniert diese Lösung nur für LXC-Container. Weil er dort in seinen Kommentaren (der Leiter des LXC-Projekts) auch sagte: "Wir verwenden Setuid-Hilfsprogramme (newuidmap und newgidmap)", die dann "eine uid- und gid-Karte einrichten können". Vermutlich gibt es also auch einen notwendigen Mechanismus in LXC selbst, sonst kann der zfs-acls-Teil nicht verwendet werden? Oder vielleicht irre ich mich. Ich bin mir nicht ganz sicher, ob ich das ganz befolge.

Ein weiterer interessanter Link, diesmal über shiftfs , und eine Diskussion über die Möglichkeit, seine Funktionen in Overlayfs zu integrieren. Was natürlich ein zugrunde liegendes Dateisystem ist, das Docker bereits verwendet.

Was passiert jedoch, wenn die Neuzuordnungsfunktion in overlayfs implementiert wird, ich aber stattdessen den Speichertreiber zfs für mein zugrunde liegendes Dateisystem verwenden möchte? Muss ich dann von der Möglichkeit ausgeschlossen werden, UIDs/GIDs neu zuzuordnen, wenn dies auf Dateisystembasis implementiert wird? Oder können wir beide separat implementieren lassen? Entschuldigung, mir ist etwas unklar, ob der Docker-Daemon solche Neuzuordnungen kennen und eine gemeinsame API und Flags bereitstellen muss (um sie an die fs-Treiberschicht weiterzugeben). Oder wenn wir stattdessen selbst auf der Hostseite (im Dateisystem, außerhalb von Docker) eine solche Neuzuordnung manuell durchführen würden. Auch dieser Aspekt bleibt mir etwas unklar.

[EDIT] Ups, Link vergessen! Hier ist es

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

Bei diesem Thema geht es um Volumes / Bind-Mounts, also getrennt vom Dateisystem des Containers

Wir würden übermäßig mit einer uid/gid-Verschiebung für das Bindmount verwenden, wenn das Overlay shiftfs-Funktionen enthält, aber auf nicht unterstützten Systemen auf etwas anderes (oder nichts) zurückgreifen müssten.

Podman ist ein wurzelloser Docker-Drop-In-Ersatz https://www.youtube.com/watch?v=N0hSn5EwW8w https://podman.io/ . Bei podman wird root nicht verwendet, sodass die Benutzerberechtigung korrekt gehandhabt wird. Unser Team ist aufgrund dieses Problems zu Podman gewechselt und hat sehr gut funktioniert.

Das macht keinen Sinn.
Es gelten die gleichen Probleme.
Beachten Sie, dass Docker auch einen Rootless-Modus hat.

Sie können Podman mit den folgenden Befehlen testen. Podman hat im Gegensatz zu Docker keinen separaten Daemon, und alles läuft unter dem Benutzer, der podman -Befehle ausführt. Dateien, die in Podman erstellt wurden, gehören also dem Benutzer, der den Befehl podman run ... ausgeführt hat.

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

Dies ist nicht der geeignete Ort, um für podman zu werben. Wenn es spezifische technische Details zur Funktionsweise gibt, die zur Lösung dieses Problems beitragen können, wären diese relevant, um sie zu diskutieren, insbesondere als potenzielle Lösungen für das von Ihnen beschriebene Problem. kommentiere gerade. Bisher war dies nicht der Fall, also führen Sie diese Diskussion bitte an anderer Stelle.

Die Tatsache, dass podman eine ganz andere Architektur als Docker hat, was dieses Problem weniger schwerwiegend/schmerzhaft macht, erlaubt es Docker nicht auf magische Weise, seine Funktionsweise vollständig zu ändern, nur um dieses eine Problem zu lösen. Ich kann Ihnen versichern, dass es viele Gründe dafür gibt, warum Docker so strukturiert ist, wie es ist, und es ist ehrlich gesagt schlechtes Gewissen, all diese Geschichte zu ignorieren.

@tianon Ja, absolut, es gibt Vor- und Nachteile für beide Ansätze. Ich habe podman nur deshalb erwähnt, weil das Ausführen eines Containers mit podman mit dem Zielbenutzer speziell dieses technische Problem löst, nämlich „Volumen als anderen Benutzer als root bereitstellen“.

Bitte werfen Sie einen Blick auf die Erlaubnis von "test_file", die in meinem obigen Kommentar erstellt wurde. Zuerst wird das Verzeichnis „~/podman_test“ gemountet und die Datei „test_file“ in den Podman-Container geschrieben. Sobald der Benutzer den Container verlässt, können Sie sehen, dass die Datei „kkimdev“ gehört, nicht root.

Das Problem ist, dass Ihr Vorschlag, ein Problem mit Docker zu beheben, darin besteht, dass er auf „Docker nicht verwenden“ hinausläuft, was für den Issue-Tracker für Docker nicht besonders konstruktiv ist.

Ja, podman ist anders gestaltet, was dieses Problem für dieses Tool strittig macht - das ist gut und schön, aber hier völlig vom Thema abgekommen. Rootless hat verschiedene Kompromisse, von denen einige für manche Leute in Ordnung sind, andere nicht. Es wird mit der Zeit besser (und meistens Kernel-Verbesserungen), aber es ist keine generische Lösung für alle hier.

Dies erfordert entweder Kernel-Modifikationen oder einen Shim für eine generische Lösung, wie oben ausführlich besprochen (und da @cpuguy83 und andere daran gearbeitet haben, zu versuchen, dieses Problem auf generische Weise zu lösen).

Docker hatte dieses spezielle Problem seit 2013 offen und fast sechs Jahre später ist keine einfache Verbesserung in Sicht. Podman wurde entwickelt, um Kompatibilität mit Docker zu erreichen, aber auch die Designfehler von Docker zu beheben (einschließlich der Ausführung als nicht privilegierter Benutzer, der keinen Superuser-Docker-Daemon benötigt).

Wenn Benutzer in der Lage sind, anderen einen Rat zu einem GitHub-Problem zu geben, ist das völlig in Ordnung. Dies ist eine Gemeinschaft. Fühlen Sie sich frei, alles zu empfehlen, was hilfreich sein könnte.

Ich kann Ihnen versichern, dass es viele Gründe dafür gibt, warum Docker so strukturiert ist, wie es ist

So ist grep . Aber wenn jemand schneller suchen muss, würde ich trotzdem ripgrep empfehlen. Sogar auf dem grep Issue Tracker. Es sollte egal sein, wessen Issue Tracker es ist, solange er das Problem der Benutzer löst und sie glücklich macht.

Wenn Podman für Sie nicht funktioniert: Gut! Aber wenn anderen geholfen wird, weil sie nur docker podman ersetzen müssen: Lassen Sie sie einfach tun.

Podmans Hauptargument ist, dass es keinen Daemon ausführt, und das ist mein Hauptargument dagegen. Wie bekomme ich meinen Container nach einem Neustart wieder hoch? Ich werde es nicht von Hand machen und alles andere ist nur schlechtes Design. Außerdem möchte ich nicht, dass mein Docker-Container einem Benutzer gehört, sondern dem System gehört, und das bedeutet root.
Podman ist sinnvoll, wenn Sie die einzige Person sind, die es verwendet.

Und um Ihr Problem zu beheben: Erstellen Sie einen Container mit COPY --chown ...:... !

Auch Docker hat solche Probleme nicht und man kann Docker-Server fernsteuern, was auch für mich wichtig ist.

Es gibt auch Tools zum Generieren von Pods aus laufenden Containern, die ich nicht empfehlen werde, da Sie sie von Grund auf sauber erstellen sollten.

Ich denke, wir sollten jetzt zum Thema zurückkehren: IMHO war der erste Rat in Ordnung, aber alles andere sprengt dieses Problem nur und wird nichts lösen.


@SuperSandro2000 , Sie können jedoch hier klicken, um die Antwort auf Ihre Aussagen zu erhalten.

Wie bekomme ich meinen Container nach einem Neustart wieder hoch? Ich werde es nicht von Hand machen und alles andere ist nur schlechtes Design.

Nun, Podman hat eine native Integration mit systemd (wie _fast_ alles andere auf fast allen modernen GNU-Linux-Distributionen). Sie müssen also nicht „zwei“ Bootsysteme verwalten (wie zuerst systemd, um den Docker-Daemon zu starten, der dann eine weitere Runde zum Starten von Containern in einer anderen Konfiguration machen muss). Mit Podman können Sie also alles mit systemd steuern (gemeint ist: das System, das Sie höchstwahrscheinlich bereits installiert haben und sowieso ausführen).

Außerdem möchte ich nicht, dass mein Docker-Container einem Benutzer gehört, sondern dem System gehört, und das bedeutet root.

Es ist völlig in Ordnung, wenn Sie es nicht wollen. Sie können Podman immer noch als Superuser ausführen, aber Sie _müssen_ nicht mehr. Im Allgemeinen gilt es als schlechte Idee und erhöht die Angriffsfläche, denn wenn jemand Ihren Docker-Daemon ausnutzen kann, hat er die Kontrolle über _alles_ auf dem System.

Podman ist sinnvoll, wenn Sie die einzige Person sind, die es verwendet.

Diese Aussage ergibt keinen Sinn. Podman ermöglicht es Ihnen, sich auf ein einziges System zu verteilen, was besonders dann sinnvoll ist, wenn viele Personen an demselben System arbeiten.

Und um Ihr Problem zu beheben: Erstellen Sie einen Container mit COPY --chown ...:... !

IMHO ist das Problem hier das _Mounten_ eines Volumes für einen Container zur _Runtime_. Was mit Imagebildung nur wenig zu tun hat.

Auch Docker hat solche Probleme nicht und man kann Docker-Server fernsteuern, was auch für mich wichtig ist.

Komisch, dass du genau den Blog erwähnst, der diesen Beitrag enthält. Ich bin jedoch nicht sehr erfahren mit Netzwerkdetails beider Implementierungen, aber wie ich verstanden habe, beginnt Podman mit den geringstmöglichen Netzwerkregeln, und nicht privilegierte Benutzer können keine veth -Paare einrichten

Um es klar zu sagen, Sie sollten in der Lage sein, mit Rootless Docker den gleichen Effekt zu erzielen wie mit Podman.
Dies liegt daran, dass dockerd als Ihr Benutzer ausgeführt wird und root im Container Ihrer UID zugeordnet ist.

Dies hat Nachteile und funktioniert natürlich nicht, wenn ein Daemon mit mehreren Benutzern geteilt wird.
https://get.docker.com/rootless

Am 27. Juni 2019 um 7:52 Uhr schrieb Alexander Adam [email protected] :

Ich denke, wir sollten jetzt zum Thema zurückkehren: IMHO war der erste Rat in Ordnung, aber alles andere sprengt dieses Problem nur und wird nichts lösen.

@SuperSandro2000 https://github.com/SuperSandro2000 , Sie können jedoch hier klicken, um die Antwort auf Ihre Aussagen zu erhalten.
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/

Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie auf diese E - Mail direkt, sehen sie auf GitHub https://github.com/moby/moby/issues/2259?email_source=notifications&email_token=AAGDCZXX2UQCG7LUVH57V6LP4TH2DA5CNFSM4AI3DP62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYXL2XI#issuecomment-506379613 , oder schalten Sie den Faden https://github.com/notifications/ unsubscribe-auth/AAGDCZX437HJP4M6XG3SEY3P4TH2DANCNFSM4AI3DP6Q .

@alexanderadam

IMHO besteht das Problem hier darin, ein Volume für einen Container zur Laufzeit bereitzustellen. Was mit Imagebildung nur wenig zu tun hat.

Meine Lösung war, das Verzeichnis nicht zu mounten, sondern es im Container zu backen, wenn es möglich ist.

Ich meine, Podman klingt gut, aber ich werde nicht wechseln, weil ich im Moment keinen Vorteil für mich sehe. Danke trotzdem für die Erklärung.

podman leidet unter dem gleichen Problem, wenn Apache innerhalb des Containers unter dem Benutzer www ausgeführt wird. https://github.com/containers/libpod/issues/3990

Die Lösung könnte darin bestehen, den www -Benutzer aus dem Container der UID auf dem Host zuzuordnen, wenn sich im Container kein root -Benutzer befindet. Ich weiß nicht, ob das möglich ist.

Wenn Sie mit --read-only ausführen möchten (um dasselbe wie die Kubernetes-Richtlinie readOnlyRootFilesystem zu tun), können Sie Folgendes tun. Es baut auf der Problemumgehung auf, die @jpetazzo vorgeschlagen hat :

  • Mein Docker-Image erstellt und verwendet einen Benutzer mit uid=1001 und gid=1001
  • Erstellen Sie separat ein Docker-Volume
  • Ändern Sie die uid:gid auf 1001
  • Mounten Sie dieses Image, wenn Sie die Anwendung ausführen.

Dockerdatei:

FROM ubuntu

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

USER appuser

Dann:

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

Wenn Sie jetzt das Docker-Image ausführen und das Volume mounten, gehört /some_dir dem gewünschten Benutzer.

$ 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

Ich werde noch einmal darauf hinweisen, weil es leicht im Thread verloren geht, dass ein chown Symlink wahrscheinlich für die meisten Szenarien funktionieren wird. Der Nachteil ist, dass Sie es irgendwie einrichten müssen, was oft bedeutet, dass Sie den Einstiegspunkt durch ein Skript ersetzen, das dann den ursprünglichen Befehl ausführt.

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

+1

Ich denke, das ist bisher das ärgerlichste Problem, das ich mit Docker habe, und zu sehen, wie lange dies bereits geöffnet ist, deutet darauf hin, dass dies bei vielen anderen nicht der Fall ist?

Es ist kein Problem, wenn Sie die Problemumgehung kennen. Meine Fälle:

  • Host ist Linux

    • UID im Container == gewünschte UID auf dem Host – es ist keine Problemumgehung erforderlich
    • uid in container != gewünschte uid auf host - führen Sie einfach ein paar setfacl Befehle aus und geben Sie rw Zugriff sowohl für den Hostbenutzer als auch für den Containerbenutzer
  • Host ist MacOS - alles funktioniert sofort nach dem Auspacken für die offizielle Docker-App.

Führen Sie einfach ein paar setfacl -Befehle aus und geben Sie rw Zugriff sowohl für den Host-Benutzer als auch für den Container-Benutzer

Das ist ein Problem. Ich möchte nicht für jedes Docker-Image ein paar setfacl -Befehle ausführen und das Betriebssystem erkennen.

Dies ist tatsächlich auch ein großes Sicherheitsproblem.

Beispielszenario:

  • host1 hat Docker installiert
  • host1 hat mehrere Dienste, die in Docker-Containern ausgeführt werden - die alle lokale Mount-Pfade unter /docker/my-service-01|02|03|etc sind
  • Jeder Container wurde von einem anderen Anbieter gebaut und jeder folgt seiner eigenen uid - und guid -Richtlinie, sodass Sie entsprechend chown -R uid.gid /docker/my-service-01... vorschreiben müssen.

Ergebnis:

  • Irgendwann haben normale oder auf host erstellte Dienstbenutzer vollen Zugriff auf /docker/my-service-01|02|03|etc , was weder beabsichtigt noch erwünscht ist.
  • Wenn Sie ein Volume als "schreibgeschützt" auf zwei Containern unterschiedlicher Anbieter bereitstellen möchten, schlägt dies fehl, da die uid.gid nicht mit den erforderlichen übereinstimmen und Sie chown nicht ausführen können uid.gid Richtlinie hat und sie unterschiedlich sind :)

Ja, wir haben dieses Problem zuvor ausführlich diskutiert, und die wichtigste Tatsache, die (damals) mitgeteilt wurde, war, dass der Linux-Kernel keinen zugrunde liegenden Unterstützungsmechanismus hatte, um neu zuordenbare UIDs und GIDs bereitzustellen. Man müsste also zum Kernel hinzugefügt werden, damit dieses Projekt (moby / docker) diese äußerst wünschenswerte Funktionalität implementieren kann. Sonst hätten wir dieses Feature schon vor einiger Zeit bekommen. Damals, als es zum ersten Mal angeschaut wurde.

Der produktivste Weg, diese Diskussion (heute) fortzusetzen, wäre also: Sehen Sie, ob sich etwas an dieser Situation seitdem geändert hat. Suchen Sie auf vger.org nach einem technischen Kommentar von Linux-Kernel-Mainline-Entwicklern. Suchen Sie nach früheren Patch-Sets / Merge-Anforderungen im Kernel nach dieser zugrunde liegenden fehlenden Funktion. etc.

In der Hoffnung auf ein besseres Verständnis dessen, was auf dieser niedrigeren Ebene passiert ist. Was war der Stolperstein? War es ein Leistungsproblem? War es ein Einwand in Bezug auf das Sicherheitsmodell / Schwächung? Ist es noch auf dem Tisch oder in einer zukünftigen Roadmap, aber macht es erst Sinn, nachdem andere Features B und C implementiert werden können? All diese Kernel-Entwicklung findet woanders statt. Auf anderen Kanälen.

@DXist Die Tatsache, dass dies unter OSX und nicht unter Linux auf magische Weise funktioniert, ist überraschend und ein Problem für sich.

Hat jemand gemäß dem letzten Kommentar von @dreamcat4 einen neuen Versuch unternommen, um zu sehen, wie der Status ist? Haben wir jetzt Unterstützung im Kernel für neu zuordenbare UIDs und GIDs? Wie ist hier der Gesamtstatus?

Ich habe Linux User Namespaces verwendet, um dieses Problem perfekt zu lösen. Funktioniert genauso (AFAICT) wie die anderen Plattformen (Container sieht Bind Mounted Volume als Root, Host sieht es als den Benutzer, der Docker ausführt).

Anleitung ist hier: https://www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/

@patrobinson +1

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen