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

我以旧的方式使用 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。(使用 docker cp) 现在我想用该文件夹的内容填充我的新命名卷。

我能把那个文件夹的内容复制到 /var/lib/jenkins/volume/my-jenkins-volume/_data吗?

111228 次浏览

你的 可以当然可以直接把数据复制到 /var/lib/docker/volumes/my-jenkins-volume/_data,但是这样做你就是:

  • 依赖于对 Docker 主机的物理访问。如果您正在与一个远程的 docker API 交互,那么这种技术将无法工作。

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

我认为您最好还是依赖于通过命令行客户端使用 docker API 可以完成的事情。最简单的解决方案可能就是使用一个 helper 容器,比如:

docker run -v my-jenkins-volume:/data --name helper busybox true
docker cp . helper:/data
docker rm helper

你可以把已接受的答案缩减为一行,例如。

docker run --rm -v `pwd`:/src -v my-jenkins-volume:/data busybox cp -r /src /data

您不需要启动某个容器将数据添加到已有的命名卷中,只需创建一个容器并在其中复制数据:

docker container create --name temp -v my-jenkins-volume:/data busybox
docker cp . temp:/data
docker rm temp

下面是将 数据的内容复制到名为 My-vol的 Docker 卷的步骤

步骤1。将卷附加到一个“临时”容器上。对于在终端中运行的容器,下面的命令是:

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

步骤2。将 数据的内容复制到 My-vol。在新的终端窗口中运行以下命令:

Cd ~/data 高山码头:/data

这将把 数据的内容复制到 My-vol卷中。复制后退出临时容器。

如果您不想创建 docker,并且您可以作为特权用户访问,那么只需(在 Linux 系统上)这样做:

docker volume create my_named_volume
sudo cp -p . /var/lib/docker/volumes/my_named_volume/_data/

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

您可以将这个 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 my-volume:/data empty cmd)
# copy files to volume
docker cp "${SRC_PATH}" "${CONTAINER_ID}":"/data/${DEST_PATH}"
# remove temporary container
docker rm "${CONTAINER_ID}"
}

例子

# 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

如果您不想在 windows docker 桌面(由 wsl2支持)上创建临时助手容器,那么 将文件复制到下面的位置

\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\my-volume\_data

这里的 我的音量是您的命名卷的名称。在文件资源管理器中从地址栏浏览上面的路径。这是 wsl 在 windows 中创建的内部网络。

enter image description here

注意: 像 云雀提到的那样使用 docker API 可能更好,但是我在 windows 上没有遇到任何问题。

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

/var/lib/docker/volumes/my-volume/_data/