Докер ADD против VOLUME

Я изучаю Docker, и у меня есть сомнения относительно того, когда и где использовать ADD и VOLUME. Вот что я думаю, что они оба делают:

ADD

Скопировать файлы в изображение во время сборки. На изображении есть все файлы, которые можно легко развернуть. С другой стороны, необходимость строить каждый раз не выглядит хорошей идеей в разработке, потому что для построения требуется, чтобы разработчик выполнил команду по восстановлению контейнера; Кроме того, создание контейнера может занять много времени.

VOLUME

Я понимаю, что с помощью docker run -v вы можете монтировать папку хоста внутри вашего контейнера, таким образом вы можете легко изменять файлы и наблюдать, как приложение в вашем контейнере реагирует на изменения. Он отлично смотрится в разработке, но я не уверен, как развернуть мои файлы таким образом.

Ответ 1

ADD

Основное различие между этими двумя заключается в том, что ADD делает все, что вы добавляете, будь то папка или просто файл на самом деле части вашего изображения. Любой, кто использует изображение, которое вы создали впоследствии, будет иметь доступ к тому, что вы ADD. Это верно, даже если вы впоследствии удалите его, потому что Docker работает в слоях, а слой ADD все еще будет существовать как часть изображения. Чтобы быть ясным, вы только ADD что-то во время сборки и никогда не сможете ADD во время выполнения.

Несколько примеров случаев, когда вы хотите использовать ADD:

  • У вас есть некоторые требования в файле requirements.txt, который вы хотите установить и установить в своем файле Docker. Затем вы можете: ADD ./requirements.txt /requirements.txt, затем RUN pip install -r /requirements.txt
  • Вы хотите использовать свой код приложения в качестве контекста в своем файле Docker, например, если вы хотите установить каталог приложений в качестве рабочего каталога в своем изображении и иметь команду по умолчанию в контейнере, запущенном с вашего изображения фактически запустите приложение, вы можете сделать:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

VOLUME

Объем, с другой стороны, просто позволяет контейнеру, запущенному с вашего изображения, иметь доступ к некоторому пути на любой локальной машине, на которой выполняется контейнер. Вы не можете использовать файлы из вашего каталога VOLUME в Dockerfile. Все, что в вашем каталоге томов не будет доступно во время сборки, но будет доступно во время выполнения.

Несколько примеров случаев, когда вы хотите использовать VOLUME:

  • Приложение, запущенное в вашем контейнере, делает журналы в /var/log/my_app. Вы хотите, чтобы эти журналы были доступны на главной машине и не удалялись при удалении контейнера. Вы можете сделать это, создав точку монтирования в /var/log/my_app, добавив VOLUME /var/log/my_app в свой файл Docker, а затем запустив контейнер с помощью docker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • У вас есть файлы локальных настроек, к которым вы хотите, чтобы приложение в контейнере имело доступ. Возможно, эти файлы настроек отличаются от вашего локального компьютера против dev и production. Тем более, если эти файлы настроек являются секретными, в этом случае вы определенно не хотите их в своем изображении. Хорошей стратегией в этом случае является добавление VOLUME /etc/settings/my_app_settings в файл Dockerfile, запуск вашего контейнера с помощью docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tag и убедитесь, что /host/settings/dir существует во всех средах, в которых вы ожидаете, что ваше приложение будет запущено.

Ответ 2

Инструкция VOLUME создает объем данных в контейнере Docker во время выполнения. Каталог, представленный в качестве аргумента для VOLUME, представляет собой каталог, который обходит файловую систему союза и в основном используется для постоянных и общих данных.

Если вы запустите docker inspect <your-container>, вы увидите в разделе Mounts есть Source, который представляет местоположение каталога на хосте, и Destination, который представляет местоположение смонтированного каталога в контейнере. Например,

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

Вот 3 варианта использования для docker run -v:

  • docker run -v /data: Это аналогично указанию инструкции VOLUME в вашем файле Docker.
  • docker run -v $host_path:$container_path: Это позволяет монтировать $host_path с вашего хоста на $container_path в вашем контейнере во время выполнения. В разработке это полезно для совместного использования исходного кода на вашем хосте с контейнером. В производстве это можно использовать для монтирования таких вещей, как информация DNS хоста (найденная в /etc/resolv.conf) или секреты в контейнере. И наоборот, вы также можете использовать эту технику для записи журналов контейнера в определенные папки на хосте. Оба $host_path и $container_path должны быть абсолютными путями.
  • docker run -v my_volume:$container_path: создает объем данных в вашем контейнере в $container_path и называет его my_volume. Это по сути то же самое, что создавать и называть тома с помощью docker volume create my_volume. Именование этого тома полезно для объема данных контейнера и тома общего хранилища с использованием драйвера хранения нескольких хостов, например Flocker.

Обратите внимание, что подход к установке папки хоста в качестве тома данных недоступен в Dockerfile. Чтобы процитировать документацию docker,

Примечание. Это недоступно из файла Docker из-за его мобильности и совместного использования. Поскольку каталог хоста по своей природе зависит от хоста, каталог хоста, указанный в файле Docker, вероятно, не будет работать на всех хостах.

Теперь, если вы хотите скопировать файлы в контейнеры в нерабочих средах, вы можете использовать инструкции ADD или COPY в вашем файле Docker. Это то, что я обычно использую для развертывания без разработки.