Docker ADD против VOLUME

116

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

ДОБАВИТЬ

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

ОБЪЕМ

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

Кристиан Гарсия
источник
3
В общем, лучше предпочесть , COPYчтобы ADD. Они почти одинаковы, но ADDимеют некоторые дополнительные возможности по отношению к URL-адресам и файлам архивов, что может удивить.
Адриан Муат,
2
@jamesmstone - эта ссылка (и официальные докеры) рекомендуют обратное - используйте КОПИРОВАНИЕ, а не ДОБАВЛЕНИЕ.
Software Engineer
ой, ты прав - ура!
jamesmstone

Ответы:

183

ДОБАВИТЬ

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

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

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

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

ОБЪЕМ

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

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

  • Приложение, запущенное в вашем контейнере, выполняет вход в систему /var/log/my_app. Вы хотите, чтобы эти журналы были доступны на главном компьютере и не удалялись при удалении контейнера. Вы можете сделать это, создав точку монтирования в /var/log/my_app, добавив VOLUME /var/log/my_appв свой Dockerfile, а затем запустив свой контейнер сdocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • У вас есть некоторые файлы локальных настроек, к которым приложение в контейнере должно иметь доступ. Возможно, эти файлы настроек отличаются на вашем локальном компьютере от разработки и производства. Особенно, если эти файлы настроек являются секретными, и в этом случае вы определенно не хотите, чтобы они присутствовали в вашем изображении . Хорошая стратегия в этом случае - добавить 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 / существует во всех средах, в которых вы ожидаете запускать приложение.
Eli
источник
13
Безусловно, самый полезный пост, который я нашел на ADD и VOLUME
Jasmeet
5
Что произойдет, если VOLUME указан, но не указан во время запуска докера (например, отсутствует параметр -v xxx)? Соотв. VOLUME становится преходящим?
col.panic
Внутри Dockerfile тома, вероятно, предназначены только для сохранения и / или отладки, но вы можете использовать переключатель командной строки Volume, чтобы поместить приложение в существующий образ (Dockerfile не нужен) и запустить его таким образом docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.js.
Chinoto Vokro
приятная "многослойная" деталь
stratovarius
27

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

Если вы запустите 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:

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

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

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

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

ivan.sim
источник
3
Должен ли я создать 2 файла докеров? Один для разработки и один для развертывания?
Cristian Garcia
Я так не думаю. Нет ничего плохого в наличии ADDинструкции в вашем Dockerfile, поскольку она выполняется только docker buildкомандой. Это необходимо, когда другие создают ваш контейнер впервые, и когда вы готовы развернуть его в других средах, не связанных с разработкой.
ivan.sim 02
3
Но не было бы более эффективным создать образ без файлов и использовать -vкоманду для разработки, а другой файл докеров создать образ, включающий файлы с ADDдля развертывания?
Cristian Garcia
1
Это компромисс, который вы должны решить. Выберите то, что вам подходит. В ADDлюбом случае, сколько времени занимает сборка с помощью ? Всего пару секунд? Если у вас есть два файла Dockerfile, и вы делитесь ими с другими (или публикуете его в реестре Docker ), какой из них используется по умолчанию? У вас возникнут дополнительные накладные расходы на обслуживание, чтобы убедиться, что нужный Dockerfile по умолчанию попадает к нужным пользователям. Но в конце концов вы решаете, что лучше всего подходит для вас. Лично мне нравится, чтобы был один и только один Dockerfile для создания моего контейнера.
ivan.sim 02
11
Между прочим, я думаю, что можно сначала добавить, а затем переопределить это добавление с помощью -v для разработки. Таким образом, вам не понадобятся отдельные файлы Dockerfiles.
Аттила Шереми