如何备份带有数据量的Docker容器?


152

我一直在使用这个Docker-image tutum / wordpress演示Wordpress网站。最近,我发现该映像将卷用于MySQL数据。

所以问题是这样的:如果我要备份和还原容器,则可以尝试提交映像,然后再删除该容器,并从提交的映像中创建一个新的容器。但是,如果我这样做,该卷将被删除,我的所有数据都将消失。

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


看看我编写的脚本,它绝对备份了docker项目中的所有内容,包括命名和未命名的卷,映像,配置,日志,容器根文件系统,数据库等等:docker-compose-backup.sh
Nick Sweeting

Answers:


141

如果我想还原容器,则可以尝试提交映像,然后再删除该容器,并从提交的映像中创建一个新的容器。但是,如果我这样做,该卷将被删除,我所有的数据都将消失

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

尽管Docker永远不会删除卷中的数据(除非您使用删除关联的容器docker rm -v),但任何Docker容器未引用的都称为悬空卷。这些悬而未决的书卷很难摆脱,也很难获得。

这意味着,一旦删除了最后一个使用卷的容器,数据卷就会变得悬而未决,其内容也难以访问。

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

这种容器称为数据卷容器

必须有一些简单的方法来备份我的容器以及卷数据,但是我在任何地方都找不到它。

备份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轻松删除所有悬空卷的命令。


34
实际上,我对制作一个可以轻松移动的容器更感兴趣,我不明白不能移动的容器的要点。
pguardiario 2014年

在这种情况下,您应该查看有助于您管理Docker数据量的工具,例如Flocker
Thomasleveil

9
Docker不会自动删除数据卷。 Data volumes are designed to persist data, independent of the container’s life cycle. Docker therefore never automatically delete volumes when you remove a container, nor will it “garbage collect” volumes that are no longer referenced by a container. 因此只有数据容器才是传统的容器
Andrii Zarubin '02

2
您不需要进行远程连接mysqldump。只需将其装入容器中,将其转储,然后使用将其复制出去docker cp
jiggunjer

@AndriiZarubin回复:完全data only container obsolete?没有。仅数据容器为您提供了一个容器,docker exec data-container tar -czf snapshot.tgz /data然后再docker cp data-container:snapshot.tgz ./snapshot.tgz等等。如果您希望容器长期存在,则tail -f /dev/null使用最少的资源使它的命令像永不退出一样。
杰西·奇斯霍尔姆

31

更新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

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

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


不,这不是“ --volumes-from”的情况,而是在dockerfile中定义了卷,这是导致数据无法持久保存的原因。如果查看tumum / lamp的dockerfile,您会明白我的意思。
pguardiario 2014年

我已经给出的答案对于任何类型的卷都是有好处的,因为卷是卷,而容器是容器,如果从卷的角度使用容器作为数据容器,则没有区别
tommasop 2014年

销毁容器时,将销毁dockerfile中定义的卷。因此,当您移动容器时,无法取回该数据。
pguardiario 2014年

您必须先取出数据,然后再移动容器,然后重新启动容器并将数据放回
tommasop 2014年

1
我得到一个错误:unknown shorthand flag: 'r' in -rm.应该--rm吗?(Docker版本18.09.5,内部版本e8ff056)
kuga

22

如果只需要备份已装载的卷,则只需从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

我们是否需要关闭容器以/var/lib/docker/volumes在Ubuntu下对该文件夹进行备份?
onknows's

2
没必要,您可以随时复制该文件夹。
Andrii Dvoiak

4
从技术上讲是可以的,但是您会遇到数据损坏的问题,因为该副本是非原子的,并且可能存在对该卷的并发写入,我宁愿先停止该容器。
亚历山德罗S.19年

13

假设您的卷名是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-

这是实时备份吗?
康·安德鲁

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

9

我知道这已经很老了,但是我意识到没有一个有据可查的解决方案可以将数据容器(作为备份)推送到Docker Hub。我刚刚在https://dzone.com/articles/docker-backup-your-data-volumes-to-docker-hub上发布了有关此操作的简短示例。

以下是底线

码头工人教程建议您可以在本地备份和还原数据量。我们将使用此技术,再添加几行,以将该备份推送到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)

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

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

run -v /folderToBackup --entrypoint "bin/sh" --name data-container repo/data-backup:${VERSION}

使用数据容器中的卷运行您的whatEver映像

docker run --volumes-from=data-container repo/whatEver

而已。

我很惊讶没有解决此问题的文档。我希望有人能对此有所帮助。我知道我花了一些时间思考这个问题。


8

如果您的项目使用docker-compose,则这是一种用于备份和还原卷的方法。

docker-compose.yml

基本上你添加db-backupdb-restore服务,您的码头工人,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/改编了命令来创建这种方法。


5

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

4

如果只需要对存档的简单备份,则可以尝试使用我的小实用程序: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


我创建了一个类似的工具github.com/01e9/docker-backup,它创建了备份档案并将其添加到Resilio同步目录中
Oleg,

2

我创建了一个工具来协调和启动数据和mysql容器的备份,简称为docker-backupdocker hub上有一个现成的映像

它主要是编排,所以主要用Bash编写。它duplicity用于实际的备份引擎。您目前可以备份到FTP(S)和Amazon S3。

配置非常简单:在YAML中编写一个配置文件,描述要备份的内容以及备份的位置,然后开始!

