Docker存储学习总结

Docker的数据持久化的两种方式

Posted by NianShen Blog on April 10, 2018

数据卷(volume)

数据卷是一个可供一个或多个容器使用的特殊目录。下面以启动一个redis的容器为例:

[root@zzr-blog ~]# docker run --name zzr-redis -d -p 6379:6379 redis
68fe82ce171c24b973b992e440f553c318cc8de2ac223163fcdb5852b030c730

[root@zzr-blog ~]# docker volume ls
DRIVER              VOLUME NAME
local               b71fc55ccdb855356813d9859c15028d10c91c4863e3b5df57faf038fce54df5
local               cf89716f6ac970facea30ca8035256eb43fa90da2f86f2f401151e5b9489b93a

通过执行docker volume ls命令可以查看当前主机上已经创建了哪些数据卷,但是并不能确定他们之间的对应关系,使用inspect命令:

docker inspect zzr-redis

docker-volume.png

可以找到对应的volume的ID,跟刚才的docker volume中的第一个是一样的。但是这个volume ID太长了不是很友好,可以指定volume的名称

[root@zzr-blog ~]# docker volume create redis_volume
redis_volume

[root@zzr-blog ~]# docker run --name zzr-redis-test -d -p 6380:6379 -v redis_volume:/usr/local/etc/redis/redis.conf redis
319e6dcfb97304edcefb24f5dbf363cdd5b0ba57eb2a66ad16db1cab57512208

[root@zzr-blog ~]# docker volume ls
DRIVER              VOLUME NAME
local               b71fc55ccdb855356813d9859c15028d10c91c4863e3b5df57faf038fce54df5
local               beead6a9a29070b21caa55c65f914012b4fe57ca779d8601480284248881fb6c
local               cf89716f6ac970facea30ca8035256eb43fa90da2f86f2f401151e5b9489b93a
local               redis_volume

redis-volume.png

总结几个点:

  • 数据卷默认一直存在,不会根据container的生命周期的改变而改变。想删除只能通过docker volume rm
  • 数据卷可以在而container之间共享重用。
  • 数据卷的修改立即生效。
  • 数据卷中的更新不影响镜像本身
  • 如果volume是空的而container中的目录有内容,那么docker会将container目录中的内容拷贝到volume中,但是如果volume中已经有内容,则会将container中的目录覆盖。

主机目录(bind mount)

将宿主机的目录mount到container中。bind mount在不同os时不可移植,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。主机上的目录可以是一个本地目录,也可以在一个NFS 内,或者在一个已经格式化好了的块设备上。其实这种形式和第一种没有本质的区别,容器内对 /usr/local/etc/redis/redis.conf 的操作都会反映到主机上的 /root 目录内。只是,重新启动容器时,可以再次使用同样的方式来将 /root 目录挂载到新的容器内,这样就可以实现数据持久化的目标。

[root@zzr-blog ~]# docker run --name zzr-redis-test2 -d -p 6381:6379 -v $(pwd):/usr/local/etc/redis/redis.conf redis
fd4bbacec8d81cf282aac249648592e191a29966d8e02865b6b96748555b60ae

bindmount.png

总结几个点:

  • 如果host机器上的目录不存在,docker会自动创建该目录在宿主机上
  • 如果container中的目录不存在,docker会自动创建该目录在容器内
  • 如果container中的目录已经有内容,那么docker会使用host上的目录将其覆盖掉