我一直在使用这个 Docker-image tutum/wordpress来演示一个 Wordpress 网站。最近我发现该图像使用卷来存储 MySQL 数据。
所以问题是这样的:如果我想备份和恢复容器,我可以尝试提交一个镜像,然后删除容器,并从提交的镜像创建一个新容器。但是,如果我这样做,该卷将被删除,并且我的所有数据都将消失。
必须有一些简单的方法来备份我的容器及其卷数据,但我在任何地方都找不到它。
我一直在使用这个 Docker-image tutum/wordpress来演示一个 Wordpress 网站。最近我发现该图像使用卷来存储 MySQL 数据。
所以问题是这样的:如果我想备份和恢复容器,我可以尝试提交一个镜像,然后删除容器,并从提交的镜像创建一个新容器。但是,如果我这样做,该卷将被删除,并且我的所有数据都将消失。
必须有一些简单的方法来备份我的容器及其卷数据,但我在任何地方都找不到它。
如果我想恢复容器,我可以尝试提交一个图像,然后删除容器,并从提交的图像创建一个新容器。但是,如果我这样做,该卷将被删除并且我的所有数据都消失了
正如 docker 用户指南所解释的,数据卷旨在将数据保存在容器文件系统之外。这也简化了多个容器之间的数据共享。
虽然 Docker 永远不会删除卷中的数据(除非您使用 删除关联的容器docker rm -v
),但未被任何 docker 容器引用的卷称为悬空卷。那些悬空的卷很难摆脱也很难访问。
这意味着一旦使用卷的最后一个容器被删除,数据卷就会变得悬空并且其内容难以访问。
为了防止那些悬空的卷,诀窍是使用要保留的数据卷创建一个额外的 docker 容器,以便始终至少有该 docker 容器引用该卷。这样,您可以删除运行 wordpress 应用程序的 docker 容器,而不会失去访问该数据卷内容的便利性。
这样的容器称为数据卷容器。
必须有一些简单的方法来备份我的容器和卷数据,但我在任何地方都找不到。
要备份 docker 映像,请使用docker save命令,该命令将生成一个 tar 存档,以后可以使用docker load命令创建新的 docker 映像。
您可以通过不同的方式备份 docker 容器
请注意,这些命令只会备份 docker 容器分层文件系统。这不包括数据量。
要备份数据卷,您可以使用要备份的卷运行新容器并执行 tar 命令以生成卷内容的存档,如docker 用户指南中所述。
在您的特定情况下,数据卷用于存储 MySQL 服务器的数据。因此,如果要为此卷导出 tar 存档,则需要先停止 MySQL 服务器。为此,您必须停止 wordpress 容器。
另一种方法是远程连接到 MySQL 服务器以使用mysqldump命令生成数据库转储。但是,为了使其工作,您的 MySQL 服务器必须配置为接受远程连接,并且还有一个允许远程连接的用户。您正在使用的 wordpress docker 映像可能不是这种情况。
Docker 最近引入了Docker 卷插件,允许将卷的处理委托给供应商实现的插件。
该docker run
命令具有该-v
选项的新行为。现在可以给它传递一个卷名。以这种方式创建的卷被命名并且以后易于引用,从而缓解了悬空卷的问题。
Docker 引入了docker volume prune
轻松删除所有悬空卷的命令。
更新 2
原始单卷备份 bash 脚本:
#!/bin/bash
# This script allows you to backup a single volume from a container
# Data in given volume is saved in the current directory in a tar archive.
CONTAINER_NAME=$1
VOLUME_NAME=$2
usage() {
echo "Usage: $0 [container name] [volume name]"
exit 1
}
if [ -z $CONTAINER_NAME ]
then
echo "Error: missing container name parameter."
usage
fi
if [ -z $VOLUME_NAME ]
then
echo "Error: missing volume name parameter."
usage
fi
sudo docker run --rm --volumes-from $CONTAINER_NAME -v $(pwd):/backup busybox tar cvf /backup/backup.tar $VOLUME_NAME
原始单卷还原 bash 脚本:
#!/bin/bash
# This script allows you to restore a single volume from a container
# Data in restored in volume with same backupped path
NEW_CONTAINER_NAME=$1
usage() {
echo "Usage: $0 [container name]"
exit 1
}
if [ -z $NEW_CONTAINER_NAME ]
then
echo "Error: missing container name parameter."
usage
fi
sudo docker run --rm --volumes-from $NEW_CONTAINER_NAME -v $(pwd):/backup busybox tar xvf /backup/backup.tar
用法可以是这样的:
$ volume_backup.sh old_container /srv/www
$ sudo docker stop old_container && sudo docker rm old_container
$ sudo docker run -d --name new_container myrepo/new_container
$ volume_restore.sh new_container
假设是:备份文件名为backup.tar,它与备份和恢复脚本位于同一目录,容器之间的卷名相同。
更新
在我看来,从容器备份卷与从数据容器备份卷没有什么不同。
卷只不过是链接到容器的路径,因此过程是相同的。
我不知道 docker-backup 是否也适用于相同的容器卷,但您可以使用:
sudo docker run --rm --volumes-from yourcontainer -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
和:
sudo docker run --rm --volumes-from yournewcontainer -v $(pwd):/backup busybox tar xvf /backup/backup.tar
结束更新
有一个不错的工具可以让你备份和恢复 docker 卷容器:
https://github.com/discordianfish/docker-backup
如果您有一个容器链接到一些容器卷,如下所示:
$ docker run --volumes-from=my-data-container --name my-server ...
您可以像这样备份所有卷:
$ docker-backup store my-server-backup.tar my-server
并像这样恢复:
$ docker-backup restore my-server-backup.tar
或者你可以按照官方的方式:
如果您的项目使用 docker-compose,这里有一种备份和恢复卷的方法。
基本上,您将服务添加db-backup
到db-restore
您的 docker-compose.yml 文件中,并根据您的卷名称对其进行调整。dbdata
我的卷在此示例中命名。
version: "3"
services:
db:
image: percona:5.7
volumes:
- dbdata:/var/lib/mysql
db-backup:
image: alpine
tty: false
environment:
- TARGET=dbdata
volumes:
- ./backup:/backup
- dbdata:/volume
command: sh -c "tar -cjf /backup/$${TARGET}.tar.bz2 -C /volume ./"
db-restore:
image: alpine
environment:
- SOURCE=dbdata
volumes:
- ./backup:/backup
- dbdata:/volume
command: sh -c "rm -rf /volume/* /volume/..?* /volume/.[!.]* ; tar -C /volume/ -xjf /backup/$${SOURCE}.tar.bz2"
为了数据一致性,在备份或恢复之前停止你的数据库容器
docker-compose stop db
要备份到默认目标 ( backup/dbdata.tar.bz2
):
docker-compose run --rm db-backup
或者,如果要指定备用目标名称,请执行以下操作:
docker-compose run --rm -e TARGET=mybackup db-backup
要从 恢复backup/dbdata.tar.bz2
,请执行以下操作:
docker-compose run --rm db-restore
或使用以下命令从特定文件恢复:
docker-compose run --rm -e SOURCE=mybackup db-restore
我改编了来自https://loomchild.net/2017/03/26/backup-restore-docker-named-volumes/的命令来创建这种方法。
如果您只需要备份已安装的卷,您可以从Dockerhost复制文件夹。
注意:如果你在Ubuntu上,Dockerhost是你的本地机器。如果你在Mac上,Dockerhost就是你的虚拟机。
在 Ubuntu 上
您可以在此处找到所有带有卷的文件夹:/var/lib/docker/volumes/
因此您可以将它们复制并存档到任何您想要的地方。
在 MAC 上
这不像在 Ubuntu 上那么容易。您需要从 VM 复制文件。
这是一个脚本,说明如何将所有带有卷的文件夹从虚拟机(运行 Docker 服务器的位置)复制到本地计算机。我们假设您的 docker-machine VM 名为default。
docker-machine ssh default sudo cp -v -R /var/lib/docker/volumes/ /home/docker/volumes
docker-machine ssh default sudo chmod -R 777 /home/docker/volumes
docker-machine scp -R default:/home/docker/volumes ./backup_volumes
docker-machine ssh default sudo rm -r /home/docker/volumes
它将在当前目录中创建一个文件夹./backup_volumes并将所有卷复制到此文件夹。
这是如何将所有保存的卷从本地目录(./backup_volumes)复制到 Dockerhost 机器的脚本
docker-machine scp -r ./backup_volumes default:/home/docker
docker-machine ssh default sudo mv -f /home/docker/backup_volumes /home/docker/volumes
docker-machine ssh default sudo chmod -R 777 /home/docker/volumes
docker-machine ssh default sudo cp -v -R /home/docker/volumes /var/lib/docker/
docker-machine ssh default sudo rm -r /home/docker/volumes
现在您可以通过以下方式检查它是否有效:
docker volume ls
假设您的卷名是data_volume
. 您可以使用以下命令在名为 的 docker 映像之间备份和恢复卷data_image
:
备份:
docker run --rm --mount source=data_volume,destination=/data alpine tar -c -f- data | docker run -i --name data_container alpine tar -x -f-
docker container commit data_container data_image
docker rm data_container
恢复:
docker run --rm data_image tar -c -f- data | docker run -i --rm --mount source=data_volume,destination=/data alpine tar -x -f-
我知道这是旧的,但我意识到没有一个有据可查的解决方案将数据容器(作为备份)推送到 docker hub。我刚刚在 https://dzone.com/articles/docker-backup-your-data-volumes-to-docker-hub上发布了一个关于如何执行此操作的简短示例
以下是底线
docker 教程建议您可以在本地备份和恢复数据卷。我们将使用这种技术,再添加几行以将此备份推送到 docker hub 中,以便将来轻松恢复到我们想要的任何位置。那么,让我们开始吧。这些是要遵循的步骤:
从名为 data-container-to-backup 的数据容器备份数据卷
docker run --rm --volumes-from data-container-backup --name tmp-backup -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /folderToBackup
将此 tar 文件展开到一个新容器中,以便我们可以将其作为其映像的一部分提交
docker run -d -v $(pwd):/backup --name data-backup ubuntu /bin/sh -c "cd / && tar xvf /backup/backup.tar"
提交并推送带有所需标签 ($VERSION) 的图像
docker commit data-backup repo/data-backup:$VERSION
docker push repo/data-backup:$VERSION
最后,让我们清理
docker rm data-backup
docker rmi $(docker images -f "dangling=true" -q)
现在我们的 repo 中有一个名为 data-backup 的图像,它只是一个带有备份文件和文件夹的文件系统。为了使用这个图像(也就是从备份中恢复),我们执行以下操作:
使用数据备份映像运行数据容器
run -v /folderToBackup --entrypoint "bin/sh" --name data-container repo/data-backup:${VERSION}
使用数据容器中的卷运行您的 whatEver 映像
docker run --volumes-from=data-container repo/whatEver
而已。
我很惊讶没有关于这项工作的文档。我希望有人觉得这很有帮助。我知道我花了一段时间才考虑到这一点。
以下命令将在安装了所有命名数据卷的容器中运行 tar,并将输出重定向到文件中:
docker run --rm `docker volume list -q | egrep -v '^.{64}$' | awk '{print "-v " $1 ":/mnt/" $1}'` alpine tar -C /mnt -cj . > data-volumes.tar.bz2
确保测试生成的存档以防出现问题:
tar -tjf data-volumes.tar.bz2
如果你只需要一个简单的存档备份,你可以试试我的小工具:https ://github.com/loomchild/volume-backup
例子
备份:
docker run -v some_volume:/volume -v /tmp:/backup --rm loomchild/volume-backup backup archive1
将归档卷命名some_volume
为/tmp/archive1.tar.bz2
归档文件
恢复:
docker run -v some_volume:/volume -v /tmp:/backup --rm loomchild/volume-backup restore archive1
将擦除并恢复some_volume
从/tmp/archive1.tar.bz2
存档文件命名的卷。
更多信息:https ://medium.com/@loomchild/backup-restore-docker-named-volumes-350397b8e362
我创建了一个工具来编排和启动数据和 mysql 容器的备份,简称为docker-backup。docker hub 上甚至还有一个现成的镜像。
它主要是用 Bash 编写的,因为它主要是编排。它duplicity
用于实际的备份引擎。您目前可以备份到 FTP(S) 和 Amazon S3。
配置非常简单:在 YAML 中编写一个配置文件,描述要备份的内容和位置,然后就可以了!
对于数据容器,它会自动挂载你的容器共享的卷来备份和处理它。对于 mysql 容器,它会链接它们并执行与您的容器捆绑在一起的 mysqldump 并处理结果。
我写它是因为我使用了 Docker-Cloud,它与最近的 docker-engine 版本不是最新的,并且因为我想通过在我的应用程序容器中不包含任何备份过程来拥抱 Docker 方式。
如果您想要一个完整的备份,您将需要执行几个步骤:
请注意,仅将容器 Docker 提交到映像不包括附加到容器的卷(参考:Docker 提交文档)。
"提交操作将不包括安装在容器内的卷中包含的任何数据。 "
我们可以使用图像来备份我们所有的卷。我写了一个脚本来帮助备份和恢复。此外,我将数据保存到 tar 文件压缩中,以将所有数据保存在本地磁盘上。我使用这个脚本将我的 Postgres 和 Cassandra 卷数据库保存在同一个图像中。例如,如果我们有一个用于 Postgres 的 pg_data 和一个用于 Cassandra 数据库的 cassandra_data 我们可以使用 pg_data 参数和 Cassandra 的 cassandra_data 参数调用以下脚本两次
备份脚本:
#! /bin/bash
GENERATE_IMAGE="data_image"
TEMPRORY_CONTAINER_NAME="data_container"
VOLUME_TO_BACKUP=${1}
RANDOM=$(head -200 /dev/urandom | cksum | cut -f1 -d " ")
if docker images | grep -q ${GENERATE_IMAGE}; then
docker run --rm --mount source=${VOLUME_TO_BACKUP},destination=/${VOLUME_TO_BACKUP} ${GENERATE_IMAGE} tar -c -f- ${VOLUME_TO_BACKUP} | docker run -i --name ${TEMPRORY_CONTAINER_NAME} ${GENERATE_IMAGE} tar -x -f-
else
docker run --rm --mount source=${VOLUME_TO_BACKUP},destination=/${VOLUME_TO_BACKUP} alpine tar -c -f- ${VOLUME_TO_BACKUP} | docker run -i --name ${TEMPRORY_CONTAINER_NAME} alpine tar -x -f-
fi
docker container commit ${TEMPRORY_CONTAINER_NAME} ${GENERATE_IMAGE}
docker rm ${TEMPRORY_CONTAINER_NAME}
if [ -f "$(pwd)/backup/${VOLUME_TO_BACKUP}.tar" ]; then
docker run --rm -v $(pwd)/backup:/backup ${GENERATE_IMAGE} tar cvf /backup/${VOLUME_TO_BACKUP}_${RANDOM}.tar /${VOLUME_TO_BACKUP}
else
docker run --rm -v $(pwd)/backup:/backup ${GENERATE_IMAGE} tar cvf /backup/${VOLUME_TO_BACKUP}.tar /${VOLUME_TO_BACKUP}
fi
例子:
恢复脚本:
#! /bin/bash
GENERATE_IMAGE="data_image"
TEMPRORY_CONTAINER_NAME="data_container"
VOLUME_TO_RESTORE=${1}
docker run --rm ${GENERATE_IMAGE} tar -c -f- ${VOLUME_TO_RESTORE} | docker run -i --rm --mount source=${VOLUME_TO_RESTORE},destination=/${VOLUME_TO_RESTORE} alpine tar -x -f-
例子:
问题:你想用其中的数据卷备份你的镜像容器,但是这个选项不是开箱即用的,直接而简单的方法是复制卷路径并备份 docker 镜像'重新加载并链接它两者一起。但这个解决方案似乎很笨拙,不可持续和可维护 - 您需要创建一个 cron 作业,每次都会使这个流程。
解决方案:使用dockup - Docker 映像备份您的Docker 容器卷并将其上传到s3 (Docker + Backup = dockup)。dockup 将使用您的 AWS 凭证根据环境变量创建一个具有名称的新存储桶,获取配置的卷,并将被压缩、压缩、加时间戳并上传到 S3 存储桶。
步骤:
docker-compose.yml
并附加env.txt
配置文件,数据应上传到专用的安全 s3 存储桶,并准备好在 DRP 执行时重新加载。为了验证要配置docker inspect <service-name>
的卷路径运行并找到卷:“卷”:{“/etc/service-example”:{},“/service-example”:{}},
编辑配置文件的内容,env.txt
放到项目路径下:
AWS_ACCESS_KEY_ID=<key_here>
AWS_SECRET_ACCESS_KEY=<secret_here>
AWS_DEFAULT_REGION=us-east-1
BACKUP_NAME=service-backup
PATHS_TO_BACKUP=/etc/service-example /service-example
S3_BUCKET_NAME=docker-backups.example.com
RESTORE=false
运行停靠容器
$ docker run --rm \ --env-file env.txt \ --volumes-from <service-name> \ --name dockup tutum/dockup:latest
如果您喜欢从命令行输入奥术运算符,您会喜欢这些手动容器备份技术。请记住,有一种更快、更有效的方法来备份同样有效的容器。我在这里写了说明:https: //www.morpheusdata.com/blog/2017-03-02-how-to-create-a-docker-backup-with-morpheus
第 1 步:将 Docker 主机添加到任何云 正如 Morpheus 支持站点上的教程中所述,您可以在几秒钟内将 Docker 主机添加到您选择的云中。首先在 Morpheus 主导航栏上选择 Infrastructure。在 Infrastructure 窗口顶部选择 Hosts,然后单击右上角的“+Container Hosts”按钮。
要通过 Morpheus 将 Docker 主机备份到云,请导航到 Infrastructure 屏幕并打开“+Container Hosts”菜单。
在菜单上选择容器主机类型,选择一个组,然后在五个字段中输入数据:名称、描述、可见性、选择云和输入标签(可选)。单击下一步,然后通过选择服务计划来配置主机选项。请注意,仅当您选择的计划启用了自定义选项时,卷、内存和 CPU 计数字段才可见。
您可以在此处添加和调整卷大小、设置内存大小和 CPU 数量以及选择网络。您还可以配置操作系统用户名和密码、域名和主机名,默认情况下是您之前输入的容器名称。单击下一步,然后添加任何自动化工作流(可选)。最后,检查您的设置并单击完成以保存它们。
第 2 步:将 Docker Registry 集成添加到公共或私有云 Adam Hicks 在另一个 Morpheus 教程中描述了与私有 Docker Registry 集成是多么简单。(使用 Morpheus 使用公共 Docker API 使用 Docker 的公共集线器供应图像不需要额外的配置。)
在主导航栏的管理选项卡下选择集成,然后选择屏幕右侧的“+新集成”按钮。在出现的 Integration 窗口中,在 Type 下拉菜单中选择 Docker Repository,输入名称并添加私有注册表 API 端点。为您正在使用的注册表提供用户名和密码,然后单击保存更改按钮。
通过 Morpheus“新集成”对话框将 Docker Registry 与私有云集成。
要配置您刚刚创建的集成,请在 Create Instance 对话框中的 Type 下选择 Docker,在 Configure 选项卡下的 Docker Registry 下拉菜单中选择注册表,然后像任何 Docker 容器一样继续配置。
第 3 步:管理备份 添加 Docker 主机并集成注册表后,将为您配置的每个实例自动配置和执行备份。Morpheus 支持提供有关查看备份、创建实例备份和创建服务器备份的说明。
如果您有像我这样简单的案例,您可以执行以下操作:
ADD folder destination
例如,假设您有来自主目录上卷的数据,例如,/home/mydata
您可以运行以下命令:
DOCKERFILE=/home/dockerfile.bk-myimage
docker build --rm --no-cache -t $IMAGENAME:$TAG -f $DOCKERFILE /home/pirate
你的 DOCKERFILE 指向这样的文件:
FROM user/myimage
MAINTAINER Danielo Rodríguez Rivero <example@gmail.com>
WORKDIR /opt/data
ADD mydata .
其余的东西是从基本图像继承的。您现在可以将该映像推送到 docker cloud,您的用户将可以直接在其容器上使用数据
我建议使用restic。这是一个易于使用的备份应用程序,可以备份到各种目标,例如本地文件系统、S3 兼容的存储服务或静态 REST 目标服务器,以提及一些选项。使用 resticker,您将拥有一个已经准备好的容器,可以使用 cron 语法进行调度:https ://github.com/djmaze/resticker
对于那些想了解更多关于restic及其用法的人,我确实写了一篇关于该主题的博客文章系列,包括其用法示例: https ://remo-hoeppli.medium.com/restic-backup-i-simple-和-美丽的备份-bdbbc178669d
这是一种卷文件夹备份方式。
如果你有 docker registry infra,这个方法非常有用。
这使用 docker 注册表轻松移动 zip 文件。
#volume folder backup script. !/bin/bash
#common bash variables. set these variable before running scripts
REPO=harbor.otcysk.org:20443/levee
VFOLDER=/data/mariadb
TAG=mariadb1
#zip local folder for volume files
tar cvfz volume-backup.tar.gz $VFOLDER
#copy the zip file to volume-backup container.
#zip file must be in current folder.
docker run -d -v $(pwd):/temp --name volume-backup ubuntu \
bash -c "cd / && cp /temp/volume-backup.tar.gz ."
#commit for pushing into REPO
docker commit volume-backup $REPO/volume-backup:$TAG
#check gz files in this container
#docker run --rm -it --entrypoint bash --name check-volume-backup \
$REPO/volume-backup:$TAG
#push into REPO
docker push $REPO/volume-backup:$TAG
在另一台服务器
#pull the image in another server
docker pull $REPO/volume-backup:$TAG
#restore files in another server filesystem
docker run --rm -v $VFOLDER:$VFOLDER --name volume-backup $REPO/volume-backup:$TAG \
bash -c "cd / && tar xvfz volume-backup.tar.gz"
运行使用此卷文件夹的图像。
您可以轻松制作一个同时具有一个运行映像和一个卷 zip 文件的映像。
但我不推荐由于各种原因(图像大小,输入命令,..)。