В вашем вопросе есть некоторые запутанные вещи, и, поскольку это не всегда интуитивно понятно, я постараюсь прояснить это на примере.
Примечания:
- Это небольшое учебное пособие, которое я написал о томах для моих сотрудников.В объяснениях должны быть некоторые недостатки, но все примеры были протестированы.
- важно, чтобы вы запускали вещи в следующем порядке, а не запускали команды повторно (потому что «новые» вещи могут затем стать «существующими»)и не соответствовал бы их назначению)
- Я подключусь к некоторому системному пути ... это только для примера: обеспечить их существование, а также избежать умножения предварительных команд создания.
Dockerfile
FROM ubuntu
VOLUME /tmp/dockerfilevolumefromnowhere
RUN mkdir -p /dir/created/from/container
RUN touch /dir/created/from/container/emptyFile.txt
VOLUME /dir/created/from/container
CMD "sh"
давайте удалим все данные предыдущих тестов
ВНИМАНИЕ, ЧТО ЭТО УДАЛЕТ ВСЕ ОБЪЕМЫ, КОТОРЫЕ НЕ ИСПОЛЬЗУЮТСЯвключая те, которые вы, возможно, создали ранее.
Если у вас есть какие-либо работающие контейнеры (особенно если они используют тома), остановите их для этих тестов.
root@host:~# docker container prune
root@host:~# docker volume prune
root@host:~# rm -r /does/not/exit/within/host
root@host:~# rm -r /does/not/exit/within/host2
root@host:~# rm -r /tmp/dockerfilevolumefromnowhere
некоторые изображения и создания томов и заполнения
root@host:~# docker build -t tmpcontainer .
root@host:~# docker volume create existingVolume
root@host:~# touch /var/lib/docker/volumes/existingVolume/_data/someExistingFile.txt
root@host:~# docker volume create existingVolume2
root@host:~# touch /var/lib/docker/volumes/existingVolume2/_data/anotherExistingFile.txt
root@host:~# docker volume create existingEmptyVolume
на данный момент у вас есть 3 "существующих тома":
root@host:~# docker volume ls
DRIVER VOLUME NAME
local existingVolume
local existingVolume2
local existingEmptyVolume
Давайте теперь запустим наш контейнер
docker run -it \
-v /does/not/exit/within/host:/does/not/exist/within/container \
-v /does/not/exit/within/host2:/sbin \
-v /tmp:/again/another/does/not/exist/within/container \
-v /tmp:/tmp/ \
-v newVolume:/another/does/not/exist/within/container \
-v newVolume2:/bin \
-v existingVolume:/new/path/on/container \
-v existingVolume2:/usr \
-v existingEmptyVolume:/var \
bash: groups: command not found # that's normal. you overrided the /usr... see beyond
Теперь мы подключены к нашему вновь созданному контейнеру.
Посмотрим, что у нас есть и на контейнере, и на хосте :
# -v /does/not/exit/within/host:/does/not/exist/within/container
#no one exists on both sides : both directories are created, and are now bound to each other
root@host:~# ll /does/not/exit/within/host
.
root@ffb82b56d64b:/# ll /does/not/exist/within/container
.
# -v /does/not/exit/within/host:/sbin
# the directory on host is created, and the one on container is erased with this new one. Both are now bound to each other
root@host:~# ll /does/not/exit/within/host2
.
root@ffb82b56d64b:/# ll /sbin
.
# -v /tmp:/again/another/does/not/exist/within/container
# the path on host exists, and the path on container will be created and will hold the content on container (they are bound to each other)
root@host:~# ll /tmp
-rw------- 1 root root 65536 Feb 19 11:11 one.txt
-rw------- 1 root root 65536 Feb 19 11:11 two.yml
root@ffb82b56d64b:/# ll /again/another/does/not/exist/within/container
-rw------- 1 root root 65536 Feb 19 11:11 one.txt
-rw------- 1 root root 65536 Feb 19 11:11 two.yml
# -v /tmp:/tmp
# the path on host exists, so all its content will replace the previously path on container
# there were some data on container's /tmp, but they are replaced with hosts ones
root@host:~# ll /tmp
-rw------- 1 root root 65536 Feb 19 11:11 one.txt
-rw------- 1 root root 65536 Feb 19 11:11 two.yml
root@ffb82b56d64b:/# ll /tmp
-rw------- 1 root root 65536 Feb 19 11:11 one.txt
-rw------- 1 root root 65536 Feb 19 11:11 two.yml
# -v newVolume:/another/does/not/exist/within/container \
# the newVolume does not exist, so it will be created and bound to path on container.
# since the path on container is new, it will be created empty
root@host:~# ll /var/lib/docker/volumes/newVolume/_data/
..
root@ffb82b56d64b:/# ll /another/does/not/exist/within/container
..
# -v newVolume2:/bin \
# once again, a volume will be created, but since it matches an existing path on container, it will hold all the content of it (no erasal!)
root@host:~# ll /var/lib/docker/volumes/newVolume2/_data/
<all the content of Ubuntu's /bin from within container>
root@ffb82b56d64b:/# ll /bin
<whole expected content of /bin on Ubuntu>
# -v existingVolume:/new/path/on/container \
# the volume exists, and it -and all files within- will be bound to a newly created path on container
root@host:~# ll /var/lib/docker/volumes/existingVolume/_data/
-rw------- 1 root root 65536 Feb 19 11:11 someExistingFile.txt
root@ffb82b56d64b:/# ll /new/path/on/container
-rw------- 1 root root 65536 Feb 19 11:11 someExistingFile.txt
# -v existingVolume2:/usr \
# the volume exists, so does the path on container. It will replace the existing path (and thus erase the former files there) and will be bound to this replaced path.
root@host:~# ll /var/lib/docker/volumes/existingVolume2/_data/
-rw------- 1 root root 65536 Feb 19 11:11 anotherExistingFile.txt
root@ffb82b56d64b:/# ll /usr
-rw------- 1 root root 65536 Feb 19 11:11 anotherExistingFile.txt
# -v existingEmptyVolume:/var \
# the volume exists, but is empty. the path on container exists in the container and is not empty. In this case, the path on container will not be erased and this will act as a new volume.
root@host:~# ll /var/lib/docker/volumes/existingEmptyVolume/_data/
drwxr-xr-x 2 root root 4096 Apr 24 2018 backups/
drwxr-xr-x 5 root root 4096 Feb 19 14:36 cache/
drwxr-xr-x 7 root root 4096 Feb 19 14:36 lib/
drwxrwsr-x 2 root staff 4096 Apr 24 2018 local/
lrwxrwxrwx 1 root root 9 Nov 12 21:54 lock -> /run/lock/
drwxr-xr-x 3 root root 4096 Feb 19 14:36 log/
drwxrwsr-x 2 root mail 4096 Nov 12 21:54 mail/
drwxr-xr-x 2 root root 4096 Nov 12 21:54 opt/
lrwxrwxrwx 1 root root 4 Nov 12 21:54 run -> /run/
drwxr-xr-x 2 root root 4096 Feb 19 14:36 spool/
drwxrwxrwt 2 root root 4096 Nov 12 21:56 tmp/
root@ffb82b56d64b:/# ll /var
drwxr-xr-x 2 root root 4096 Apr 24 2018 backups/
drwxr-xr-x 5 root root 4096 Feb 19 14:36 cache/
drwxr-xr-x 7 root root 4096 Feb 19 14:36 lib/
drwxrwsr-x 2 root staff 4096 Apr 24 2018 local/
lrwxrwxrwx 1 root root 9 Nov 12 21:54 lock -> /run/lock/
drwxr-xr-x 3 root root 4096 Feb 19 14:36 log/
drwxrwsr-x 2 root mail 4096 Nov 12 21:54 mail/
drwxr-xr-x 2 root root 4096 Nov 12 21:54 opt/
lrwxrwxrwx 1 root root 4 Nov 12 21:54 run -> /run/
drwxr-xr-x 2 root root 4096 Feb 19 14:36 spool/
drwxrwxrwt 2 root root 4096 Nov 12 21:56 tmp/
Обратите внимание, что теперь ранее существующий и вновь созданный том можно использовать для других контейнеров (так же, как вы только что использовали ранее существующие здесь выше).
В конце концов, все, что нам осталось, чтобы охватить все наши варианты использования, - это тома, созданные из Dockerfile .Давайте посмотрим на содержимое / var / lib / docker / volume.Помните, что мы очистили его перед выполнением наших тестов, поэтому все те, что здесь, соответствуют нашим тестам.
root@host:~# ll /var/lib/docker/volumes
drwx------ 6 root root 4096 Feb 19 11:11 ./
drwx--x--x 14 root root 4096 Feb 14 09:50 ../
-rw------- 1 root root 65536 Feb 19 14:36 metadata.db #indeed
drwxr-xr-x 3 root root 4096 Feb 19 14:36 635af95ec06f8a44c22915005189bfb12d5bcf2e5ac97c25112d3e65a72546f4/ # anonymous container 1
drwxr-xr-x 3 root root 4096 Feb 19 14:36 897b28ec17275a3c3be184bb20b6314b38c1404e638080c8fe4fc36cae2f9f65/ # anonymous container 2
drwxr-xr-x 3 root root 4096 Feb 19 14:36 existingEmptyVolume/ #we created it (empty) before the run command
drwxr-xr-x 3 root root 4096 Feb 19 14:35 existingVolume/ #we created it before the run command
drwxr-xr-x 3 root root 4096 Feb 19 14:36 existingVolume2/ #we created it before the run command
drwxr-xr-x 3 root root 4096 Feb 19 14:36 newVolume/ #we created it during run command
drwxr-xr-x 3 root root 4096 Feb 19 14:36 newVolume2/ #we created it during run command
Так что же это за анонимные контейнеры: на самом деле они созданы из вашего dockerfile.Давайте проверим их содержание.
root@host:~# ll /var/lib/docker/volumes/63eeedcb1aa2e4d8785cca409698371381558348ce19bc614d87da372901d224/_data/
-rw-r--r-- 1 root root 0 Feb 19 10:14 emptyFile.txt
root@host:~# ll /var/lib/docker/volumes/ea0ed5ff271cba03a8b7d35144b58e8da1b2e50b4e05c4cccda7f19b401d7f0b/_data/
..
Видите, они хранят все, что вы положили в них из файла Docker.Они являются анонимными, поэтому вы не можете (или фактически не должны) использовать их из других контейнеров, поскольку новые будут создаваться при каждом запуске контейнера из этого образа.
Примечание : выВозможно, в это время заметил какую-то странную вещь:
root@host:~# ll /tmp/dockerfilevolumefromnowhere #YES : from HOST!
.. #it exists... but is not linked to the volume or the path in container in any way.
Здесь ... не спрашивайте: меня все еще удивляет, почему он создан на хосте.Я предполагаю, что это ошибка, но эта проблема должна обсуждаться на докере ML, а не здесь.В любом случае, вы не должны делать это таким образом: mkdir перед созданием тома поверх него!
Итак, что мы можем увидеть со всеми этими примерами:
- связывание / монтирование с хостов путь к контейнеру (/ some / path / on / host: / a / path / on / container) создаст путь к контейнеру (независимо от того, существует ли он ранее) и заменитвсе прежние данные здесь.Обе директории (и их содержимое) теперь связаны друг с другом.
- монтирование из тома * * (someVolumeName: / a / path / on / container) к контейнеру привязывает том кпуть на контейнере.
- монтирование существующего непустого тома в путь контейнера заменит (возможное) содержимое внутри контейнера на содержимое из существующего тома (если оно пустое: оно будет действовать как новыйтом)
- монтирование нового тома к пути контейнера будет связывать содержимое пути в контейнере с томом.Том теперь будет содержать это содержимое (например, для последующего использования): здесь ничего не будет стерто / заменено.
- и том или путь (независимо от того, находится ли он в контейнере или хосте) будет создан , если он не существует.
- том из Dockerfile будет анонимным и будет создаваться заново при каждом запуске другого контейнера из этого образа (предыдущие останутся).Они также будут созданы в / var / lib / docker / volume.
- том, объявленный при запуске команда будет создана (т.е. будет "новыми" томами), если они не существовали ранее.В противном случае вместо них будут использоваться существующие.
- том, созданный с помощью команды запуска , будет сохранен в / var / lib / docker / volume в каталоге, соответствующем их имени.
Примечание: , что я не говорю здесь о правах собственности и правах.Намеренно: это другой вопрос, который мы можем обсудить позже.