如Working with Volumes上的Docker文档中所述,有一个所谓的仅数据容器的概念,它提供了一个可以挂载到多个其他容器中的卷,无论数据专用容器是否实际运行。
基本上,这听起来很棒。但有一件事我不明白。
由于Docker在主机上的某个内部文件夹中创建并管理这些卷(由于可移植性原因而不显式映射到主机上的文件夹)({{1> }})。
假设我使用这样的卷,然后我需要将它从一个主机迁移到另一个主机 - 如何移植卷? AFAICS它有一个唯一的ID - 我可以将卷及其仅数据容器复制到新主机吗?如何找出要复制的文件?或者是否有一些内置于Docker的支持我还没有发现?
答案 0 :(得分:111)
官方答案现已公布:
Sharing Directories using Volumes
在"备份,还原或迁移数据卷"你有这个部分:
<强> BACKUP:强>
sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
--rm
:退出时移除容器--volumes-from DATA
:附加到DATA容器共享的卷-v $(pwd):/backup
:bind将当前目录挂载到容器中;将tar文件写入busybox
:一个简单的小图片 - 适合快速维护tar cvf /backup/backup.tar /data
:创建/ data目录中所有文件的未压缩tar文件<强> RESTORE:强>
# create a new data container
$ sudo docker create -v /data --name DATA2 busybox true
# untar the backup files into the new container᾿s data volume
$ sudo docker run --rm --volumes-from DATA2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
data/
data/sven.txt
# compare to the original container
$ sudo docker run --rm --volumes-from DATA -v `pwd`:/backup busybox ls /data
sven.txt
答案 1 :(得分:15)
您可以将卷导出到tar并转移到另一台计算机。并在第二台机器上使用tar导入数据。这不依赖于卷的实现细节。
# you can list shared directories of the data container
docker inspect <data container> | grep "/vfs/dir/"
# you can export data container directory to tgz
docker run --cidfile=id.tmp --volumes-from <data container> ubuntu tar -cO <volume path> | gzip -c > volume.tgz
# clean up: remove exited container used for export and temporary file
docker rm `cat id.tmp` && rm -f id.tmp
答案 2 :(得分:13)
从Docker docs和top answer here扩展官方答案,您可以在.bashrc或.zshrc中使用以下别名
# backup files from a docker volume into /tmp/backup.tar.gz
function docker-volume-backup-compressed() {
docker run --rm -v /tmp:/backup --volumes-from "$1" debian:jessie tar -czvf /backup/backup.tar.gz "${@:2}"
}
# restore files from /tmp/backup.tar.gz into a docker volume
function docker-volume-restore-compressed() {
docker run --rm -v /tmp:/backup --volumes-from "$1" debian:jessie tar -xzvf /backup/backup.tar.gz "${@:2}"
echo "Double checking files..."
docker run --rm -v /tmp:/backup --volumes-from "$1" debian:jessie ls -lh "${@:2}"
}
# backup files from a docker volume into /tmp/backup.tar
function docker-volume-backup() {
docker run --rm -v /tmp:/backup --volumes-from "$1" busybox tar -cvf /backup/backup.tar "${@:2}"
}
# restore files from /tmp/backup.tar into a docker volume
function docker-volume-restore() {
docker run --rm -v /tmp:/backup --volumes-from "$1" busybox tar -xvf /backup/backup.tar "${@:2}"
echo "Double checking files..."
docker run --rm -v /tmp:/backup --volumes-from "$1" busybox ls -lh "${@:2}"
}
请注意,备份会保存到/tmp
,因此您可以移动保存在Docker主机之间的备份文件。
还有两对备份/恢复别名。一个使用压缩和debian:jessie和其他没有压缩但使用busybox。如果要备份的文件很大,请使用压缩。
答案 3 :(得分:2)
如果可以在机器之间建立 SSH 连接,这里是一个单行:
docker run --rm -v <SOURCE_DATA_VOLUME_NAME>:/from alpine ash -c "cd /from ; tar -cf - . " | ssh <TARGET_HOST> 'docker run --rm -i -v <TARGET_DATA_VOLUME_NAME>:/to alpine ash -c "cd /to ; tar -xpvf - " '
感谢 Guido Diepen 的 post。
答案 4 :(得分:1)
我将在IBM添加另一个最近的工具,它实际上是为从一个容器主机到另一个容器主机的卷迁移而创建的。这是一个目前正在进行的项目。因此,您可能会在将来找到具有其他功能的其他版本。
开发货物是为了将容器从一个主机迁移到另一个主机及其数据,同时将停机时间降至最低。 Cargo使用联合文件系统的数据联合功能,在源主机和目标主机上创建统一的数据视图(主要是根文件系统)。这允许Cargo在目标主机上几乎立即(在几毫秒内)启动容器,因为来自源根文件系统的数据被按需复制到目标主机(使用写时复制(COW)< / strong>分区)或懒惰地在后台(使用rsync)。
重点是:
- centralized
服务器处理迁移过程
这里给出了项目的链接:
https://github.com/nadgowdas/cargo
答案 5 :(得分:1)
如果您的计算机位于不同的VPC中,或者要从本地计算机复制到本地计算机(例如,对于我的情况),则可以使用我创建的dvsync。它基本上是ngrok与rsync
结合在SSH上,打包成两个小映像(均为约25MB)。首先,在要复制数据的机器上启动dvsync-server
(您需要NGROK_AUTHTOKEN
,可以从ngrok dashboard获得):
$ docker run --rm -e NGROK_AUTHTOKEN="$NGROK_AUTHTOKEN" \
--mount source=MY_VOLUME,target=/data,readonly \
quay.io/suda/dvsync-server
然后,您可以在要将文件复制到的机器上启动dvsync-client
,并传递服务器显示的DVSYNC_TOKEN
:
docker run -e DVSYNC_TOKEN="$DVSYNC_TOKEN" \
--mount source=MY_TARGET_VOLUME,target=/data \
quay.io/suda/dvsync-client
一旦复制完成,客户端将退出。这也适用于Docker CLI,Compose,Swarm和Kubernetes。
答案 6 :(得分:0)
改编自已接受的答案,但提供了更大的灵活性,您可以在 bash 管道中使用它:
#!/bin/bash
if [ $# != 2 ]; then
echo Usage "$0": volume /path/of/the/dir/in/volume/to/backup
exit 1
fi
if [ -t 1 ]; then
echo The output of the cmd is binary data "(tar)", \
and it should be redirected instead of printed to terminal
exit 1
fi
volume="$1"
path="$2"
exec docker run --rm --mount type=volume,src="$volume",dst=/mnt/volume/ alpine tar cf - . -C /mnt/volume/"$path"
如果您想定期和增量备份卷,那么您可以使用以下脚本:
#!/bin/bash
if [ $# != 3 ]; then
echo Usage "$0": volume /path/of/the/dir/in/volume/to/backup /path/to/put/backup
exit 1
fi
volume="$1"
volume_path="$2"
path="$3"
if [[ "$path" =~ ^.*/$ ]]; then
echo "The 3rd argument shouldn't end in '/', otherwise rsync would not behave as expected"
exit 1
fi
container_name="docker-backup-rsync-service-$RANDOM"
docker run --rm --name="$container_name" -d -p 8738:873 \
--mount type=volume,src="$volume",dst=/mnt/volume/ \
nobodyxu/rsyncd
echo -e '\nStarting syncing...'
rsync --info=progress2,stats,symsafe -aHAX --delete \
"rsync://localhost:8738/root/mnt/volume/$volume_path/" "$path"
exit_status=$?
echo -e '\nStopping the rsyncd docker...'
docker stop -t 1 "$container_name"
exit $exit_status
它利用 rsync
的服务器和客户端功能直接同步卷和主机目录之间的目录。