Fügen Sie Docker ein Volume hinzu, schließen Sie jedoch einen Unterordner aus

208

Angenommen, ich habe einen Docker-Container und einen Ordner auf meinem Host /hostFolder. Wenn ich diesen Ordner als Docker zum Docker-Container hinzufügen möchte, kann ich dies entweder durch Verwenden ADDim Dockerfileoder durch Mounten als Volume tun .

So weit, ist es gut.

/hostFolderEnthält jetzt einen Unterordner , /hostFolder/subFolder.

Ich möchte /hostFolderin den Docker-Container einbinden (ob als schreibgeschützt oder schreibgeschützt, spielt für mich keine Rolle, funktioniert beides), aber ich möchte NICHT , dass er enthalten ist /hostFolder/subFolder. Ich möchte dies ausschließen, und ich möchte auch, dass der Docker-Container Änderungen an diesem Unterordner vornehmen kann, ohne dass dies auch auf dem Host geändert wird.

Ist das möglich? Wenn das so ist, wie?

Golo Roden
quelle
2
@AbhijitSarkar das ist kein sehr konstruktiver (noch in keiner Weise hilfreicher) Kommentar.
Kano
1
@Kano Es ist ein Kommentar, keine Antwort.
Abhijit Sarkar

Antworten:

395

Mit Docker-Compose kann ich node_modules lokal verwenden, aber im Docker-Container mit der folgenden Syntax im ignorieren docker-compose.yml

volumes:
   - './angularApp:/opt/app'
   - /opt/app/node_modules/

Also wird alles in ./angularAppzugeordnet /opt/appund dann erstelle ich ein anderes Mount-Volume, /opt/app/node_modules/das jetzt ein leeres Verzeichnis ist - auch wenn es auf meinem lokalen Computer ./angularApp/node_modulesnicht leer ist.

Kernix
quelle
3
Es funktioniert, aber ich kann diese Verzeichnisse nicht im Container entfernen. Beispiel: Ich muss durch ein /opt/app/node_modules/anderes Verzeichnis mit demselben Namen ersetzen . Fehler tritt auf: 'Lautstärke beschäftigt'
Stepan Yudin
32
Vergessen Sie nicht den nachgestellten Schrägstrich! z.B. / opt / app / node_modules funktioniert nicht, es wird von ./angularApp/node_modules
Stingus
3
Dieser Trick hat bei mir funktioniert, scheint aber nicht mehr zu funktionieren, selbst bei derselben Compose-Datei. Neugierig, ob es auch aufgehört hat, für andere zu arbeiten.
Plinehan
7
Vielen Dank! Du hast meinen Tag gerettet! Im Falle der Verwendung von einfachen Docker, nicht Kompositionen, würde es so aussehen: -v $(pwd):/build/ -v /build/node_modules
Bogdan Mart
3
Ich habe das Dokument docs.docker.com/storage/volumes/… gefunden . If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume.
Hiroshi
118

Wenn Sie möchten, dass Unterverzeichnisse von Docker-Compose ignoriert, aber dauerhaft verwendet werden, können Sie Folgendes tun docker-compose.yml:

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules

Dadurch wird Ihr aktuelles Verzeichnis als freigegebenes Volume bereitgestellt, aber anstelle Ihres lokalen node_modulesVerzeichnisses wird ein dauerhaftes Docker-Volume bereitgestellt . Dies ähnelt der Antwort von @kernix, ermöglicht jedoch das Fortbestehen node_moduleszwischen den docker-compose upLäufen, was wahrscheinlich das gewünschte Verhalten ist.

