Docker монтирует тома на хосте

Я успешно смог поделиться папками между док-контейнером с томами, используя

docker run -v /host/path:/container/path ...

Но мой вопрос в том, в чем разница между этим и использованием команды VOLUME в Dockerfile

VOLUME /path

Я использую образ с командой VOLUME, и я хотел бы знать, как поделиться им с моим хостом. Я сделал это с помощью команды -v выше, но я не знал, нужны ли мне и -v, и VOLUME.


person Jeff Storey    schedule 14.08.2014    source источник


Ответы (6)


Команда VOLUME смонтирует каталог внутри вашего контейнера и сохранит все файлы, созданные или отредактированные в этом каталоге, на диске вашего хоста вне файловой структуры контейнера, минуя объединенную файловую систему.

Идея состоит в том, что ваши тома могут быть разделены между вашими док-контейнерами, и они останутся, пока есть контейнер (работающий или остановленный), который ссылается на них.

Вы можете заставить другие контейнеры монтировать существующие тома (фактически разделяя их между контейнерами), используя команду --volumes-from при запуске контейнера.

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

Пример:

  1. У вас есть Dockerfile, который определяет файл VOLUME /var/lib/mysql.
  2. Вы создаете образ докера и помечаете его some-volume
  3. Вы запускаете контейнер

А потом,

  1. У вас есть другой образ докера, который вы хотите использовать на этом томе.
  2. Вы запускаете контейнер Docker со следующим: docker run --volumes-from some-volume docker-image-name:tag
  3. Теперь у вас есть работающий док-контейнер, в котором том из some-volume будет смонтирован в /var/lib/mysql.

Примечание. Использование --volumes-from приведет к монтированию тома поверх того, что существует в расположении тома. То есть, если у вас было что-то в /var/lib/mysql, оно будет заменено содержимым тома.

person Chris McKinnel    schedule 14.08.2014
comment
Что произойдет, если я использую -v для каталога, который уже указан в VOLUME? - person Jeff Storey; 14.08.2014
comment
--volumes-from установит ваш VOLUME поверх всего, что вы укажете с помощью -v. Интересно, что запуск контейнера в привилегированном режиме (docker run --privileged) и umounting /var/lib/mysql просто оставят пустой каталог, поэтому ваше монтирование -v полностью игнорируется, когда оно конфликтует с VOLUME. - person Chris McKinnel; 14.08.2014
comment
Вы говорите, что тома хранятся до тех пор, пока на них ссылается контейнер, и я видел это в другом месте. docs.docker.com/userguide/dockervolumes говорит, что тома данных предназначены для сохранения данных независимо от жизненного цикла контейнера. Поэтому Docker никогда не удаляет тома автоматически при удалении контейнера, а также не собирает в мусор тома, на которые контейнер больше не ссылается. Одно из этих утверждений должно быть неверным. - person mc0e; 06.05.2015
comment
Файлы тома сохраняются на диске, когда контейнер больше не ссылается на него, но сам том больше нельзя использовать (если только вы точно не знаете, как вручную подключить том к контейнеру, но даже в этом случае я не знаю, как это сделать). не знаю, возможно ли это). Когда я говорю, что больше нельзя использовать, я имею в виду, что вы не можете использовать --volumes-from для его использования. Когда выше говорится о сборе мусора, они имеют в виду удаление файлов с вашего диска, которые были в томе. - person Chris McKinnel; 07.05.2015
comment
Их можно использовать, используя -v, но не --volumes-from. Volumes-from принимает имя контейнера для извлечения данных тома (я полагаю, что для этого требуются ВСЕ точки объема). Однако для самого -v в руководстве упоминается, что вы можете указать именованный том для -v в форме named-volume:/path/in/container. Безымянным томам присваиваются хэши для имен, и эти хэши могут быть предоставлены вместо пути к хосту для доступа к осиротевшим томам. :) Имейте в виду, что volume ls может не показывать их все - попробуйте также docker volume ls -f dangling=true. - person Jasmine Hegman; 12.06.2016

Позвольте мне добавить свой собственный ответ, потому что я считаю, что другие упускают смысл Докера.

Использование VOLUME в Dockerfile — это правильный путь™, потому что вы сообщаете Docker, что определенный каталог содержит постоянные данные. Docker создаст том для этих данных и никогда не удалит его, даже если вы удалите все контейнеры, которые его используют.

Он также обходит объединенную файловую систему, так что том фактически является фактическим каталогом, который монтируется (для чтения и записи или только для чтения) в нужном месте во всех контейнерах, которые его разделяют.

Теперь, чтобы получить доступ к этим данным с хоста, вам нужно только проверить свой контейнер:

# docker inspect myapp
[{
    .
    .
    .
    "Volumes": {
        "/var/www": "/var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6...",
        "/var/cache/nginx": "/var/lib/docker/vfs/dir/62499e6b31cb3f7f59bf00d8a16b48d2...",
        "/var/log/nginx": "/var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87..."
    },
    "VolumesRW": {
        "/var/www": false,
        "/var/cache/nginx": true,
        "/var/log/nginx": true
    }
}]

