Docker THÊM vs TÌNH NGUYỆN


116

Tôi đang học Docker và tôi nghi ngờ về việc sử dụng ADDvà khi nào và ở đâu VOLUME. Đây là những gì tôi nghĩ cả hai điều này làm:

THÊM VÀO

Sao chép tập tin vào hình ảnh tại thời điểm xây dựng. Hình ảnh có tất cả các tập tin để bạn có thể triển khai rất dễ dàng. Mặt khác, cần phải xây dựng mọi lúc không giống như một ý tưởng hay trong phát triển vì việc xây dựng đòi hỏi nhà phát triển phải chạy một lệnh để xây dựng lại container; Ngoài ra, việc xây dựng các container có thể tốn thời gian.

ÂM LƯỢNG

Tôi hiểu rằng việc sử dụng docker run -vbạn có thể gắn một thư mục máy chủ bên trong thùng chứa của mình, bằng cách này bạn có thể dễ dàng sửa đổi các tệp và xem ứng dụng trong vùng chứa của bạn phản ứng với các thay đổi. Nó có vẻ tuyệt vời trong phát triển, nhưng tôi không chắc cách triển khai các tệp của mình theo cách này.


3
Nói chung, nó là tốt nhất để thích COPYđến ADD. Chúng gần giống nhau, nhưng ADDcó một số khả năng bổ sung, ghi URL và lưu trữ tệp có thể gây ngạc nhiên.
Adrian Mouat

2
@jamesmstone - liên kết đó (và các tài liệu docker chính thức) đề xuất ngược lại - sử dụng COPY thay vì THÊM.
Kỹ sư phần mềm

Rất tiếc, bạn đã đúng - chúc mừng!
jamesmstone

Câu trả lời:


183

THÊM VÀO

Sự khác biệt cơ bản giữa hai điều này là ADDlàm cho bất cứ điều gì bạn thêm vào, có thể là một thư mục hoặc chỉ là một tệp thực sự là một phần của hình ảnh của bạn . Bất cứ ai sử dụng hình ảnh bạn xây dựng sau đó sẽ có quyền truy cập vào bất cứ điều gì bạn ADD. Điều này đúng ngay cả khi bạn sau đó loại bỏ nó vì Docker hoạt động theo lớp và ADDlớp vẫn sẽ tồn tại như một phần của hình ảnh. Để rõ ràng, bạn chỉ ADDmột cái gì đó vào thời gian xây dựng và không thể bao giờ ADDtrong thời gian chạy.

Một vài ví dụ về trường hợp bạn muốn sử dụng ADD:

  • Bạn có một số yêu cầu trong tệp tests.txt mà bạn muốn tham khảo và cài đặt trong Dockerfile của mình. Sau đó bạn có thể làm: ADD ./requirements.txt /requirements.txttheo sauRUN pip install -r /requirements.txt
  • Ví dụ, bạn muốn sử dụng mã ứng dụng làm bối cảnh trong Dockerfile, nếu bạn muốn đặt thư mục ứng dụng của mình làm thư mục làm việc trong hình ảnh của mình và để có lệnh mặc định trong vùng chứa chạy từ hình ảnh của bạn thực sự chạy ứng dụng của bạn, bạn có thể làm được:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

ÂM LƯỢNG

Mặt khác, Volume chỉ cho phép một container chạy từ hình ảnh của bạn có quyền truy cập vào một số đường dẫn trên bất kỳ máy cục bộ nào mà container đang chạy. Bạn không thể sử dụng các tệp từ VOLUMEthư mục của mình trong Dockerfile . Bất cứ điều gì trong thư mục âm lượng của bạn sẽ không thể truy cập được vào thời gian xây dựng nhưng sẽ có thể truy cập được vào thời gian chạy .

Một vài ví dụ về trường hợp bạn muốn sử dụng VOLUME:

  • Ứng dụng đang được chạy trong container của bạn tạo ra các bản ghi /var/log/my_app. Bạn muốn các bản ghi đó có thể truy cập được trên máy chủ và không bị xóa khi vùng chứa bị xóa. Bạn có thể làm điều này bằng cách tạo một điểm gắn kết tại /var/log/my_appbằng cách thêm VOLUME /var/log/my_appvào Dockerfile của bạn và sau đó chạy container của bạn vớidocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • Bạn có một số tệp cài đặt cục bộ mà bạn muốn ứng dụng trong vùng chứa có quyền truy cập. Có lẽ các tệp cài đặt đó khác nhau trên máy cục bộ của bạn so với sản xuất so với sản xuất. Đặc biệt là nếu các tệp cài đặt đó là bí mật, trong trường hợp đó bạn chắc chắn không muốn chúng trong hình ảnh của mình . Một chiến lược tốt trong trường hợp đó là thêm VOLUME /etc/settings/my_app_settingsvào Dockerfile của bạn, chạy container của bạn docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tagvà đảm bảo / host / settings / dir tồn tại trong tất cả các môi trường mà bạn mong đợi ứng dụng của mình sẽ chạy.

13
Cho đến nay, bài viết hữu ích nhất tôi tìm thấy cho đến nay trên THÊM và
TÌNH NGUYỆN

