用于克隆/快照Docker容器的脚本,包括其数据?

时间:2015-09-26 07:53:09

标签: shell web-applications docker clone docker-compose

我想克隆一个包含其所有数据的dockerized应用程序,在此示例中使用三个容器:1)Web应用程序容器(如CMS),2)数据库容器和3)数据卷容器(使用码头工人量。)

使用docker-compose,我可以轻松地仅使用初始数据创建这些容器的相同实例。但是,如果我想在同一台服务器上克隆一组正在运行的容器,包括它所有的累积数据,那就像我克隆一个KVM容器一样?使用KVM,我会暂停或关闭VM,使用virt-clone之类的东西进行克隆,然后启动克隆的guest虚拟机,该guest虚拟机具有与原始数据相同的所有数据。

一个用例是在进行重大更改之前或安装新版本的插件之前创建正在运行的开发Web服务器的克隆/快照。

使用Docker,这似乎并不那么简单,因为数据不会自动与其容器一起复制。理想情况下,我想做一些简单的事情,如docker-compose clone,最后得到第二组与第一组相同的容器,包括所有数据。 Docker和docker-compose都没有提供克隆命令(从版本1.8开始),因此我需要考虑各种方法,例如备份和安装。恢复数据/数据库或使用第三方工具,如Flocker。

与此相关的问题是如何执行与dockerized app的KVM快照类似的操作,并能够轻松返回到先前的状态。优选地,克隆,快照和恢复应该是可能的,具有最小的停机时间。

完成这些事情的首选Docker方式是什么?

编辑:根据第一个答案,我会更具体地提出我的问题,以便有希望达到程序化步骤,以便能够使用bash或docker-compose-clonedocker-compose-snapshot执行某些操作python脚本。克隆docker卷的内容似乎是关键,因为每次在同一个yaml文件上运行docker-compose时,容器本身都会被克隆。

通常我的完整克隆脚本需要

  1. 复制包含docker-compose文件的目录
  2. 暂时停止容器
  3. 创建(但不一定要运行)第二组容器
  4. 确定要复制的数据量
  5. 备份这些数据卷
  6. 将数据卷还原到克隆的数据容器中
  7. 启动第二组容器

    • 这是正确的方法,我应该如何实现?我特别不确定如何在脚本中执行步骤4(确定要复制的数据卷),因为命令docker volume ls仅在Docker 1.9中可用。

    • 如何使用此方法执行类似于KVM快照的操作? (可能使用ZFS的COW文件系统功能,我的Docker已经安装了这些功能)。

3 个答案:

答案 0 :(得分:0)

使用docker,您可以将所有状态保存在卷中。只要重新使用相同的卷(来自主机或数据卷容器),就可以从映像重新创建容器。

我不知道从数据卷容器中导出卷的简单方法。我知道docker 1.9版本将添加一些与卷交互的顶级api,但我不确定导出是否会立即可用。

如果您正在使用主机卷,则可以从docker外部管理状态。

答案 1 :(得分:0)

目前,我正在使用以下脚本基于上述方法克隆dockerized CMS Web应用程序Concrete5.7。它使用docker-compose创建第二组相同的容器,然后只备份数据卷中的数据,并将其恢复到第二组中的数据容器。

这可以作为开发更通用的脚本的示例:

#!/bin/bash
set -e

# This script will clone a set of containers including all its data

# the docker-compose.yml is in the PROJ_ORIG directory
# - do not use capital letters or underscores for clone suffix, 
#   as docker-compose will modify or remove these
PROJ_ORIG="c5app"
PROJ_CLONE="${PROJ_ORIG}003"

# 1. duplicate the directory containing the docker-compose file
cd /opt/docker/compose/concrete5.7/
cp -Rv ${PROJ_ORIG}/ ${PROJ_CLONE}/

# 2. temporarily stop the containers
cd ${PROJ_ORIG}
docker-compose stop

# 3. create, run and stop the second set of containers 
#    (docker-compose does not have a create command)
cd ../${PROJ_CLONE}
docker-compose up -d
docker-compose stop

# 4. determine the data-volumes to be duplicated
#   a) examine which containers are designated data containers
#   b) then use docker inspect to determine the relevant directories
#   c) store destination directories & process them for backup and clone
#
# In this appliaction we use two data containers 
# (here we used DATA as part of the name):
# $ docker-compose ps | grep DATA
#     c5app_DB-DATA_1    /true                            Exit 0
#     c5app_WEB-DATA_1   /true                            Exit 0
#
# $ docker inspect ${PROJ_ORIG}_WEB-DATA_1 | grep Destination
#     "Destination": "/var/www/html",
#     "Destination": "/etc/apache2",
#
# $ docker inspect ${PROJ_ORIG}_DB-DATA_1 | grep Destination
#     "Destination": "/var/lib/mysql",

# these still need to be determined manually from examining 
# the docker-compose.yml or using the commands in 4.
DATA_SUF1="_WEB-DATA_1"
VOL1_1="/etc/apache2"
VOL1_2="/var/www/html"

DATA_SUF2="_DB-DATA_1"
VOL2_1="/var/lib/mysql"

# 5. Backup Data:
docker run --rm --volumes-from ${PROJ_ORIG}${DATA_SUF1} -v ${PWD}:/clone debian tar -cpzf /clone/clone${DATA_SUF1}.tar.gz ${VOL1_1} ${VOL1_2}
docker run --rm --volumes-from ${PROJ_ORIG}${DATA_SUF2} -v ${PWD}:/clone debian tar -cpzf /clone/clone${DATA_SUF2}.tar.gz ${VOL2_1}

# 6. Clone Data:
# existing files in volumes need to be deleted before restoring, 
# as the installation may have created additional files during initial run,
# which do not get overwritten during restore
docker run --rm --volumes-from ${PROJ_CLONE}${DATA_SUF1} -v ${PWD}:/clone debian bash -c "rm -rf ${VOL1_1}/* ${VOL1_2}/* && tar -xpf /clone/clone${DATA_SUF1}.tar.gz"
docker run --rm --volumes-from ${PROJ_CLONE}${DATA_SUF2} -v ${PWD}:/clone debian bash -c "rm -rf ${VOL2_1}/* && tar -xpf /clone/clone${DATA_SUF2}.tar.gz"

# 7. Start Cloned Containers:
docker-compose start

# 8. Remove tar archives
rm -v clone${DATA_SUF1}.tar.gz
rm -v clone${DATA_SUF2}.tar.gz

经过测试和运行,但仍有以下限制:

  • 需要手动确定要复制的数据量
  • 需要修改脚本,具体取决于数据容器和数据卷的数量
  • 没有快照/恢复功能

我欢迎任何改进建议(特别是第4步)。或者,如果有人想出一个不同的,更好的方法,我会接受这个答案。

可以找到此示例中使用的应用程序以及docker-compose.yml文件here.

答案 2 :(得分:0)

在Windows上,有一个Docker的开源容器项目端口可以从Windocks获得,它可以满足您的需求。有两种选择:

  1. 通过构建映像时指定的Add database命令将较小的数据库复制到容器中。之后,每个构建的容器都会自动接收数据库。
  2. 对于大型数据库,有一个克隆功能。在创建容器期间克隆数据库,即使对于TB级别的DB,克隆也会在几秒钟内完成。删除容器也会自动删除克隆。现在它只适用于SQL Server。

    有关数据库添加和克隆的详细信息,请参阅here