UPDATE 2016-03-02: Mit Docker 1.9.0 hat Docker benannte Volumes, welche Data-only Container ersetzen. Die unten stehende Antwort, sowie mein verlinkter Blog-Beitrag, haben weiterhin Wert im Sinne von wie man über Daten innerhalb von Docker nachdenkt, aber erwägen Sie die Verwendung von benannten Volumes, um das unten beschriebene Muster umzusetzen, anstatt Data-Container zu verwenden.
Ich glaube, der kanonische Weg, dies zu lösen, besteht darin, Data-only-Container zu verwenden. Mit diesem Ansatz erfolgt der gesamte Zugriff auf die Volumendaten über Container, die -volumes-from
den Data-Container verwenden, sodass die Host-UID/GID keine Rolle spielt.
Ein Beispiel, das in der Dokumentation genannt wird, ist das Sichern eines Datenvolumens. Dazu wird ein weiterer Container verwendet, um das Backup über tar
durchzuführen, und auch dieser verwendet -volumes-from
, um das Volumen einzubinden. Daher denke ich, dass der Schlüsselpunkt ist zu verstehen: Anstatt darüber nachzudenken, wie man Zugriff auf die Daten auf dem Host mit den richtigen Berechtigungen bekommt, überlegen Sie, wie Sie was auch immer Sie benötigen -- Backups, durchsuchen usw. -- über einen anderen Container durchführen. Die Container selbst müssen konsistente UID/GIDs verwenden, aber sie müssen nicht auf etwas auf dem Host gemappt werden, um portabel zu bleiben.
Das ist auch für mich relativ neu, aber wenn Sie einen bestimmten Anwendungsfall haben, fühlen Sie sich frei zu kommentieren und ich werde versuchen, die Antwort zu erweitern.
UPDATE: Für den in den Kommentaren genannten Anwendungsfall könnten Sie ein Image some/graphite
haben, um Graphite auszuführen, und ein Image some/graphitedata
als Data-Container. Also, unter Vernachlässigung von Ports und dergleichen, sieht das Dockerfile
des Images some/graphitedata
VON debian:jessie
# Fügen Sie zuerst unseren Benutzer und unsere Gruppe hinzu, um sicherzustellen, dass ihre IDs unabhängig von anderen später hinzugefügten Abhängigkeiten konsistent zugewiesen werden
RUN groupadd -r graphite \
&& useradd -r -g graphite graphite
RUN mkdir -p /data/graphite \
&& chown -R graphite:graphite /data/graphite
VOLUME /data/graphite
USER graphite
CMD ["echo", "Data-Container für Graphite"]
Erstellen und erstellen Sie den Data-Container:
docker build -t some/graphitedata Dockerfile
docker run --name graphitedata some/graphitedata
Das some/graphite
Dockerfile sollte auch die gleichen UID/GIDs erhalten, daher könnte es ungefähr so aussehen:
VON debian:jessie
# Fügen Sie zuerst unseren Benutzer und unsere Gruppe hinzu, um sicherzustellen, dass ihre IDs unabhängig von anderen später hinzugefügten Abhängigkeiten konsistent zugewiesen werden
RUN groupadd -r graphite \
&& useradd -r -g graphite graphite
# ... Graphite-Installation ...
VOLUME /data/graphite
USER graphite
CMD ["/bin/graphite"]
Und es würde folgendermaßen ausgeführt:
docker run --volumes-from=graphitedata some/graphite
Ok, das gibt uns also unseren Graphite-Container und den dazugehörigen Data-Only-Container mit dem richtigen Benutzer/Gruppe (beachten Sie, dass Sie den some/graphite
-Container auch für den Data-Container verwenden könnten, indem Sie den entrypoing/CMD beim Ausführen überschreiben, aber sie als separate Images zu haben ist meiner Meinung nach klarer).
Nun, sagen wir, Sie möchten etwas im Datenordner bearbeiten. Anstatt das Volumen an den Host zu binden und es dort zu bearbeiten, erstellen Sie einen neuen Container, um diese Aufgabe zu erledigen. Nennen wir ihn some/graphitetools
. Erstellen wir auch den entsprechenden Benutzer/Gruppe, genauso wie beim some/graphite
-Image.
VON debian:jessie
# Fügen Sie zuerst unseren Benutzer und unsere Gruppe hinzu, um sicherzustellen, dass ihre IDs unabhängig von anderen später hinzugefügten Abhängigkeiten konsistent zugewiesen werden
RUN groupadd -r graphite \
&& useradd -r -g graphite graphite
VOLUME /data/graphite
USER graphite
CMD ["/bin/bash"]
Sie könnten dies DRY machen, indem Sie im Dockerfile von some/graphite
oder some/graphitedata
erben, oder anstatt ein neues Image zu erstellen, nur eines der vorhandenen wiederverwenden (entrypoint/CMD nach Bedarf überschreiben).
Jetzt führen Sie einfach aus:
docker run -ti --rm --volumes-from=graphitedata some/graphitetools
und dann vi /data/graphite/whatever.txt
. Das funktioniert perfekt, weil alle Container denselben Graphite-Benutzer mit übereinstimmender UID/GID haben.
Da Sie /data/graphite
nie vom Host einbinden, spielt es keine Rolle, wie die Host-UID/GID auf die in den Containern graphite
und graphitetools
definierten UID/GID abgebildet werden. Diese Container können nun auf jeden Host bereitgestellt werden und werden weiterhin perfekt funktionieren.
Das Schöne daran ist, dass graphitetools
alle möglichen nützlichen Dienstprogramme und Skripte enthalten könnte, die Sie jetzt auch auf portable Weise bereitstellen können.
UPDATE 2: Nachdem ich diese Antwort geschrieben habe, habe ich beschlossen, einen umfassenderen Blog-Beitrag zu diesem Ansatz zu schreiben. Ich hoffe, es hilft.
UPDATE 3: Ich habe diese Antwort korrigiert und weitere Details hinzugefügt. Sie enthielt zuvor einige falsche Annahmen über den Besitz und Berechtigungen -- der Besitz wird normalerweise zum Zeitpunkt der Volumenerstellung d. h. im Data-Container zugewiesen, weil dies der Zeitpunkt ist, zu dem das Volumen erstellt wird. Siehe diesen Blog. Dies ist jedoch keine Voraussetzung -- Sie können den Data-Container einfach als "Referenz/Handle" verwenden und den Besitz/Berechtigungen in einem anderen Container über chown in einem entrypoint setzen, der mit gosu endet, um den Befehl als den richtigen Benutzer auszuführen. Wenn sich jemand für diesen Ansatz interessiert, kommentieren Sie bitte, und ich kann Links zu einem Beispiel bereitstellen, das diesen Ansatz verwendet.