Nate T.
quelle
20
Benannte Volumes sind ein überlegener Ansatz. Protip: Stellen Sie sicher, dass Sie keinen Datenträgernamen mit Bindestrich verwenden. Sie werden einen kleinen Teil Ihres Lebens in einem Debug-Albtraum verbringen, nur um herauszufinden, dass Sie erneut von einer lächerlichen Nuance getäuscht wurden.
Staub im Web
3
"Beachten Sie, dass Docker-Compose Down diese persistenten Volumes zerstört." Dies gilt nicht für Docker für Mac Version 17.0.5+ (und möglicherweise ältere Versionen). docker-compose downentfernt die Container, aber das Volume bleibt bestehen, bis Sie so etwas wiedocker system prune
BrDaHa
3
Falls jemand interessiert ist zu verstehen, warum die Verwendung des node_modules:benannten Volumes das /app/node_modulesim Docker-Container "ignoriert" , kann dieser Beitrag nützlich sein. Wie behandelt Docker mehrere Mount-Typen?
ira
3
Ich weiß nicht, ob ich etwas falsch mache, aber wenn ich dies tue, starte den Container und führe dann npm install auf dem HOST-Computer aus. Dadurch werden auch die node_modules im CONTAINER geändert. Ich kann mir nicht vorstellen, warum jemand das tun möchte, aber ich suche immer noch nach einer saubereren Trennung.
Renra
3
@Renra hatte genau das gleiche Problem, mein Host-Computer schrieb ständig über node_modules, obwohl ich das genannte Volume hatte ... verursachte alle möglichen Inkompatibilitätsprobleme. Gab es auf Festsetzung und arbeitete um es nur um anstelle des gesamten Repo mein src Ordner kopieren
dancypants
19

Verwenden Sie Folgendes, um eine Datei auszuschließen

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded
Frank Wong
quelle
6
Perfekte Lösung für das, was ich brauchte (um node_modules NICHT dem Host zuzuordnen, da Symlink-Inhalte auf einem Windows-Host fehlerhaft waren). Das Zeigen auf / dev / null hat nicht funktioniert, aber das Erstellen eines leeren Verzeichnisses und das Zuordnen zu diesem Verzeichnis hat perfekt funktioniert und die Probleme gelöst, die ich hatte - danke für diese Idee.
Liam Hammett
1
Dies funktioniert nicht in Docker für Mac 18.09.0 : Cannot start service xxx: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58: mounting \\\"/dev/null\\\" to rootfs \\\"/var/lib/docker/overlay2/d15ed56ad020d408c63a1f6a6365dbb88d5d3b78a4605980d3faa9861102ef21/merged\\\" at [...] unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. Das Hinzufügen eines abschließenden Schrägstrichs hat nicht geholfen.
Blaise
Ich kann bestätigen, dass es auch unter Ubuntu 16.04 mit Docker 18.09.3 nicht funktioniert.
Dirk
Das funktioniert bei mir nicht. Es wird lediglich /dev/nullals Gerätedatei in den Container kopiert .
Radon Rosborough
1
Bitte beachten Sie, dass dies nur zum Ausschließen von DATEIEN funktioniert! / dev / null ist eine Datei und sollte daher das Ziel sein, die Fehlermeldung ist in dieser Hinsicht ziemlich klar : Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. Dies ist nicht genau das, wonach das OP gesucht hat, aber es war sehr nützlich für mich, da ich eine einzelne Datei ausschließen musste.
Avius
13

Erstens unterscheidet sich die Verwendung der ADDAnweisung in einer Docker-Datei stark von der Verwendung eines Volumes (entweder über das -vArgument to docker runoder die VOLUMEAnweisung in einer Docker-Datei). Die Befehle ADDund COPYnehmen zum Zeitpunkt der docker buildAusführung nur eine Kopie der Dateien . Diese Dateien werden erst aktualisiert, wenn mit dem docker buildBefehl ein neues Image erstellt wurde . Im Gegensatz dazu bedeutet die Verwendung eines Volumes im Wesentlichen, dass "dieses Verzeichnis nicht im Container-Image gespeichert werden sollte, sondern stattdessen ein Verzeichnis auf dem Host". Wenn eine Datei in einem Volume geändert wird, wird sie sowohl vom Host als auch vom Container sofort angezeigt.