对于数据容器,它将自动挂载容器共享的卷以备份和处理它。对于mysql容器,它将链接它们并执行与您的容器捆绑在一起的mysqldump并处理结果。

我写它的原因是因为我使用的不是最新docker-engine版本的最新Docker-Cloud,而且因为我想通过不将任何备份过程包含在我的应用程序容器中来拥抱Docker方式。


2

如果要完整备份,则需要执行一些步骤:

  1. 将容器提交到图像
  2. 保存图像
  3. 通过在容器中创建卷的安装点的tar文件来备份容器的卷。
  4. 对数据库容器也重复步骤1-3。

请注意,仅将容器对映像进行Docker提交并不包括附加到容器的卷(请参阅:Docker commit documentation)。

提交操作将不包含容器内安装的卷中包含的任何数据。


1

如果您喜欢从命令行输入奥术运算符,那么您会喜欢这些手动容器备份技术。请记住,有一种更快捷,更有效的备份容器的方法,它同样有效。我在这里写了说明:https : //www.morpheusdata.com/blog/2017-03-02-how-to-create-a-docker-backup-with-morpheus

步骤1:将Docker主机 添加到任何云中正如Morpheus支持站点上的教程中所述,您可以在几秒钟内将Docker主机添加到您选择的云中。首先在主Morpheus导航栏上选择“基础结构”。选择基础结构窗口顶部的主机,然后单击右上角的“ +容器主机”按钮。

要通过Morpheus将Docker主机备份到云中,请导航至“基础架构”屏幕,然后打开“ +容器主机”菜单。

在菜单上选择一个容器主机类型,选择一个组,然后在五个字段中输入数据:名称,描述,可见性,选择云和输入标签(可选)。单击“下一步”,然后通过选择服务计划来配置主机选项。请注意,仅当您选择的计划启用了自定义选项时,“卷”,“内存”和“ CPU计数”字段才可见。

您可以在此处添加卷并为其设置大小,设置内存大小和CPU数量,然后选择一个网络。您还可以配置OS用户名和密码,域名和主机名,默认情况下,它们是您先前输入的容器名称。单击下一步,然后添加任何自动化工作流(可选)。最后,检查您的设置并单击完成以保存设置。

第2步:将Docker注册表集成添加到公共云或私有云中, Adam Hicks在另一份Morpheus教程中描述了与私有Docker Registry集成的简单性。(使用Morpheus使用公共Docker API通过Docker的公共集线器配置映像时,不需要进行额外的配置。)

在主导航栏的“管理”标签下选择“集成”,然后选择屏幕右侧的“ +新集成”按钮。在出现的“集成”窗口中,在“类型”下拉菜单中选择“ Docker Repository”,输入名称并添加私有注册表API端点。提供您正在使用的注册表的用户名和密码,然后单击“保存更改”按钮。

通过Morpheus的“ New Integration”对话框将Docker Registry与私有云集成。

要置备刚创建的集成,请在“创建实例”对话框的“类型”下选择“ Docker”,在“配置”选项卡下的“ Docker注册表”下拉菜单中选择注册表,然后像配置任何Docker容器一样继续置备。

步骤3:管理备份 添加Docker主机并集成注册表后,将为您配置的每个实例自动配置并执行备份。Morpheus支持提供了有关查看备份,创建实例备份以及创建服务器备份的说明。


0

如果您的案例像我的那么简单,则可以执行以下操作:

  1. 创建一个扩展容器基础映像的Dockerfile
  2. 我假设您的卷已映射到您的文件系统,所以您可以使用以下命令将这些文件/文件夹添加到映像中 ADD folder destination
  3. 做完了!

例如,假设您拥有主目录中卷中的数据(例如在处)/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云,您的用户将直接在其容器上使用数据


如果最终要将其烘焙到图像中,使用卷有什么意义?
jiggunjer

具有卷的@jiggunjer允许您覆盖容器中的数据
Danielo515

我也可以使用来覆盖没有卷的数据docker cp
jiggunjer

0

问题:您要备份包含数据卷的映像容器,但此选项并非开箱即用,简单而直接的方法是复制卷路径并备份docker映像,然后重新加载并链接它两者一起。但是此解决方案似乎笨拙,并且不可持续且不可维护-您将需要创建一个cron作业,以使每次工作都顺畅进行。

解决方案:使用dockup -Docker映像备份Docker容器卷并将其上传到s3(Docker + Backup = dockup)。对接将使用您的AWS凭证创建一个新的存储桶,其名称与环境变量相同,获取已配置的卷,并将其压缩,压缩,加盖时间戳记并上传到S3存储桶。

步骤

  1. 配置docker-compose.yml并将其附加env.txt配置文件,数据应上传到专用的安全s3存储桶,并准备在执行DRP时重新加载。为了验证哪个卷路径配置运行docker inspect <service-name>并且找到

“卷”:{“ / etc / service-example”:{},“ / service-example”:{}},

  1. 编辑配置文件的内容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
    
  2. 运行停靠容器

$ docker run --rm \
--env-file env.txt \
--volumes-from <service-name> \
--name dockup tutum/dockup:latest
  1. 然后验证您的s3存储桶是否包含相关数据

-1

这是一种卷文件夹备份方式。
如果您具有以下docker Registry,则此方法非常有用。
这使用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文件的图像。
但是由于种种原因(图像大小,输入命令等),我不建议这样做。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.