Dodaj wolumin do Dockera, ale wyklucz podfolder

209

Załóżmy, że mam kontener Dockera i folder na moim hoście /hostFolder. Teraz, jeśli chcę dodać ten folder do kontenera Docker jako wolumin, mogę to zrobić, używając ADDgo Dockerfilelub montując go jako wolumin.

Na razie w porządku.

Teraz /hostFolderzawiera podfolder /hostFolder/subFolder.

Chcę zamontować /hostFolderw kontenerze Docker (niezależnie od tego, czy jest to tylko do odczytu, czy do odczytu, nie ma znaczenia, działa dla mnie oba), ale NIE chcę, aby było to uwzględnione /hostFolder/subFolder. Chcę to wykluczyć, a także chcę, aby kontener Docker mógł dokonywać zmian w tym podfolderze, bez konsekwencji zmiany go również na hoście.

czy to możliwe? Jeśli tak to jak?

Golo Roden
źródło
2
@AbhijitSarkar, który nie jest zbyt konstruktywnym (ani w żaden sposób pomocnym) komentarzem.
kano
1
@Kano To komentarz, a nie odpowiedź.
Abhijit Sarkar

Odpowiedzi:

396

Za pomocą komponentu dokującego jestem w stanie używać modułów node_modules lokalnie, ale zignoruj ​​go w kontenerze dokera, używając następującej składni w docker-compose.yml

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

Wszystko ./angularAppjest odwzorowane na/opt/app a następnie tworzę kolejny wolumin montowania, /opt/app/node_modules/który jest teraz pustym katalogiem - nawet jeśli na moim komputerze lokalnym ./angularApp/node_modulesnie jest pusty.

kernix
źródło
3
Działa, ale nie mogę usunąć tych katalogów z kontenera Na przykład: muszę zastąpić /opt/app/node_modules/innym katalogiem o tej samej nazwie. Wystąpił błąd: „Volume busy”
Stepan Yudin
32
Nie zapomnij o końcowym cięciu! na przykład. / opt / app / node_modules nie działa, zostanie zastąpiony przez ./angularApp/node_modules
Stingus
3
Ta sztuczka kiedyś działała dla mnie, ale wydaje się, że już nie działa, nawet w przypadku samego pliku Compose. Ciekawe, czy przestałby także działać dla innych.
plinehan
8
dzięki! Uratowałeś mi dzień! W przypadku użycia prostego dokera, a nie kompasu, wyglądałoby to tak: -v $(pwd):/build/ -v /build/node_modules
Bogdan Mart
3
Znalazłem dokument, docs.docker.com/storage/volumes/… . 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

Jeśli chcesz, aby podkatalogi były ignorowane przez okno dokowane, ale trwałe, możesz wykonać następujące czynności docker-compose.yml:

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

Spowoduje to zamontowanie bieżącego katalogu jako woluminu udostępnionego, ale zamontowanie trwałego woluminu dokującego w miejsce node_moduleskatalogu lokalnego . Jest to podobne do odpowiedzi @kernix, ale pozwoli to node_modulesna zachowanie się między kolejnymi docker-compose upuruchomieniami, co jest prawdopodobnie pożądanym zachowaniem.

Nate T.
źródło
20
Nazwane woluminy są doskonałym podejściem. Protip: upewnij się, że nie używasz nazwy woluminu dzielonego. Spędzisz niewielką część swojego życia w koszmarze debugowania, ale tylko po to, by przekonać się, że po raz kolejny oszukali cię niedorzeczne niuanse.
dustintheweb
3
„Pamiętaj, że skompilowanie dokera zabije te trwałe woluminy”. Nie dotyczy to Docker dla komputerów Mac w wersji 17.0.5+ (i prawdopodobnie starszych wersji). docker-compose downusunie pojemniki, ale wolumin będzie trwał, dopóki nie uruchomisz czegoś takiegodocker system prune
BrDaHa
3
Jeśli ktoś jest zainteresowany, nie może zrozumieć, dlaczego użycie node_modules:nazwanego woluminu „ignoruje” /app/node_moduleskontenera w oknie dokowanym, może uznać ten post za użyteczny. W jaki sposób doker obsługuje wiele typów montowania?
ira
3
Nie wiem, czy robię coś źle, ale jeśli to zrobię, uruchom kontener, a następnie uruchom npm install na maszynie HOST, to również zmienia moduły node_modu w CONTAINER. Nie mogę sobie wyobrazić, dlaczego ktoś chciałby to zrobić, ale wciąż szukam czystszej separacji.
Renra
3
@Renra miał dokładnie ten sam problem, moja maszyna hosta nieustannie zapisywała moduły node_module, mimo że miałem nazwany wolumin ... powodował różnego rodzaju problemy z niekompatybilnością. Zrezygnowałem z jego naprawy i
obejrzałem
19