Ich glaube nicht, dass Sie mit Volumes erreichen können, was Sie wollen. Sie müssen Ihre Verzeichnisstruktur überdenken, wenn Sie dies tun möchten.

Es ist jedoch recht einfach zu erreichen COPY(was vorzuziehen ist ADD). Sie können entweder eine .dockerignoreDatei verwenden, um das Unterverzeichnis auszuschließen, oder Sie können COPYalle Dateien ausführen RUN rm bla, um das Unterverzeichnis zu entfernen.

Denken Sie daran, dass alle Dateien, die Sie dem Image hinzufügen COPYoder ADDmit denen Sie sich im Build-Kontext befinden müssen, dh in oder unter dem Verzeichnis, aus dem Sie ausgeführt werden docker build.

Adrian Mouat
quelle
1
Lerne jeden Tag etwas Neues :-) Das Arbeiten von COPY und ADD funktioniert im Build-Kontext (nicht vom Host). Wäre es möglich, ein Volume zum Maskieren des Unterordners zu verwenden? Das OP möchte den / hostFolder (glaube ich) mounten und / hostFolder / subFolder trennen. Wenn es für jedes ein VOLUME gäbe, aber nur der HostFolder 'gemountet' wäre (-v), würde dies die Änderungen des SubFolders am Container isolieren?
Greg
Ich bin mir nicht sicher, ich habe noch nie versucht, Volumes zu verschachteln. Ich bin nicht davon überzeugt, dass es eine gute Idee ist, aber ich müsste mich darum kümmern.
Adrian Mouat
1
Ich kann anscheinend nirgendwo ein Beispiel dafür finden, was in eine .dockerignoreDatei eingefügt werden soll, um ein Unterverzeichnis (oder sogar ein Verzeichnis) auszuschließen. Angesichts des angegebenen Zwecks der Datei ist dies ziemlich seltsam.
Lukas Oberhuber
1
Sobald Sie Dateien hinzufügen, landen diese immer noch in einigen Ebenen. Wenn Sie sie entfernen, können Sie sie nicht ausblenden, wenn sie sicherheitsrelevant sind oder die Bildgröße verringern (da sie sich in den zugrunde liegenden Ebenen befinden). Es gibt Optionen für squashdie Ebenen. Einer ist github.com/goldmann/docker-squash und ein anderer wird oc ex dockerbuildaus dem OpenShift-Projekt verwendet.
Akostadinov
6

Sieht so aus, als würde die alte Lösung nicht mehr funktionieren (zumindest für mich). Das Erstellen eines leeren Ordners und das Zuordnen eines Zielordners dazu hat jedoch geholfen.

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/
Holdbar
quelle
Funktioniert auch nicht mit docker-compose 1.25.0-rc3Dateisyntax v3.
thisismydesign
6

Mit der Docker-Befehlszeile:

docker run \
    --mount type=bind,src=/hostFolder,dst=/containerFolder \
    --mount type=volume,dst=/containerFolder/subFolder \
    ...other-args...

Die -vOption kann auch verwendet werden (Gutschrift an Bogdan Mart ), --mountist jedoch klarer und empfohlen .

DS.
quelle
6

für die Leute, die auch das Problem hatten, dass der Ordner node_modules immer noch von Ihrem lokalen System überschrieben wird und umgekehrt

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules/

Dies ist die Lösung, wobei das Nachlaufen /nach den node_modules der Fix ist.

Daenor
quelle
0

Um eine gemountete Datei auszuschließen, die im Volume Ihres Computers enthalten ist, müssen Sie sie überschreiben, indem Sie derselben Datei ein Volume zuweisen. In Ihrer Konfigurationsdatei:

services:
  server:
    build : ./Dockerfile
    volumes:
      - .:/app

Ein Beispiel in Ihrer Docker-Datei:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
Emmario Delar
quelle