5
Điều gì xảy ra nếu VOLUME được chỉ định, nhưng không được cung cấp trong quá trình chạy docker (ví dụ: tham số -v xxx bị thiếu)? Là sự tôn trọng. Sau đó, hiệu quả trở nên thoáng qua?
col.panic

Bên trong Dockerfile, các khối lượng có lẽ chỉ dành cho sự kiên trì và / hoặc gỡ lỗi, nhưng bạn có thể sử dụng công tắc dòng lệnh âm lượng để đưa một ứng dụng vào một hình ảnh hiện có (không cần Dockerfile) và chạy nó như thế này docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.js.
Chinoto Vokro

chi tiết "lớp" đẹp
stratovarius

27

Các VOLUMEhướng dẫn tạo ra một khối lượng dữ liệu trong thùng chứa Docker của bạn khi chạy. Thư mục được cung cấp làm đối số VOLUMElà một thư mục bỏ qua Hệ thống tệp Liên minh và chủ yếu được sử dụng cho dữ liệu được chia sẻ và liên tục.

Nếu bạn chạy docker inspect <your-container>, bạn sẽ thấy bên dưới Mountsphần có một Sourcevị trí đại diện cho vị trí thư mục trên máy chủ và một Destinationđại diện cho vị trí thư mục được gắn trong container. Ví dụ,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

Dưới đây là 3 trường hợp sử dụng cho docker run -v:

  1. docker run -v /data: Điều này tương tự với việc chỉ định VOLUMEhướng dẫn trong Dockerfile của bạn.
  2. docker run -v $host_path:$container_path: Điều này cho phép bạn gắn kết $host_pathtừ máy chủ của bạn vào $container_pathtrong thùng chứa của bạn trong thời gian chạy. Trong quá trình phát triển, điều này rất hữu ích để chia sẻ mã nguồn trên máy chủ của bạn với vùng chứa. Trong sản xuất, điều này có thể được sử dụng để gắn kết những thứ như thông tin DNS của máy chủ (tìm thấy /etc/resolv.conf) hoặc các bí mật vào thùng chứa. Ngược lại, bạn cũng có thể sử dụng kỹ thuật này để ghi nhật ký của bộ chứa vào các thư mục cụ thể trên máy chủ. Cả hai $host_path$container_pathphải là con đường tuyệt đối.
  3. docker run -v my_volume:$container_path: Điều này tạo ra một khối lượng dữ liệu trong thùng chứa của bạn tại $container_pathvà đặt tên cho nó my_volume. Về cơ bản, nó giống như việc tạo và đặt tên cho một tập bằng cách sử dụng docker volume create my_volume. Đặt tên một ổ đĩa như thế này rất hữu ích cho một khối lượng dữ liệu chứa và một ổ lưu trữ chia sẻ sử dụng trình điều khiển lưu trữ đa máy chủ như Flocker .

Lưu ý rằng phương pháp gắn thư mục máy chủ dưới dạng khối lượng dữ liệu không có sẵn trong Dockerfile. Để trích dẫn tài liệu docker ,

Lưu ý: Điều này không có sẵn từ Dockerfile do tính di động và mục đích chia sẻ của nó. Vì bản chất của thư mục máy chủ là phụ thuộc vào máy chủ, một thư mục máy chủ được chỉ định trong Dockerfile có thể sẽ không hoạt động trên tất cả các máy chủ.

Bây giờ nếu bạn muốn sao chép các tệp của mình vào các thùng chứa trong môi trường không phát triển, bạn có thể sử dụng ADDhoặc COPYhướng dẫn trong Dockerfile của mình. Đây là những gì tôi thường sử dụng để triển khai không phát triển.


3
Tôi có nên tạo 2 tập tin docker? Một để phát triển và một để triển khai?
Cristian Garcia

Tôi không nghĩ vậy. Không có gì sai khi có ADDlệnh trong Dockerfile của bạn, vì nó chỉ được thực thi bằng docker buildlệnh. Điều này là cần thiết khi người khác xây dựng container của bạn lần đầu tiên và khi bạn sẵn sàng triển khai nó đến các môi trường không phát triển khác.
ivan.sim

3
Nhưng sẽ hiệu quả hơn khi xây dựng một hình ảnh mà không có các tệp và sử dụng -vlệnh để phát triển và có một tệp docker khác tạo một hình ảnh bao gồm các tệp ADDđể triển khai?
Cristian Garcia

1
Đó là một sự đánh đổi bạn phải quyết định. Chọn những gì làm việc cho bạn. Việc xây dựng với một ADDmất bao lâu? Vài giây trong tổng số? Nếu bạn có hai tệp Dockerfile và bạn chia sẻ nó với những người khác (hoặc xuất bản nó trên sổ đăng ký docker), thì tệp nào là mặc định? Bạn sẽ có một số chi phí bảo trì bổ sung để đảm bảo Dockerfile mặc định đúng đến đúng người dùng. Nhưng vào cuối ngày, bạn quyết định những gì phù hợp nhất với bạn. Cá nhân, tôi muốn đảm bảo rằng có một và chỉ một Dockerfile để xây dựng container của tôi.
ivan.sim

11
Bằng cách này, tôi nghĩ rằng tốt trước hết THÊM, sau đó ghi đè thêm bằng -v để phát triển. Bằng cách đó, bạn sẽ không cần Dockerfiles riêng.
Attila Szeremi
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.