如何使用其数据卷备份Docker容器?

pgu*_*rio 125 backup docker linux-containers

我一直在使用这个Docker-image tutum/wordpress来演示一个Wordpress网站.最近我发现图像使用了MySQL数据的卷.

所以问题是:如果我想备份和恢复容器,我可以尝试提交图像,然后删除容器,并从提交的图像创建一个新容器.但是,如果我这样做,卷将被删除,我的所有数据都将消失.

必须有一些简单的方法来备份我的容器及其卷数据,但我无法在任何地方找到它.

Tho*_*eil 120

如果我想恢复容器,我可以尝试提交图像,然后删除容器,并从提交的图像创建一个新容器.但是,如果我这样做,卷将被删除,我的所有数据都将消失

正如docker用户指南所解释的那样,数据卷旨在将数据保存在容器文件系统之外.这也便于在多个容器之间共享数据.

虽然Docker永远不会删除卷中的数据(除非您删除关联的容器docker rm -v),但任何docker容器未引用的都称为悬空卷.那些悬空的卷很难摆脱,很难进入.

这意味着只要删除使用卷的最后一个容器,数据量就会悬空,其内容难以访问.

为了防止这些悬空卷,诀窍是使用您想要保留的数据卷创建一个额外的docker容器; 这样至少会有至少那个引用该卷的docker容器.这样,您可以删除运行wordpress应用程序的docker容器,而不会失去对该数据卷内容的访问权限.

这种容器称为数据容器.

必须有一些简单的方法来备份我的容器和体积数据,但我无法在任何地方找到它.

备用泊坞窗图像

要备份docker镜像,请使用docker save命令生成tar归档文件,以后可以使用它来使用docker load命令创建新的docker镜像.

备份docker容器

您可以通过不同方式备份docker容器

  • 通过使用docker commit命令基于docker容器当前状态提交新的docker镜像
  • 通过使用docker export命令将docker容器文件系统导出为tar存档.稍后您可以使用docker import命令从该tar存档创建新的docker镜像.

请注意,这些命令只会备份docker容器分层文件系统.这排除了数据量.

备份docker数据卷

要备份数据卷,您可以使用要备份的卷运行新容器,并执行tar命令以生成卷内容的存档,如docker用户指南中所述.

在您的特定情况下,数据卷用于存储MySQL服务器的数据.因此,如果要导出此卷的tar存档,则需要先停止MySQL服务器.为此,您必须停止wordpress容器.

备份MySQL数据

另一种方法是使用mysqldump命令远程连接到MySQL服务器以生成数据库转储.但是,为了使其工作,您的MySQL服务器必须配置为接受远程连接,并且还允许允许远程连接的用户.您正在使用的wordpress docker图像可能不是这种情况.


编辑

Docker最近推出了Docker卷插件,它允许将卷的处理委托给供应商实现的插件.

docker run命令具有该-v选项的新行为.现在可以传递卷名.以这种方式创建的卷被命名并且稍后可以轻松引用,从而缓解了悬空卷的问题.

编辑2

