тома для установки докеров на хосте

135

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

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

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

VOLUME /path

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

Джефф Стори
источник

Ответы:

155

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

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

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

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

Пример:

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

А потом,

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

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

Крис МакКиннел
источник
12
Что произойдет, если я использую -v для каталога, который уже был указан в VOLUME?
Джефф Стори,
6
--volumes-fromустановит вас VOLUMEповерх всего, что вы укажете -v. Интересно, что похоже, что запуск контейнера в привилегированном режиме ( docker run --privileged) и umounting /var/lib/mysqlпросто оставит пустой каталог, поэтому ваше -vмонтирование полностью игнорируется, когда оно конфликтует с файлом VOLUME.
Крис МакКиннел
2
Вы говорите, что тома хранятся до тех пор, пока на них ссылается контейнер, и я видел это в другом месте. В docs.docker.com/userguide/dockervolumes говорится: «Тома данных предназначены для хранения данных независимо от жизненного цикла контейнера. Поэтому Docker никогда не удаляет тома автоматически, когда вы удаляете контейнер, и он не будет« собирать мусор »тома, которые больше не являются на который ссылается контейнер ". Одно из этих утверждений должно быть неверным.
mc0e
1
Файлы, находящиеся в томе, хранятся на диске, когда контейнер больше не ссылается на него, но сам том больше не может использоваться (если вы точно не знаете, как вручную подключить том к контейнеру, но даже тогда я не не знаю, возможно ли это). Когда я говорю, что больше нельзя использовать, я имею в виду, что вы не можете использовать --volumes-from, чтобы использовать его. Когда они говорят выше «сборщик мусора», они имеют в виду удаление файлов с вашего диска, которые были в томе.
Крис МакКиннел
1
Их можно использовать с -v, но не с -volumes-from. Volumes-from принимает имя контейнера для извлечения данных тома (я считаю, что для этого нужны ВСЕ точки объема). Однако для самой -v в руководстве упоминается, что вы можете предоставить именованный том для -v в форме named-volume:/path/in/container. Безымянным томам присваиваются хэши для имен, и эти хэши могут быть предоставлены вместо пути к хосту для доступа к потерянным томам. :) Учтите, volume lsможет не все показать - docker volume ls -f dangling=trueтоже попробуйте .
Jasmine Hegman
44

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

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

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

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

# 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
Тобия
источник
Что делать, если хост-докер запущен на виртуальной машине? Например, boot2docker на Mac. Тогда эти тома доступны только удаленно. Кроме того, при использовании томов в Dockerfile, как вы описали, содержимое образа будет скопировано на том. Однако при монтировании в локальный каталог этого копирования не происходит. Вы знаете, почему это так? Есть ли способ иметь локально смонтированный том, но при этом «начать все заново» с файлами из образа?
LostSalad
4
с docker-compose вы можете именно это сделать, смонтировать том в определенном месте операционной системы хоста . Никаких символических ссылок не требуется ...
Хьюго Купманс,
@Tobia: пример docker-compose см. В документации docs.docker.com/compose/compose-file/…
Хьюго Купманс,
11

ОБЪЕМ используется 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

Теперь запустите другой контейнер с опцией volume-from как (say-container2)

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

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

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

Йогеш Джилхавар
источник
8

В принципе 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и -voption заключается в том, что вы можете -vдинамически использовать option при запуске контейнера. Это означает, что вы можете монтировать какой-либо каталог динамически. И еще одно отличие состоит в том, что вы можете смонтировать каталог хоста в контейнере, используя-v

nacyot
источник
8

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

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

Vennesa
источник