在Docker中将数据添加到现有命名卷的正确方法是什么?

Den*_*boy 64 docker

我以旧方式使用Docker,使用卷容器:

docker run -d --name jenkins-data jenkins:tag echo "data-only container for Jenkins"
Run Code Online (Sandbox Code Playgroud)

但现在我通过创建命名卷改为新方法:

 docker volume create --name my-jenkins-volume 
Run Code Online (Sandbox Code Playgroud)

我将这个新卷绑定到一个新的Jenkins容器.我唯一留下的是一个文件夹,其中/var/jenkins_home包含我以前的jenkins容器.(通过使用docker cp)现在我想用我的新命名卷填充该文件夹的内容.

我可以将该文件夹的内容复制到/var/lib/jenkins/volume/my-jenkins-volume/_data

lar*_*sks 106

您当然可以直接复制数据/var/lib/docker/volumes/my-jenkins-volume/_data,但通过这样做,您将:

  • 依靠对docker主机的物理访问.如果您正在与远程docker api进行交互,则此技术将不起作用.

  • 依赖于卷实现的特定方面,将来可能会发生变化,从而破坏您依赖它的任何流程.

我认为你最好依靠你可以通过命令行客户端使用docker api完成的事情.最简单的解决方案可能就是使用辅助容器,例如:

docker run -v my-jenkins-volume:/data --name helper busybox true
docker cp . helper:/data
docker rm helper
Run Code Online (Sandbox Code Playgroud)

  • 这个帮助程序容器永远不需要实际运行.简单地创建它就足够了,然后运行`docker cp`然后将其删除. (7认同)
  • 关于你的第二个子弹,你可以运行`docker volume inspect my-jenkins-volume --format'{{.Mountpoint}}'`以编程方式获取它的物理位置.尽管如此,仍然感觉不是一个好主意. (3认同)
  • 请注意,在使用[Mac的Docker](https://docs.docker.com/docker-for-mac/)时列出`/ var / lib / docker / volumes / my-jenkins-volume / _data`无效因为文件存储在[xhyve虚拟机](https://github.com/mist64/xhyve)内部。参见https://forums.docker.com/t/var-lib-docker-does-not-exist-on-host/18314 (3认同)
  • True 在这里解释 /sf/ask/2083356201/ (2认同)

hea*_*dab 20

您可以使用例如减少一行的接受答案

docker run --rm -v `pwd`:/src -v my-jenkins-volume:/data busybox cp -r /src /data
Run Code Online (Sandbox Code Playgroud)

  • `-v \`pwd\`:/src` 不暗示该命令正在主机上运行吗?(例如,如果主机是不同的机器,它如何映射 `pwd`?——它不能。)如果 docker 命令没有在主机上运行,​​这将不起作用。我相信这就是我们拥有 docker cp 的原因。这似乎不是 docker 的“方式”——它只是一种特殊情况,仅当 docker 命令在主机上运行时才有效。我理解正确吗? (4认同)

mai*_*mic 9

您可以将此 BASH 函数添加到您的文件中.bashrc,以将文件复制到现有的 Docker 卷,而无需运行容器

# Usage: copy-to-docker-volume SRC_PATH DEST_VOLUME_NAME [DEST_PATH]
copy-to-docker-volume() {
  SRC_PATH=$1
  DEST_VOLUME_NAME=$2
  DEST_PATH="${3:-}"
  # create smallest Docker image possible
  echo -e 'FROM scratch\nLABEL empty=""' | docker build -t empty -
  # create temporary container to be able to mount volume
  CONTAINER_ID=$(docker container create -v "${DEST_VOLUME_NAME}":/data empty cmd)
  # copy files to volume
  docker cp "${SRC_PATH}" "${CONTAINER_ID}":"/data/${DEST_PATH}"
  # remove temporary container
  docker rm "${CONTAINER_ID}"
}
Run Code Online (Sandbox Code Playgroud)

例子

# create volume as destination
docker volume create my-volume
# create directory to copy
mkdir my-dir
echo "hello file1" > my-dir/my-file-1
# copy directory to volume
copy-to-docker-volume my-dir my-volume
# list directory on volume
docker run --rm -it -v my-volume:/data busybox ls -la /data/my-dir
# show file content on volume
docker run --rm -it -v my-volume:/data busybox cat /data/my-dir/my-file-1

# create another file to copy
echo "hello file2" > my-file-2
# copy file to directory on volume
copy-to-docker-volume my-file-2 my-volume my-dir
# list (updated) directory on volume
docker run --rm -it -v my-volume:/data busybox ls -la /data/my-dir
# check volume content
docker run --rm -it -v my-volume:/data busybox cat /data/my-dir/my-file-2
Run Code Online (Sandbox Code Playgroud)


Dmy*_*huk 7

您无需启动某个容器即可将数据添加到已经存在的命名卷中,只需创建一个容器并在其中复制数据即可:

docker container create --name temp -v my-jenkins-volume:/data busybox
docker cp . temp:/data
docker rm temp
Run Code Online (Sandbox Code Playgroud)

  • 假设busybox的内容并不是真正需要的;你可以用 `hello-world` 来做到这一点,它也有效。`busybox` 是 1.22MB。相反,`hello-world` 是 13.3kB。问题是:就像我们从头开始创建 Dockerfile 一样,我们是否可以使用“无”作为映像来执行“docker 容器创建”,因为我们只想“挂载”卷而不启动容器? (7认同)
  • +1 这个解决方案在顶部投票,但“docker cp”的正确语法是“docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH” (2认同)
  • @XaviMontero 请参阅[我的答案](/sf/answers/4795812801/),了解使用大小为 0B 的 Docker 映像的解决方案。它与这个答案类似,但有点复杂,因为我使用的图像是在本地构建的。这个答案简单又开门见山。谢谢德米特罗·梅尔尼丘克 (2认同)

Nam*_*yev 6

以下是将~/data 的内容复制到名为my-vol 的docker 卷的步骤

步骤 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卷中。复制后退出临时容器。


mul*_*g0r 5

如果您不想创建 docker 并且可以以特权用户身份访问,只需执行以下操作(在 Linux 系统上):

docker volume create my_named_volume
sudo cp -p . /var/lib/docker/volumes/my_named_volume/_data/
Run Code Online (Sandbox Code Playgroud)

此外,它还允许您在 docker 运行时或停止 docker 容器时访问数据。


sha*_*359 5

如果您不想在 Windows docker 桌面上创建临时帮助程序容器(由 wsl2 支持),请将文件复制到以下位置

\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\my-volume\_data
Run Code Online (Sandbox Code Playgroud)

这里my-volume是您命名卷的名称。从文件资源管理器的地址栏中浏览上述路径。这是windows中wsl创建的内部网络。

在此输入图像描述

注意:使用larsks提到的 docker API 可能会更好,但我在 Windows 上没有遇到任何问题。

同样在linux上文件可以复制到

/var/lib/docker/volumes/my-volume/_data/
Run Code Online (Sandbox Code Playgroud)