Докер 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. Это то, что я обычно использую для развертывания без разработки.