Docker ADD vs VOLUME


116

Я вчуся Докер і у мене є сумніви щодо того, коли і де використовувати ADDі VOLUME. Ось що я думаю, що обидва:

ДОДАТИ

Копіюйте файли на зображення під час збирання. У зображенні є всі файли, тому ви можете легко розгорнути їх. З іншого боку, потреба будувати кожен раз не виглядає гарною ідеєю в розробці, оскільки для побудови потрібен розробник запустити команду для відновлення контейнера; крім того, будівництво контейнера може зайняти багато часу.

ОБ'ЄМНА

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


3
Загалом, краще віддати перевагу , COPYщоб ADD. Вони майже однакові, але ADDмають деякі додаткові URL-адреси wrt та архівні файли, що може дивувати.
Адріан Муат

2
@jamesmstone - це посилання (і офіційні документи докера) рекомендують навпаки - скопіюйте COPY, а не ADD.
Програмний інженер

ой, ви праві - ура!
jamesmstone

Відповіді:


183

ДОДАТИ

Принципова різниця між цими двома полягає в тому, ADDщо ви робите все, що ви додаєте, будь то папка або просто файл, фактично частина вашого зображення . Кожен, хто використовує згодом створене вами зображення, матиме доступ до будь-якого з вас ADD. Це справедливо навіть у тому випадку, якщо потім ви видалите його, оскільки Docker працює в шарах, а ADDшар все ще буде частиною зображення. Щоб було зрозуміло, ви ADDстворюєте лише щось під час збирання, і ніколи не можете його ADDвиконувати.

Кілька прикладів випадків, коли ви хочете скористатися ADD:

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

    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
  • У вас є кілька файлів локальних налаштувань, до яких ви хочете, щоб програма в контейнері мала доступ. Можливо, ці файли налаштувань відрізняються на вашій локальній машині проти dev vs 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 існує у всіх середовищах, в яких ви очікуєте запуску програми.

13
На сьогоднішній день найкорисніший пост, який я знайшов поки що в
ДОДАТОК

5
Що станеться, якщо вказано VOLUME, але він не надається під час запуску докера (наприклад, параметр -v xxx відсутній)? Чи респ. ГОЛОМ тоді ефективно стає тимчасовим?
col.panic

Всередині Dockerfile томи, ймовірно, призначені лише для збереження та / або налагодження, але ви можете використовувати перемикач командного рядка гучності, щоб отримати додаток до наявного зображення (не потрібен 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розділі є a, Sourceякий представляє розташування каталогу на хості, і a, 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вашого контейнера під час виконання. У розробці це корисно для обміну вихідним кодом вашого хоста з контейнером. У виробництві це можна використовувати для монтажу /etc/resolv.confв контейнер таких речей, як інформація про DNS хоста (знайдена в ) або секрети. І навпаки, ви також можете використовувати цю техніку для запису журналів контейнера в конкретні папки на хості. І те, $host_pathі інше $container_pathповинні бути абсолютними шляхами.
  3. docker run -v my_volume:$container_path: Це створює об'єм даних у вашому контейнері $container_pathта називає його my_volume. Це по суті те саме, що створювати та називати томи за допомогоюdocker volume create my_volume . Іменування такого тома корисно для об'єму даних контейнера та об'єму спільного зберігання, використовуючи драйвер для зберігання з кількома хостами, як Flocker .

Зауважте, що підхід монтажу хостової папки як обсягу даних недоступний у Dockerfile. Щоб процитувати документацію докера ,

Примітка. Це недоступно в Dockerfile через його переносимість та спільне використання. Оскільки каталог хостів за своєю природою залежить від хоста, каталог хостів, зазначений у Dockerfile, ймовірно, не буде працювати на всіх хостах.

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


3
Чи потрібно створити 2 докерські файли? Один для розробки та один для розгортання?
Крістіан Гарсія

Я не думаю, що так. Немає нічого поганого в тому, щоб мати ADDінструкцію у своєму Dockerfile, оскільки вона виконується лише docker buildкомандою. Це потрібно, коли інші створюють ваш контейнер вперше і коли ви готові розгорнути його в інших середовищах, що не розробляються.
ivan.sim

3
Але хіба не було б більш ефективно створити зображення без файлів і використовувати -vкоманду для розробки, а чи створити інший файл докера образ, який включає файли ADDдля розгортання?
Крістіан Гарсія

1
Ви повинні вирішити цю компроміс. Виберіть те, що працює для вас. Скільки часу триває збірка з ADDпритягненням? Всього пару секунд? Якщо у вас є два файли Dockerfile, і ви ділитесь ними з іншими (або публікуєте їх у реєстрі докер ), який з них є типовим? У вас будуть додаткові накладні витрати на обслуговування, щоб забезпечити правильний Dockerfile за потрібними користувачами. Але наприкінці дня ви вирішуєте, що найкраще підходить для вас. Особисто мені подобається переконатися, що є один і єдиний Dockerfile для створення мого контейнера.
ivan.sim

11
До речі, я думаю, що добре спочатку додавати, а потім переосмислювати додавання з -v для розробки. Таким чином вам не знадобляться окремі Dockerfiles.
Attila Szeremi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.