Как правильно добавить данные в существующий именованный том в Docker?

88

Я использовал Docker по-старому, с контейнером тома:

docker run -d --name jenkins-data jenkins:tag echo "data-only container for Jenkins"

Но теперь я перешел на новый способ, создав именованный том:

 docker volume create --name my-jenkins-volume 

Я привязал этот новый том к новому контейнеру Jenkins. Единственное, что у меня осталось, - это папка, в которой /var/jenkins_homeхранится мой предыдущий контейнер jenkins. (с помощью docker cp) Теперь я хочу заполнить мой новый именованный том содержимым этой папки.

Могу я просто скопировать содержимое этой папки в /var/lib/jenkins/volume/my-jenkins-volume/_data?

DenCowboy
источник

Ответы:

134

Конечно, вы можете копировать данные напрямую /var/lib/docker/volumes/my-jenkins-volume/_data, но сделав это, вы:

  • Опираясь на физический доступ к хосту докеров. Этот метод не будет работать, если вы взаимодействуете с удаленным API-интерфейсом докеров.

  • Опора на конкретный аспект реализации тома может измениться в будущем, нарушив любые процессы, которые у вас есть, которые на него полагаются.

Я думаю, вам лучше полагаться на то, что вы можете выполнить с помощью docker api через клиент командной строки. Самое простое решение - использовать вспомогательный контейнер, например:

docker run -v my-jenkins-volume:/data --name helper busybox true
docker cp . helper:/data
docker rm helper
ларски
источник
3
Что касается второй пули, вы можете запустить ее программно, docker volume inspect my-jenkins-volume --format '{{.Mountpoint}}'чтобы узнать ее физическое местоположение. Тем не менее, это не кажется хорошей идеей.
c24w
8
Этот вспомогательный контейнер никогда не должен запускаться. Достаточно просто создать его, затем запустить, docker cpа затем удалить.
Alex
Вы не можете выполнить команду в этом контейнере, чтобы увидеть результаты или изменить файлы вручную.
CodeOrElse 01
3
Обратите внимание, что список /var/lib/docker/volumes/my-jenkins-volume/_dataпри использовании Docker для Mac не работает, потому что файлы хранятся внутри виртуальной машины xhyve . См. Forum.docker.com/t/var-lib-docker-does-not-exist-on-host/18314
Ортомала Локни
1
Истина объясняется здесь stackoverflow.com/questions/29762231/…
Zuabi
32

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

docker run --rm -v `pwd`:/src -v my-jenkins-volume:/data busybox cp -r /src /data
головной убор
источник
1
Мне интересно, может ли временный характер / tmp представлять риск того, что контейнер может удалить ваши данные до завершения cp? pathname.com/fhs/pub/fhs-2.3.html#TMPTEMPORARYFILES
чт
1
Ссылка на самом деле не проясняет время жизни файлов в / tmp. Я заявляю: «Программы не должны предполагать, что какие-либо файлы или каталоги в / tmp сохраняются между вызовами программы». что означает, что файлы выживут, но это гарантия. Параметр -v для docker создаст каталог в контейнере, если он не существует, поэтому изменение / tmp / src на / src будет работать, если вы беспокоитесь об этом потенциальном состоянии гонки. Я отредактирую ответ, чтобы отразить это, так как обратной стороны нет.
headdab
3
не -v `pwd`:/srcозначает ли это, что команда выполняется на хосте? (Как может карта хоста, pwdесли это, например, другая машина? - не может.) Если команда docker не запущена на хосте, это не сработает. Я считаю, что именно поэтому у нас есть docker cp. Похоже, что это не «путь» для докера - это просто особый случай, который работает только тогда, когда команда docker выполняется на хосте. Я правильно понял?
Wyck
Да, думаю, ты прав. pwdдолжен разрешиться в файл на хост-машине. Из документации по монтированию докеров: «В случае монтирования с привязкой первое поле - это путь к файлу или каталогу на хост-машине».
headdab 02
1
Следовательно, это не работает для копирования ваших локальных файлов в контейнер, если он находится на удаленном хосте, поскольку вы монтируете, pwdкоторый даже не должен существовать на удаленном хосте. Вместо этого решение Дмитрия Мельничука (create + cp + rm) копирует локальные в контейнер независимо от того, где он запущен.
Хави Монтеро
25

Вам не нужно запускать какой-либо контейнер для добавления данных в уже существующий именованный том, просто создайте контейнер и скопируйте туда данные:

docker container create --name temp -v my-jenkins-volume:/data busybox
docker cp . temp:/data
docker rm temp
Дмитрий Мельничук
источник
2
При условии, что содержимое busybox действительно не нужно; вы можете сделать это, hello-worldи это тоже работает. busyboxсоставляет 1,22 МБ. Вместо этого hello-world13,3 КБ. Возникает вопрос: можно ли создать Docker-файл с нуля, используя «ничего» в качестве образа, так же, как мы можем просто «смонтировать» том и никогда не запускать контейнер?
Хави Монтеро
1
+1 для этого решения поверх голосовала , но правильный синтаксис docker cpявляетсяdocker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
Marco Dufal
3

Вот шаги для копирования содержимого ~ / data в том докера с именем my-vol.

Шаг 1. Присоедините том к «временному» контейнеру. Для этого запустите в терминале эту команду:

docker run --rm -it --name alpine --mount type=volume,source=my-vol,target=/data alpine

Шаг 2. Скопируйте содержимое ~ / data в my-vol . Для этого запустите эти команды в новом окне терминала:

cd ~/data docker cp . alpine:/data

Это скопирует содержимое ~ / data в том my-vol . После копирования выйдите из временного контейнера.

Намик Гаджиев
источник