Docker Step by Step(三) Docker数据的持久化

Docker容器服务中数据的持久化

     上一篇文章里面我们通过dockerhub,pull了一个mysql镜像并运行成容器,并实现了远程访问,这个是比较初级的使用方式
实际当中会有一些问题,比如mysql的数据是全部存在于容器当中的,也就是说mysql数据的生命周期和它所在的容器一致,
如果容器被删除那么数据也就没有了。而且对于运行在容器中的服务,这样的数据存在,也不便于迁移、备份,有时可能需要
进行数据的共享读取或者写入,也不是很方便。
 

Docker的数据存储解决方案

主要有两种类型Volumes数据卷方式、Bind mount 即挂载目录方式。
另外还有一种tmpfs是临时存储。 这里我们主要介绍前面两种。
如下图,可以看出volume和bind mount的数据存储都是基于Container外的宿主机文件系统的。
 
 
 

Volume数据卷方式特点

Volume和Bind mount两种方式是有一些不同的,我们先来看Volume方式。
Volumes以下简称数据卷,是归Docker管理的一种数据存储方式,可以理解为一个专门用于数据存储的容器
可以由Docker命令创建,删除,挂载到其他容器,用于存储数据。
Volumes数据卷将数据存放到宿主机的文件系统: /var/lib/docker/volumes/
注:这个默认位置也可以通过符号链接等方式修改为其他的位置,可以参考本文后面的参考文章链接。
 
 
  • Volume数据卷的常用操作
Volume数据卷有几种使用方式,你可以单独创建好数据卷,然后在容器启动时在挂载给容器。
也可以在容器启动的同时,创建数据卷。
 
 

以下我们创建数据卷,再挂载给容器。

  • 先创建数据卷
我们先创建一个单独的volume,my-vol
以下是操作命令:
sudo docker volume create my-vol
然后通过 sudo docker volume ls 来列表数据卷,如下图:
 
可以使用sudo docker volume inspect my-vol来查看数据卷的详细信息:
从上面图中可见默认数据卷的数据所在位置是位于宿主机:
/var/lib/docker/volumes/my-vol/_data
使用sudo ls /var/lib/docker/volumes/my-vol/_data  列表这个文件夹,内容目前是空的。
 
  • 将数据卷挂载到容器
上篇文章,我们先用之前使用sudo docker pull mysql:5.7 拉取了官方mysql镜像,
现在直接基于这个镜像运行容器,并且挂载上面创建的my-vol数据卷。
通过以下docker run命令:
sudo  docker run -d \
    -p 13306:3306 \
  --name mysql5.7  \
  --mount source=my-vol,target=/var/lib/mysql  \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7.30
 
其中 -d表示容器后台运行
-p是容器中mysql容器内外端口映射
—name为容器名称
—mount 则是将 之前创建的mys-vol数据卷映射(挂载)到mysq容器的数据目录
               分别用source=my-vol 和target=/var/lib/mysql 定义,后者是容器中mysql储存数据的位置
-e 是mysql官方镜像的环境变量参数,即root密码
mysql:5.7.30是使用的镜像名称
 
注:更多官方mysql镜像信息可以参考: https://hub.docker.com/_/mysql
 
其实上面命令关于挂载数据卷的就是 —mount参数。
将数据卷挂载到容器的参数除了— mount 之外,还可以用 -v 参数,达到的效果相同,只是命令格式不同 
官方目前推荐用—mount ,以下是使用-v达到 同等功能的命令:
sudo  docker run -d \
    -p 13306:3306 \
  --name mysql5.7  \
  -v my-vol:/var/lib/mysql  \
-e MYSQL_ROOT_PASSWORD=123456 \
  mysql:5.7.30
 
:以上-v的冒号两边不要有空格,不然命令会报错。
 
  • 用客户端登录并产生数据
接下来我们用mysql客户端软件,比如mysql workbench登录上面创建的mysql:5.7这个容器的mysql服务
para.ubuntu.com是docker宿主机的名称,13306是上面设置的mysql容器对外端口。
root密码是上面设置的123456
注:mysql实际不推荐root能远程登录,此处只是演示。
 
然后我们在这个数据库中创建一些数据:
 
最后我们使用之前的sudo docker volume inspect my-vol 查看数据在宿主机文件系统位置,并列表这个位置的数据,那么
现在这个文件夹中是有数据存在的,这个就是容器中mysql服务产生的数据库数据的相关文件。
你也可以使用sudo docker exec -it mysql5.7 /bin/bash 进入容器内部,查看/var/lib/mysql 文件夹也是这些数据,因为他们实际是同一个存储位置。
 
 
  • 通过实践了解数据卷独立存储