Docker引入了docker volume prune命令来轻松删除所有悬空卷.

  • 实际上我对制作一个容易移动的容器更感兴趣,我不明白容器无法移动的意义. (28认同)
  • Docker不会自动删除数据卷.`数据量旨在持久保存数据,与容器的生命周期无关.因此,当您删除容器时,Docker永远不会自动删除卷,也不会"垃圾收集"容器不再引用的卷.因此,仅数据容器是传统的 (6认同)
  • 您不需要“mysqldump”的远程连接。只需将 shell 放入容器中,转储它,然后使用 docker cp 将其复制出来即可。 (4认同)

tom*_*sop 26

更新2

原始单卷备份脚本:

#!/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
Run Code Online (Sandbox Code Playgroud)

原始单卷还原脚本:

#!/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
Run Code Online (Sandbox Code Playgroud)

用法可以是这样的:

$ 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
Run Code Online (Sandbox Code Playgroud)

假设是:备份文件名为backup.tar,它与备份和恢复脚本位于同一目录中,容器之间的卷名相同.

UPDATE

在我看来,从容器备份卷与从数据容器备份卷没有什么不同.

卷只是链接到容器的路径,因此流程是相同的.

我不知道docker-backup是否也适用于相同的容器卷,但您可以使用:

sudo docker run --rm --volumes-from yourcontainer -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
Run Code Online (Sandbox Code Playgroud)

和:

sudo docker run --rm --volumes-from yournewcontainer -v $(pwd):/backup busybox tar xvf /backup/backup.tar
Run Code Online (Sandbox Code Playgroud)

结束更新

有一个很好的工具可用于备份和恢复docker volume容器:

https://github.com/discordianfish/docker-backup

如果您有一个容器链接到某些容器卷,如下所示:

$ docker run --volumes-from=my-data-container --name my-server ...
Run Code Online (Sandbox Code Playgroud)

您可以像这样备份所有卷:

$ docker-backup store my-server-backup.tar my-server
Run Code Online (Sandbox Code Playgroud)

并恢复如下:

$ docker-backup restore my-server-backup.tar
Run Code Online (Sandbox Code Playgroud)

或者您可以按照官方方式:

如何将仅数据卷从一个主机移植到另一个主机?


jdh*_*deb 25

如果您的项目使用 docker-compose,这里是一种备份和恢复卷的方法。

docker-compose.yml

基本上,您在docker-compose.yml 文件中添加db-backupdb-restore服务,并根据您的卷名称对其进行调整。我的卷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"

Run Code Online (Sandbox Code Playgroud)

避免腐败

为了数据一致性,在备份或恢复之前停止你的数据库容器

docker-compose stop db
Run Code Online (Sandbox Code Playgroud)

备份

要备份到默认目标 ( backup/dbdata.tar.bz2):

docker-compose run --rm db-backup
Run Code Online (Sandbox Code Playgroud)

或者,如果要指定备用目标名称,请执行以下操作:

docker-compose run --rm -e TARGET=mybackup db-backup
Run Code Online (Sandbox Code Playgroud)

恢复

要从 恢复backup/dbdata.tar.bz2,请执行以下操作:

docker-compose run --rm db-restore
Run Code Online (Sandbox Code Playgroud)

或者使用以下命令从特定文件恢复:

docker-compose run --rm -e SOURCE=mybackup db-restore
Run Code Online (Sandbox Code Playgroud)

我改编了来自https://loomchild.net/2017/03/26/backup-restore-docker-named-volumes/ 的命令来创建这种方法。


And*_*iak 15

如果您只需备份已装载的卷,则只需从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
Run Code Online (Sandbox Code Playgroud)

它将在当前目录中创建一个./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
Run Code Online (Sandbox Code Playgroud)

现在你可以检查它是否有效:

docker volume ls
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,是的,您可以,但是您会遇到数据损坏问题,因为副本是非原子的,并且可能会对卷进行并发写入,我宁愿先停止容器。 (6认同)
  • 没必要,您可以随时复制该文件夹. (2认同)

Sah*_*uja 11

假设您的卷名是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
Run Code Online (Sandbox Code Playgroud)

恢复:

docker run --rm data_image tar -c -f- data | docker run -i --rm --mount source=data_volume,destination=/data alpine tar -x -f-
Run Code Online (Sandbox Code Playgroud)

  • 由于同一个卷可以安装在多个 docker 上,是的,这是实时备份。例如。可以备份安装在 Mysql 容器上的卷(假设没有数据损坏)。但是对于因担心数据损坏而需要停止的服务,不,这不是实时的。 (3认同)

小智 8

我知道这是旧的,但我意识到没有一个记录良好的解决方案将数据容器(作为备份)推送到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
Run Code Online (Sandbox Code Playgroud)

将此tar文件扩展为一个新容器,以便我们可以将其作为其映像的一部分提交

docker run -d -v $(pwd):/backup --name data-backup ubuntu /bin/sh -c "cd / && tar xvf /backup/backup.tar"
Run Code Online (Sandbox Code Playgroud)

使用所需标记提交并推送图像($ VERSION)

docker commit data-backup repo/data-backup:$VERSION
docker push repo/data-backup:$VERSION
Run Code Online (Sandbox Code Playgroud)

最后,让我们清理一下

docker rm data-backup
docker rmi $(docker images -f "dangling=true" -q)
Run Code Online (Sandbox Code Playgroud)

现在我们在repo中有一个名为data-backup的映像,它只是一个包含备份文件和文件夹的文件系统.为了使用此映像(也称为从备份还原),我们执行以下操作:

使用数据备份映像运行数据容器

run -v /folderToBackup --entrypoint "bin/sh" --name data-container repo/data-backup:${VERSION}
Run Code Online (Sandbox Code Playgroud)

使用data-conainter中的卷运行whatEver图像

docker run --volumes-from=data-container repo/whatEver
Run Code Online (Sandbox Code Playgroud)

而已.

我很惊讶没有关于这项工作的文档.我希望有人觉得这很有帮助.我知道我花了一段时间才想到这一点.


kon*_*rad 6

以下命令将在安装了所有命名数据卷的容器中运行 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
Run Code Online (Sandbox Code Playgroud)

如果出现问题,请确保测试生成的存档:

tar -tjf data-volumes.tar.bz2
Run Code Online (Sandbox Code Playgroud)


loo*_*ild 5

如果你只需要一个简单的存档备份,你可以试试我的小工具:https : //github.com/loomchild/volume-backup

例子

备份:

docker run -v some_volume:/volume -v /tmp:/backup --rm loomchild/volume-backup backup archive1
Run Code Online (Sandbox Code Playgroud)

将归档卷命名some_volume/tmp/archive1.tar.bz2归档文件

恢复:

docker run -v some_volume:/volume -v /tmp:/backup --rm loomchild/volume-backup restore archive1
Run Code Online (Sandbox Code Playgroud)

擦除和恢复some_volume/tmp/archive1.tar.bz2存档文件命名的卷。

更多信息:https : //medium.com/@loomchild/backup-restore-docker-named-volumes-350397b8e362