Что я обычно делаю, так это создаю символические ссылки в каком-нибудь стандартном месте, таком как /srv, чтобы я мог легко получить доступ к томам и управлять содержащимися в них данными (только для тех томов, которые вам интересны):

ln -s /var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6... /srv/myapp-www
ln -s /var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87... /srv/myapp-log
person Tobia    schedule 01.04.2015
comment
Что делать, если узел докера работает на виртуальной машине? Например, boot2docker на Mac. Тогда эти тома доступны только удаленно. Кроме того, при использовании томов в Dockerfile, как вы описали, содержимое образа будет скопировано на том. Однако при монтировании в локальный каталог такого копирования не происходит. Вы знаете, почему это так? Есть ли способ иметь локально смонтированный том, но при этом «начать заново» с файлами из образа? - person LostSalad; 04.10.2015
comment
с помощью docker-compose вы можете сделать это, смонтировать том на конкретное расположение хост-системы. Симлинки не нужны... - person Hugo Koopmans; 24.02.2016
comment
@Tobia: пример docker-compose см. в документации docs.docker.com /compose/compose-file/ - person Hugo Koopmans; 24.03.2020

VOLUME используется в Dockerfile для предоставления тома, который будет использоваться другими контейнерами. Например, создайте Dockerfile как:

ИЗ убунту: 14.04

RUN mkdir /myvol  
RUN echo "hello world" > /myvol/greeting  
VOLUME /myvol

построить образ:

$ docker build -t testing_volume .

Запустите контейнер, скажем container1:

$ docker run -it <image-id of above image> bash

Теперь запустите другой контейнер с параметром Volumes-From как (скажем-container2)

$ docker run -it --volumes-from <id-of-above-container> ubuntu:14.04 bash

Вы получите все данные из каталога container1 /myvol в container2 в том же месте.

Параметр -v задается во время выполнения контейнера, который используется для монтирования каталога контейнера на хосте. Он прост в использовании, просто укажите параметр -v с аргументом <host-path>:<container-path>. Вся команда может быть как $ docker run -v <host-path>:<container-path> <image-id>

person Yogesh Jilhawar    schedule 26.09.2016

В основном варианты VOLUME и -v почти равны. Это означает «смонтировать конкретный каталог в вашем контейнере». Например, VOLUME /data и -v /data имеют одинаковое значение. Если вы запустите образ с параметром VOLUME /data или с параметром -v /data, каталог /data будет смонтирован в вашем контейнере. Этот каталог не принадлежит вашему контейнеру.

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

$ docker run -it -v /data --name volume ubuntu:14.04 bash
root@2b5e0f2d37cd:/# cd /data
root@2b5e0f2d37cd:/data# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/data# cd /tmp
root@2b5e0f2d37cd:/tmp# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/tmp# exit
exit

$ docker commit volume nacyot/volume  
835cfe3d8d159622507ba3256bb1c0b0d6e7c1419ae32751ad0f925c40378945
nacyot $ docker run -it nacyot/volume
root@dbe335c7e64d:/# cd /data
root@dbe335c7e64d:/data# ls
root@dbe335c7e64d:/data# cd /tmp
root@dbe335c7e64d:/tmp# ls
1  2  3  4  5  6  7  8  9
root@dbe335c7e64d:/tmp# 
root@dbe335c7e64d:/tmp# 

Этот смонтированный каталог, такой как /data, используется для хранения данных, которые не принадлежат вашему приложению. И вы можете заранее определить каталог данных, который не принадлежит контейнеру, используя VOLUME.

Разница между параметрами Volume и -v заключается в том, что вы можете динамически использовать параметр -v при запуске контейнера. Это означает, что вы можете динамически монтировать какой-либо каталог. И еще одно отличие состоит в том, что вы можете смонтировать свой хост-каталог в своем контейнере, используя -v

person nacyot    schedule 14.08.2014

Это из самой документации Docker, может помочь, просто и понятно:

«Каталог хоста по своей природе зависит от хоста. По этой причине вы не можете монтировать каталог хоста из Dockerfile, инструкция VOLUME не поддерживает передачу хост-каталога, потому что созданные образы должны быть переносимыми. Хост каталог не будет доступен на всех потенциальных хостах.».

person Nesa Mouzehkesh    schedule 11.04.2017

Если вы пришли сюда, потому что искали простой способ просматривать любые VOLUME:

  1. Узнайте имя тома с помощью docker volume list
  2. Завершите работу всех запущенных контейнеров, к которым подключен этот том.
  3. Беги docker run -it --rm --mount source=[NAME OF VOLUME],target=/volume busybox
  4. Оболочка откроется. cd /volume для ввода громкости.
person flix    schedule 22.10.2020