由于数据卷volume独立于容器存在,因此我们可以把刚才的mysql容器停止并且删除,之后重新用docker run创建新容器
仍然可以挂载之前创建的my-vol数据卷。
执行以下命令停止并删除之前创建的mysql容器: 
sudo docker stop mysql5.7
sudo docker rm mysql5.7
然后使用sudo docker volume inspect my-vol 显示数据卷仍然存在
然后使用 sudo ls /var/lib/docker/volumes/my-vol/_data 显示数据也存在。
 
接下来用之前命令创建另一个容器mysql5.7 b,并挂载my-vol数据卷。
sudo  docker run -d \
    -p 13307:3306 \
  --name mysql5.7b  \
  --mount source=my-vol,target=/var/lib/mysql  \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7.30
此处容器名称为mysql5.7b ,对外端口是13307
然后执行以上命令后,启动客户端登录:
 
那么用之前mysql容器创建的表数据依然能用。
 
  • 启动容器同是创建数据卷
如果之前并没有创建volume数据卷,使用以上docker run命令创建容器时,会同时创建一个名为my-vol的Volume。
 
 
  • 数据卷的数据可以共享
数据卷volume不仅独立与容器存在,并且可以进行共享。
比如两个容器,可以同时挂载使用同一个数据卷。
 
 
我们先创建一个数据卷
sudo docker volume create --name data-vol1
然后执行:
sudo docker run -it --name=container-1 --mount source=data-vol1,target=/data1 ubuntu
创建容器container-1,挂载data-vol1数据卷到data1文件夹,同时以交互形式进入容器。
并执行:echo "the file ready to share" > /data1/test.txt
创建一个有内容的文件test.txt
最后执行exit退出交互模式到宿主机。
 
再用交互模式创建一个容器container-2,并且使用 —volumes-from 参数指定挂载的数据卷来自container-1
sudo docker run -it --name=container-2 --volumes-from container-1 ubuntu
执行exit退出当前容器,回到宿主机。
执行:sudo docker restart container-1
重启container-1容器
执行 sudo docker exec -it container-1 /bin/bash
进入容器后,执行: cat /data-1/test.txt 
可以看到刚才分别在两个容器对文件的操作头起了作用。
 
此时你打开两个终端,分别进入container-1和container-2两个容器同时在/data1/文件夹创建文件,会发现所作的修改分别体现在两个容器中。
也就是两个容器此时共享的是同一个volume数据卷。
多个容器共享数据卷,在现实中具体如何使用,需要结合实际考虑,这个功能更适合于多个服务共同输出数据到一个
集中存储的场景。
 
另外如果创建一个共享,但是只读的数据卷,可以加ro参数,如下container3能访问container-1共享的数据卷,但是是只读访问的。
sudo docker run -it --name=container-3 --volumes-from container-1:ro ubuntu
 
删除数据卷命令
数据卷实际是占用存储空间的,所以如果没有用的数据卷,特别是没有被容器使用的孤立数据卷应该定期清除:
 
删除数据卷名称为my-vol的命令如下
docker volume rm mysql-vol
 
删除所有没有被任何容器使用的数据卷
docker volume prune
 
 

Bind Mounts挂载目录方式

挂在目录的方式,可以更灵活的把docker内部要持久话的数据挂在到任何位置,比如以下命令:
与数据卷Volume最大的不同就是可以指定任意宿主机上面的目录与容器内的文件夹做映射。
同样也同时支持-0mount参数和-v参数,以下分别是两个命令启动容器,使用bind mounts方式映射
当前宿主机的opt文件夹到容器内的opt文件夹
sudo docker run -d \
  -it \
  --name mycontainer \
  --mount type=bind,source="$(pwd)",target=/opt \
  ubuntu
 
sudo docker run -d \
  -it \
  --name mycontainer2 \
  -v "$(pwd)":/opt \
  ubuntu
 
 

Volume和Bind Mounts两种方式的不同:

Volumes数据卷将数据存放到宿主机的文件系统: /var/lib/docker/volumes/
Volumes数据可以在多个容器间共享,可以通过docker volumes一系列命令管理数据卷。
注:这个默认位置也可以通过符号链接等方式修改为其他的位置,可以参考本文后面的参考文章链接。
 
而Bind mount则是可以映射任何宿主机的位置,数据访问权限可以由用户设定。
这种方式比较灵活,可以Docker容器内的文件夹映射到宿主机某个文件夹,
可以是宿主机比较快的磁盘、比如SSD或者是容量比较打的硬盘,完全由用户指定。
 
 
 
参考文章:
修改Docker默认数据存储位置(通过配置文件或者ln软链接)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值