Thêm âm lượng vào Docker, nhưng loại trừ thư mục con


208

Giả sử tôi có một Docker container và một thư mục trên máy chủ của tôi /hostFolder. Bây giờ nếu tôi muốn thêm thư mục này vào thùng chứa Docker dưới dạng âm lượng, thì tôi có thể thực hiện việc này bằng cách sử dụng ADDtrong Dockerfilehoặc gắn nó dưới dạng âm lượng.

Càng xa càng tốt.

Bây giờ /hostFolderchứa một thư mục con , /hostFolder/subFolder.

Tôi muốn gắn /hostFoldervào bộ chứa Docker (dù là đọc-ghi hay chỉ đọc không quan trọng, hoạt động cả đối với tôi), nhưng tôi KHÔNG muốn bao gồm nó /hostFolder/subFolder. Tôi muốn loại trừ điều này và tôi cũng muốn bộ chứa Docker có thể thực hiện các thay đổi cho thư mục con này mà không phải chịu hậu quả của việc thay đổi nó trên máy chủ.

Điều này có thể không? Nếu vậy thì thế nào?


2
@AbhijitSarkar đó không phải là một bình luận mang tính xây dựng (cũng không hữu ích).
kano

1
@Kano Đó là một bình luận, không phải là một câu trả lời.
Abhijit Sarkar

Câu trả lời:


396

Sử dụng docker-compose Tôi có thể sử dụng node_modules cục bộ, nhưng bỏ qua nó trong bộ chứa docker bằng cú pháp sau trong docker-compose.yml

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

Vì vậy, mọi thứ trong ./angularAppđược ánh xạ tới /opt/appvà sau đó tôi tạo một khối lượng gắn kết khác /opt/app/node_modules/hiện là thư mục trống - ngay cả khi trong máy cục bộ của tôi ./angularApp/node_moduleskhông trống.


3
Nó hoạt động nhưng tôi không thể loại bỏ các thư mục này trong container Ví dụ: tôi cần thay thế /opt/app/node_modules/bằng một thư mục khác có cùng tên. Xảy ra lỗi: 'âm lượng bận'
Stepan Yudin

32
Đừng quên dấu gạch chéo! ví dụ. / opt / app / node_modules không hoạt động, nó sẽ bị ghi đè bởi ./angularApp/node_modules
Stingus

3
Thủ thuật này được sử dụng để làm việc cho tôi, nhưng dường như không còn nữa, ngay cả đối với tệp Soạn giống nhau. Tò mò nếu nó cũng ngừng làm việc cho người khác.
plinehan

7
cảm ơn! Bạn đã cứu ngày của tôi! Trong trường hợp sử dụng docker đơn giản, không phải compos, nó sẽ trông như sau: -v $(pwd):/build/ -v /build/node_modules
Bogdan Mart

3
Tôi đã tìm thấy tài liệu, docs.docker.com/st Storage / volume / lau . 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

Nếu bạn muốn có các thư mục con bị bỏ qua bởi docker-compose nhưng vẫn tồn tại, bạn có thể thực hiện như sau docker-compose.yml:

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

Điều này sẽ gắn kết thư mục hiện tại của bạn dưới dạng một ổ đĩa được chia sẻ, nhưng gắn một ổ cắm docker liên tục thay cho node_modulesthư mục cục bộ của bạn . Điều này tương tự như câu trả lời của @kernix, nhưng điều này sẽ cho phép node_modulestồn tại giữa các docker-compose uplần chạy, có khả năng là hành vi mong muốn.


20
Khối lượng được đặt tên là một cách tiếp cận vượt trội. Protip: đảm bảo bạn không sử dụng tên âm lượng được gạch nối. Bạn sẽ dành một phần nhỏ cuộc sống của mình trong cơn ác mộng gỡ lỗi, chỉ để biết rằng bạn lại một lần nữa bị đánh lừa bởi một sắc thái lố bịch.
Dustintheweb

3
"Lưu ý rằng docker-compose down sẽ giết chết các khối lượng liên tục này." Điều này không đúng trong Docker cho Mac v 17.0.5+ (và có thể là các phiên bản cũ hơn). docker-compose downsẽ loại bỏ các thùng chứa, nhưng âm lượng sẽ tồn tại cho đến khi bạn chạy một cái gì đó nhưdocker system prune
BrDaHa

3
Trong trường hợp ai đó quan tâm để hiểu lý do tại sao sử dụng node_modules:âm lượng được đặt tên "bỏ qua" /app/node_modulestrong thùng chứa docker, có thể tìm thấy bài đăng này hữu ích Làm thế nào docker xử lý nhiều loại gắn kết?
ira

3
Tôi không biết liệu mình có làm gì sai không, nhưng nếu tôi làm điều này, hãy khởi động container và sau đó chạy cài đặt npm trên máy HOST, nó cũng thay đổi node_modules bên trong CONTAINER. Tôi không thể tưởng tượng được tại sao mọi người muốn làm điều đó, nhưng tôi vẫn đang tìm kiếm một sự tách biệt rõ ràng hơn.
Renra

3
@Renra có cùng một vấn đề, máy chủ của tôi sẽ liên tục ghi lên node_modules mặc dù tôi có âm lượng được đặt tên ... gây ra tất cả các loại vấn đề không tương thích. Đã sửa chữa nó và làm việc xung quanh nó bằng cách chỉ sao chép thư mục src của tôi thay vì toàn bộ repo
dancypants

19

Để loại trừ một tệp, sử dụng như sau

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded

6
Giải pháp hoàn hảo cho những gì tôi cần (để KHÔNG ánh xạ node_modules lên máy chủ vì công cụ symlink bị hỏng trên máy chủ Windows). Chỉ vào / dev / null không hoạt động, nhưng tạo một thư mục trống và ánh xạ nó tới đó hoạt động hoàn hảo và giải quyết các vấn đề tôi gặp phải - cảm ơn vì ý tưởng này.
Liam Hammett

1
Điều này không hoạt động trong Docker cho 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. Thêm một dấu gạch chéo không giúp được gì.
Blaise

Tôi có thể xác nhận rằng nó không hoạt động trên Ubuntu 16.04 với Docker 18.09.3.
Dirk

Điều đó không làm việc cho tôi. Tất cả những gì nó làm là sao chép /dev/nullvào container, dưới dạng tệp thiết bị.
Radon Rosborough

1
Xin lưu ý rằng công việc này chỉ để loại trừ PHIM! / dev / null là một tệp và do đó phải là mục tiêu, thông báo lỗi khá rõ ràng về điều này : 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. Đây không phải là chính xác những gì OP đang tìm kiếm, nhưng nó rất hữu ích cho tôi, vì tôi cần loại trừ một tệp duy nhất.
Avius

13

Đầu tiên, sử dụng ADDlệnh trong Dockerfile rất khác so với sử dụng âm lượng (thông qua -vđối số đến docker runhoặc VOLUMEhướng dẫn trong Dockerfile). Các lệnh ADDCOPYchỉ cần lấy một bản sao của các tệp tại thời điểm docker buildđược chạy. Các tệp này không được cập nhật cho đến khi một hình ảnh mới được tạo bằng docker buildlệnh. Ngược lại, sử dụng một ổ đĩa về cơ bản là nói "thư mục này không nên được lưu trữ trong hình ảnh chứa, thay vào đó sử dụng một thư mục trên máy chủ"; Bất cứ khi nào một tập tin bên trong một ổ đĩa được thay đổi, cả máy chủ và thùng chứa sẽ thấy nó ngay lập tức.

Tôi không tin rằng bạn có thể đạt được những gì bạn muốn bằng cách sử dụng khối lượng, bạn sẽ phải suy nghĩ lại về cấu trúc thư mục của mình nếu bạn muốn làm điều này.

Tuy nhiên, nó khá đơn giản để đạt được bằng cách sử dụng COPY(nên được ưu tiên ADD). Bạn có thể sử dụng một .dockerignoretệp để loại trừ thư mục con hoặc bạn có thể COPYtất cả các tệp sau đó thực hiện RUN rm blađể xóa thư mục con.

Hãy nhớ rằng bất kỳ tệp nào bạn thêm vào hình ảnh có COPYhoặc ADDphải nằm trong bối cảnh xây dựng, tức là trong hoặc bên dưới thư mục bạn chạy docker buildtừ đó.


1
học một cái gì đó mới mỗi ngày :-) COPY và ADD hoạt động từ bối cảnh xây dựng (không phải máy chủ lưu trữ). Có thể sử dụng một âm lượng để che dấu SubFolder không? OP muốn gắn kết / hostFolder (tôi nghĩ) và làm cho / hostFolder / subFolder bị ngắt kết nối. Nếu có một SỐ LƯỢNG cho mỗi, nhưng chỉ có máy chủ lưu trữ được 'gắn kết' (-v), thì điều đó có làm cô lập các thay đổi của Bộ lọc con đối với vùng chứa không?
Greg

Tôi không chắc chắn, tôi chưa bao giờ thử khối lượng lồng nhau. Tôi không tin đó là một ý tưởng tốt, nhưng tôi phải xem xét nó.
Adrian Mouat

1
Tôi dường như không thể tìm thấy một ví dụ ở bất cứ nơi nào cần đặt trong một .dockerignoretệp để loại trừ một thư mục con (hoặc thậm chí là một thư mục). Vì đó là mục đích đã nêu của tập tin, nó khá kỳ quặc.
Lukas Oberhuber

1
một khi bạn thêm bất kỳ tập tin nào, chúng vẫn kết thúc ở một số lớp. Vì vậy, việc loại bỏ chúng sẽ không giúp bạn ẩn chúng nếu bảo mật nhạy cảm hoặc giảm kích thước hình ảnh (vì chúng sẽ nằm trong các lớp bên dưới). Có các tùy chọn cho squashcác lớp. Một là github.com/goldmann/docker-squash và một cái khác đang sử dụng oc ex dockerbuildtừ dự án openshift.
akostadinov

6

Có vẻ như giải pháp cũ không còn hiệu quả nữa (ít nhất là đối với tôi). Tuy nhiên, việc tạo một thư mục trống và ánh xạ thư mục đích vào nó.

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

Không hoạt động với tôi docker-compose 1.25.0-rc3, với cú pháp tệp v3.
thisismydesign

6

Với dòng lệnh docker:

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

Các -vtùy chọn cũng có thể được sử dụng (tín dụng để Bogdan Mart ), nhưng --mountlà rõ ràng hơn và khuyến khích .


6

đối với những người cũng gặp vấn đề là thư mục node_modules vẫn sẽ ghi đè từ hệ thống cục bộ của bạn và ngược lại

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

Đây là giải pháp, Với dấu vết /sau nút_modules là bản sửa lỗi.


0

Để loại trừ một tệp được gắn có trong ổ đĩa của máy, bạn sẽ phải ghi đè lên nó bằng cách phân bổ một ổ đĩa cho cùng tệp này. Trong tập tin cấu hình của bạn:

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

Một ví dụ trong bạn dockerfile:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.