Aby wykluczyć plik, użyj następujących poleceń

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded
Frank Wong
źródło
6
Idealne rozwiązanie dla tego, czego potrzebowałem (aby NIE mapować modułów node_modu do hosta, ponieważ dowiązania symboliczne zepsuły się na hoście Windows). Wskazywanie na / dev / null nie działało, ale tworzenie pustego katalogu i mapowanie go do tego działało idealnie i rozwiązało problemy, które miałem - dzięki za ten pomysł.
Liam Hammett
1
To nie działa w Döcker for 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. Dodanie ukośnika nie pomogło.
Blaise,
Mogę potwierdzić, że nie działa on również na Ubuntu 16.04 z Docker 18.09.3.
Dirk
To mi nie działa. Wystarczy skopiować /dev/nulldo kontenera jako plik urządzenia.
Radon Rosborough,
1
Uwaga: działa to tylko w przypadku wykluczenia PLIKÓW! / dev / null jest plikiem, a więc powinien być cel, komunikat o błędzie jest dość jasno: 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. Nie tego dokładnie szukał OP, ale było to dla mnie bardzo przydatne, ponieważ musiałem wykluczyć pojedynczy plik.
Avius
13

Po pierwsze, użycie ADDinstrukcji w Dockerfile różni się bardzo od używania woluminu (albo poprzez -vargument do docker runalbo VOLUMEinstrukcję w Dockerfile). ADDI COPYpolecenia po prostu wziąć kopię plików w czasie docker buildjest prowadzony. Te pliki nie są aktualizowane, dopóki nie zostanie utworzony nowy obraz za pomocądocker build polecenia. Natomiast użycie woluminu zasadniczo mówi „ten katalog nie powinien być przechowywany w obrazie kontenera; zamiast tego użyj katalogu na hoście”; za każdym razem, gdy plik w woluminie jest zmieniany, zarówno host, jak i kontener natychmiast go zobaczą.

Nie wierzę, że możesz osiągnąć to, co chcesz za pomocą woluminów, musisz przemyśleć strukturę katalogu, jeśli chcesz to zrobić.

Jest to jednak dość łatwe do osiągnięcia przy użyciu COPY(co powinno być preferowane ADD). Możesz użyć .dockerignorepliku, aby wykluczyć podkatalog, lub możesz zrobić COPYwszystkie pliki, RUN rm blaaby usunąć podkatalog.

Pamiętaj, że wszelkie pliki dodawane do obrazu za pomocą COPYlub ADDmuszą znajdować się w kontekście kompilacji, tj. W katalogu lub z katalogu, z którego uruchamiasz docker build.

Adrian Mouat
źródło
1
ucz się czegoś nowego każdego dnia :-) KOPIUJ i DODAJ pracę w kontekście kompilacji (nie hosta). Czy można użyć woluminu do maskowania podfolderu? OP chce zamontować / hostFolder (myślę) i rozłączyć / hostFolder / subFolder. Jeśli dla każdego istnieje GŁOŚNOŚĆ, ale tylko „folder” hosta został „zamontowany” (-v), czy to izoluje zmiany w podfolderze w kontenerze?
Greg
Nie jestem pewien, nigdy nie próbowałem zagnieżdżać woluminów. Nie jestem przekonany, że to dobry pomysł, ale musiałbym się nad tym zastanowić.
Adrian Mouat
1
Nie mogę znaleźć nigdzie przykładu, co należy umieścić w .dockerignorepliku, aby wykluczyć podkatalog (lub nawet katalog). Biorąc pod uwagę, że taki jest cel pliku, jest on dość dziwny.
Lukas Oberhuber
1
po dodaniu plików nadal kończą się na niektórych warstwach. Usunięcie ich nie pomoże ukryć ich, jeśli jest wrażliwe na bezpieczeństwo lub zmniejszyć rozmiar obrazu (ponieważ będą znajdować się w podstawowych warstwach). Istnieją opcje squashwarstw. Jedna to github.com/goldmann/docker-squash, a druga korzysta oc ex dockerbuildz projektu openshift.
akostadinov,
6

Wygląda na to, że stare rozwiązanie już nie działa (przynajmniej dla mnie). Pomogło jednak tworzenie pustego folderu i mapowanie folderu docelowego do niego.

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/
uchwyt
źródło
Dla mnie też nie działa ze docker-compose 1.25.0-rc3składnią pliku v3.
thisismydesign
6

Za pomocą wiersza polecenia dokera:

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

-vOpcja może być również używany (kredyt do Bogdana Mart ), ale --mountjest bardziej czytelna i zalecane .

DS.
źródło
6

dla osób, które również miały problem z tym, że folder node_modules nadal nadpisywał z twojego systemu lokalnego i na odwrót

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

To jest rozwiązanie, z końcową /poprawką po module_węzła.

Daenor
źródło
0

Aby wykluczyć podłączony plik znajdujący się w woluminie komputera, musisz go zastąpić, przydzielając wolumin do tego samego pliku. W twoim pliku konfiguracyjnym:

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

Przykład w twoim pliku dokera:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
Emmario Delar
źródło