四时宝库

程序员的知识宝库

详解docker——容器数据持久化和数据共享

概述

docker 主要有两种数据存储形式, 一种是storage driver(也叫做 Graph driver), 另一种是 volume driver. stroage driver主要是存储那些无状态的数据, 写入密集型的场景应该使用 volume driver.

storage driver

容器运行的文件系统是镜像层和容器层组成的, 一层一层叠加, 只有最上面的那层是可写的, 其他层都是只读的. Docker通过Union FS技术支持文件的读写和新建, Docker 采用插件式的方式支持多种Union FS实现, 官方文档中一般使用stroage driver术语, 目前已经有多种实现的插件, 比如: aufs/overlay/overlay2/devicemanger等等.

boot2docker 缺省使用的storage-driver 为 aufs, 下面命令将创建一个使用 overlay2 的 storage driver docker运行环境.

docker-machine create --driver virtualbox --engine-storage-driver overlay2 test2

正式的docker 环境, 需要修改 /etc/docker/daemon.json 文件

{
"storage-driver": "btrfs"
}

几个查询storage driver的命令:

docker info 命令, 查询docker运行环境使用的storage-driver.

docker image inspect 命令,查看镜像使用的存储driver.

docker container inspect 命令,查看容器使用的存储driver.

volume driver

volume driver 经常用来实现数据持久化和文件共享功能, 具体有两种存在方式, 分别是:

1. bind mount 方式:

是将host的目录或文件直接mount到容器中, host的目录或文件既可以容器运行之前就已存在的, 也可以是在容器运行之前不存在的.

如果在docker run 命令中采用了 -v /host/dir_or_file:/container/dir_or_file的形式, 就是bind mount方式, 即指定了host的挂载点的绝对路径.

2. volume 方式

是由 Docker 管理, 该volume最终存储到host的 /var/lib/docker/volumes 下. volume 方式还分为 named volume 和 Anonymous volume.

named volume 有两种创建方法,

(1) docker run 命令中采用了 -v one_volume_name:/container/dir_or_file , 这里的one_volume_name不是host中的绝对路径, 而是一个名称.

(2) 通过 docker volume create 创建的, 该命令支持更多的选项, 推荐使用.

匿名volume方式 是通过 docker run 命令中传入了 -v /container/dir 类型的参数.

3. bind mount 方式和volume方式的简单对比:

bind mount方式, docker容器直接访问host的目录或文件, 性能是最好的.

bind mount方式, docker容器直接访问host的目录或文件, 对于该host绝对目录可能会引入权限问题. 如果容器仅需要只读访问权限, 最好是显式设定只读方式.

对于 volume方式, 如果host中落地目录为空, docker先将容器中的对应目录复制到host下, 然后再进行挂载操作; 对于bind mount方式, 挂载之前没有复制操作.

容器要依赖host主机的一个绝对路径, 使得容器的移植性变差, docker 官方并不推荐这个方法, 而是推荐使用volume.

几个示例说明:

docker run -d --name web0 -v myetc:/etc busybox /bin/sh -c "while true; do echo hello world; sleep 1; done" 
 #创建了一个named volume, 该volume 在 /var/lib/docker/volume/myetc 下. 
docker run -d --name web1 -v /etc busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"
 #创建了一个匿名的volume, 该volume在/var/lib/docker/volume父目录下, 具体子目录不确定, 
 #比如 /var/lib/docker/volume/9170d32e15b7578240afde81d5514637beece7d469b7ea253e23759a23b0a397 
docker run -d --name web2 -v /etc2:/etc busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"
 #使用 bind mount 方式, host上的目录为 /etc2 

docker run 命令的--volume 和 --mount 参数

--volume 和 --mount 两种参数写法都支持上述volume和bind mount方式, --mount 采用key-value的写法, 支持更多的设置选项, docker 新版更加推荐使用 --mount 参数写法, 但 --volume 写法更加简洁, 仍然给广泛使用.

另一种推荐的volume写法是, 显式地使用 docker volume create 命令创建 named volume,

有了上面的知识, 很容易就能实现容器和Host之间共享数据. 对于同一Host下多个容器共享数据, 直接docker run -v参数非常不方便, 最好是使用 data container作为桥梁. 一般data container 不启任何应用, 也不需要将容器真正运行起来, 仅仅是挂载一下 volume, data container除了用于多个容器之间数据共享之外, 也可用于volume的备份和恢复.

data container和volume的备份恢复

#创建一个名 为 dbstore 的数据容器, 设置一个匿名的/dbdata volume. 
docker create -v /dbdata --name dbstore busybox /bin/sh 
#创建一个名为 web3 的应用容器, 将 dbstore 数据容器的volume 挂载过来. 
docker run -d --name web3 --volumes-from dbstore busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"
#备份数据容器 dbstore 的/dbdata目录到容器到host的host_backup目录下, 最终在host上的文件名为 /host_backup/backup.tar
docker run --rm --volumes-from dbstore -v /host_backup:/backup busybox tar -cvf /backup/backup.tar /dbdata
 
#恢复数据容器dbstore 的/dbdata目录, 数据源为host上的文件 /host_backup/backup.tar
docker run --rm --volumes-from dbstore -v /host_backup:/backup busybox /bin/sh -c "cd /dbdata && tar -xvf /backup/backup.tar --strip 1"

之所以介绍持久化概念,是因为docker的容器设计理念是可以即开即用,用完可以随意删除,而新建容器是根据镜像进行渲染,容器的修改是不会影响到镜像,但是有时候容器里面运行的产生的数据(如mysql)或者配置项(如nginx的nginx.conf)我们又需要保存起来的,因而我们需要对容器某些修改的数据进行挂载,也就是把这些数据持久化。

后面会分享更多关于devops和DBA内容,感兴趣的朋友可以关注下!!

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接