4 Docker数据存储
一、数据卷特性:
启动容器后,创建可写层,在可写层中 ”写时复制“
“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录“绑定”
解决的问题: 存在于联合文件系统中,不易于宿主机访问 容器间数据共享不便 删除容器其数据会丢失
二、数据卷结构:
1)Docker 管理卷
Docker-managed volume
核心:写入Dockerfile中,创建镜像时指定挂载目录
在容器创建以后,会自动在 /var/lib/docker/volumes/随机的目录/_data/ 与容器中挂载的路径关联,持久化
2)绑定挂载卷
Bind mount volume
核心:运行容器时,加入参数,指定挂载目录
注意:当 docker run -v 与 VOLUME 指定的挂载目录冲突时,以 docker run -v 为准(作用域小,优先级高)
实验1:指定挂载位置,实现数据存储
解决:
存在于联合文件系统中,不易于宿主机访问 删除容器其数据会丢失
1、基于 Dockerfile 中 有 VOLUME 参数创建的镜像,实现
[root@localhost ~]# vim Dockerfile
[root@localhost ~]# cat Dockerfile
FROM 163
VOLUME /data
WORKDIR /data
[root@localhost ~]# docker build -t volume:v1 .
[root@localhost ~]# docker run --name test -d volume:v1 #基于volume:v1镜像运行容器
注意:此处不能用 $ docker run --name test --rm -it volume:v1 /bin/bash
[root@localhost ~]# docker exec -it test /bin/bash
[root@4b3da857052b data]# touch yqqq{1..5}.txt
[root@4b3da857052b data]# exit
[root@localhost ~]# cc #清除所有容器
4b3da857052b
[root@localhost ~]# find /var/lib/docker/volumes/ -name "yqq*" #能找到文件
/var/lib/docker/volumes/23be7ebe569e133601fa6d8e6cc6cf54603badb5e9080c50c1de26e8f62bd130/_data/yqqq1.txt
/var/lib/docker/volumes/23be7ebe569e133601fa6d8e6cc6cf54603badb5e9080c50c1de26e8f62bd130/_data/yqqq2.txt
/var/lib/docker/volumes/23be7ebe569e133601fa6d8e6cc6cf54603badb5e9080c50c1de26e8f62bd130/_data/yqqq3.txt
/var/lib/docker/volumes/23be7ebe569e133601fa6d8e6cc6cf54603badb5e9080c50c1de26e8f62bd130/_data/yqqq4.txt
/var/lib/docker/volumes/23be7ebe569e133601fa6d8e6cc6cf54603badb5e9080c50c1de26e8f62bd130/_data/yqqq5.txt
2、docker run -v 运行容器时,实现
[root@localhost ~]# docker run --name test -d -v /data:/data1 nginx:latest #加-v创建容器
2c6d5927c6f3f3727d12d6db3c879312095c1e1942f85b3e9603d5ea774e6825
[root@localhost ~]# cd /data/ #在本地目录中创建文件
[root@localhost data]# touch qweasd
[root@localhost data]# ls
qweasd
[root@localhost data]# docker exec -it test /bin/bash #进入容器,到指定目录发现数据存在
root@2c6d5927c6f3:/# cd /data1/
root@2c6d5927c6f3:/data1# ls
qweasd
3、测试 VOLUME 与 docker run -v 的优先级
注意:当 docker run -v 与 VOLUME 指定的挂载目录冲突时,以 docker run -v 为准(作用域小,优先级高)
#wordpress镜像中默认有VOLUME选项,基于wordpress镜像,加-v选项启动容器
[root@localhost ~]# docker run --name wordpress -d -v /html:/var/www/html wordpress
3a5ba96b5d92101e62b1d042502e69580e8aa6bc31847d7e6021b5c9bdc8eb18
[root@localhost ~]# ls /html/ #到/html目录下发现wordpress的文件
index.php wp-admin wp-config-sample.php wp-links-opml.php wp-settings.php
license.txt wp-blog-header.php wp-content wp-load.php wp-signup.php
readme.html wp-comments-post.php wp-cron.php wp-login.php wp-trackback.php
wp-activate.php wp-config-docker.php wp-includes wp-mail.php xmlrpc.php
[root@localhost ~]# touch /html/yangqindaociyiyou #创建一个文件
[root@localhost ~]# docker exec -it wordpress /bin/bash #进入容器,发现有刚才创建的文件,持久化存储成功,docker run -v 优先级高
root@3a5ba96b5d92:/var/www/html# ls |grep yangqin
yangqindaociyiyou
实验2:容器间的数据共享
解决:容器间数据共享不便
[root@localhost ~]# docker run --name wordpress1 -d wordpress #先启动一个wordpress1容器
bb06b81560eff736acc7583a8f22d2536b7abd4d9af9301293002d2533755823
[root@localhost ~]# docker inspect wordpress1 |grep Source #找到数据存储位置
"Source": "/var/lib/docker/volumes/b81ff34f82ba5e253d6f30e5c246b5130beaa2e40b310f5c28b46b759e4d0864/_data",
#基于找到的位置,加-v选项启动wordpress2、wordpress3
[root@localhost ~]# docker run --name wordpress2 -d -v /var/lib/docker/volumes/b81ff34f82ba5e253d6f30e5c246b5130beaa2e40b310f5c28b46b759e4d0864/_data:/var/www/html wordpress
1c27bd5267bfaa3c49843f27cc56f911103a886617f1cc632a7536a5ee789a22
[root@localhost ~]# docker run --name wordpress3 -d -v /var/lib/docker/volumes/b81ff34f82ba5e253d6f30e5c246b5130beaa2e40b310f5c28b46b759e4d0864/_data:/var/www/html wordpress
c700222b21a2e2489dbaf573e8e4aa035b68561f29a60b344a0ec7340a289216
#测试:在本地目录中创建文件,进入容器中查看,实现容器间的数据共享
[root@localhost _data]# touch QQQQQQQQQQQQQQQQQQQQQQQ
[root@localhost _data]# docker exec wordpress1 ls
[root@localhost _data]# docker exec wordpress2 ls
[root@localhost _data]# docker exec wordpress3 ls
拓展:--volumes-from #指定其他容器的挂载路径启动容器
将实验2步骤简化:
[root@localhost ~]# docker run --name wordpress1 -d wordpress
[root@localhost ~]# docker run --name wordpress2 -d --volumes-from wordpress1 wordpress
[root@localhost ~]# docker run --name wordpress3 -d --volumes-from wordpress1 wordpress
[root@localhost ~]# docker exec wordpress1 touch AAAAAAAAAAAAAAA
[root@localhost ~]# docker exec wordpress2 ls
[root@localhost ~]# docker exec wordpress3 ls
三、存储驱动
1)Docker 存储驱动 ( storage driver )
是 Docker 的核心组件,它是 Docker 实现分成镜像的基础
1、device mapper ( DM ):性能和稳定性存在问题,不推荐生产环境使用
centos6 默认为DM
老版本的docker默认采用DM
2、btrfs:社区实现了 btrfs driver,稳定性和性能存在问题
3、overlayfs:内核 3.18 overlayfs 进入主线,性能和稳定性优异,第一选择
NAS:(不是网络NAS网络附加存储,是NAS网络附加存储延伸出的一个概念)
FREENAS
TRUENAS
overlayv2 128层限制
2)启用 overlay 存储引擎
以前版本没有启用 overlay 存储引擎,启用 overlay 存储引擎(现阶段默认已经启用,一般不会用到)
$ echo "overlay" > /etc/modules-load.d/overlay.conf
$ cat /proc/modules|grep overlay #若能截取到overlay关键字,即overlay已经启用
$ reboot #若未启用,重启电脑
$ vim /etc/systemd/system/docker.service #修改docker配置文件(根据系统版本不同,配置文件位置不一样)
--storage-driver=overlay #在启动命令后加入选项
3) overlay 存储驱动使用实例
1、核心命令:
$ mount -t overlay overlay -o lowerdir=./low,upperdir=./upper,workdir=./work ./merged
$ mount -t overlay overlay -o lowerdir=./lower1:./lower2:./lower3,upperdir=./upper,workdir=./work ./merged
------- ------- ---------------------------------- -------------- ------------ -------
| | | | | |
| | | | | |
V | | | | |
指定overlay文件系统 | | | | |
V | | | |
指定当前挂载的路径 | | | |
V | | |
指定lower的路径,对应于仅读层,多个用 : 隔开 | | |
V | |
指定upper的路径,相当于可写层 | |
V |
指定work目录,工作缓存目录 |
|
V
指定merged的位置,对应挂载点位置
2、实验详细:
1.创建环境目录,挂载overlay文件系统
#创建实验环境的目录
[root@localhost ~]# mkdir overlay
[root@localhost ~]# cd overlay/
[root@localhost overlay]# mkdir lower1 lower2 lower3 upper work merged
#向对应仅读层中写入数据
[root@localhost overlay]# echo "1" > lower1/1.html
[root@localhost overlay]# echo "2" > lower2/2.html
[root@localhost overlay]# echo "3" > lower3/3.html
#挂载overlay文件系统
[root@localhost overlay]# mount -t overlay ./overlay -o lowerdir=./lower1:./lower2:./lower3,upperdir=./upper,workdir=./work ./merged
[root@localhost overlay]# mount |grep overlay
/dev/mapper/centos-root on /var/lib/docker/overlay type xfs (rw,relatime,attr2,inode64,noquota)
./overlay on /root/overlay/merged type overlay (rw,relatime,lowerdir=./lower1:./lower2:./lower3,upperdir=./upper,workdir=./work)
2.测试 overlay 文件系统使用
仅在挂载目录,对数据进行操作,符合“写时复制”规则(对其他目录的操作不合理)
启用overlay文件系统后,挂载目录中,会自动挂载仅读层的数据
[root@localhost overlay]# tree .
.
├── lower1
│ └── 1.html
├── lower2
│ └── 2.html
├── lower3
│ └── 3.html
├── merged
│ ├── 1.html
│ ├── 2.html
│ └── 3.html
├── upper
└── work
└── work
7 directories, 6 files
[root@localhost overlay]# cat merged/1.html
1
[root@localhost overlay]# cat merged/2.html
2
[root@localhost overlay]# cat merged/3.html
3
a.写入
[root@localhost overlay]# echo "123123" >> merged/1.html #符合写时复制,将复制lower仅读层到可写层upper中,再对数据进行修改
[root@localhost overlay]# echo "222222" >> merged/2.html
[root@localhost overlay]# tree .
.
├── lower1
│ └── 1.html
├── lower2
│ └── 2.html
├── lower3
│ └── 3.html
├── merged
│ ├── 1.html
│ ├── 2.html
│ └── 3.html
├── upper
│ ├── 1.html
│ └── 2.html
└── work
└── work
7 directories, 8 files
[root@localhost overlay]# cat upper/1.html #用户使用的挂载点,显示的内容跟可写层相关
1
123123
[root@localhost overlay]# cat merged/1.html
1
123123
[root@localhost overlay]# cat upper/2.html
2
222222
[root@localhost overlay]# cat merged/2.html
2
222222
b.删除
[root@localhost overlay]# rm -rf merged/2.html #删除数据,在可写层标记文件删除
#挂载点向下读取时,经过可写层标记已删除,即不在挂载点显示
#本质上没有删除lower仅读层的数据
[root@localhost overlay]# tree .
.
├── lower1
│ └── 1.html
├── lower2
│ └── 2.html
├── lower3
│ └── 3.html
├── merged
│ ├── 1.html
│ └── 3.html
├── upper
│ ├── 1.html
│ └── 2.html
└── work
└── work
7 directories, 7 files
[root@localhost overlay]# ls -l upper/*
-rw-r--r-- 1 root root 9 1月 5 18:21 upper/1.html
c--------- 1 root root 0, 0 1月 5 18:22 upper/2.html #可写层中,文件类型为c,表示:标记文件删除
#以下操作不合理,只是为了演示:在挂载点处删除的文件,本质上没有对lower仅读层文件删除
[root@localhost overlay]# rm -rf upper/2.html #删除可写层中的,标记文件删除
[root@localhost overlay]# tree .
.
├── lower1
│ └── 1.html
├── lower2
│ └── 2.html
├── lower3
│ └── 3.html
├── merged
│ ├── 1.html
│ ├── 2.html #在挂载点中 2.html 找回
│ └── 3.html
├── upper
│ └── 1.html
└── work
└── work
7 directories, 7 files
[root@localhost overlay]# cat merged/2.html #且数据为lower仅读层中数据
2
4)容器中 overlay 存储驱动使用实例
可写层随着容器的删除而删除,可写层所挂载的位置也会删除
(再次强调:仅能对挂载点位置数据进行修改,对其他目录进行修改可能会造成数据损坏)
[root@localhost ~]# docker run --name wordpress -d wordpress #运行一个wordpress容器
a91d43dd8947b27c32a107650794d6768a7f7e50243ae90c0bb4f743e8d9c514
[root@localhost ~]# docker exec -it wordpress /bin/bash #进入容器,到 /root/ 下创建文件
root@a91d43dd8947:/var/www/html# cd && ls
root@a91d43dd8947:~# touch yangqindaociyiyou
root@a91d43dd8947:~#
exit
[root@localhost ~]# find /var/lib/docker/overlay/ -name yangqindaociyiyou #在本地找到刚才创建文件的位置
/var/lib/docker/overlay/cfd7b36a48172c0f7739759b690d43f4b0ab7b95a89b77e39d57e42b19937e73/upper/root/yangqindaociyiyou
/var/lib/docker/overlay/cfd7b36a48172c0f7739759b690d43f4b0ab7b95a89b77e39d57e42b19937e73/merged/root/yangqindaociyiyou
[root@localhost ~]# ls /var/lib/docker/overlay/cfd7b36a48172c0f7739759b690d43f4b0ab7b95a89b77e39d57e42b19937e73
lower-id merged upper work
#lower-id:记录可写层
#merged:挂载点位置
#upper:可写层目录
#work:工作缓存目录
#下面测试:在挂载目录创建文件,进入容器中验证文件存在(即验证容器使用 overlay 文件系统)
[root@localhost ~]# cd /var/lib/docker/overlay/cfd7b36a48172c0f7739759b690d43f4b0ab7b95a89b77e39d57e42b19937e73/merged/
[root@localhost merged]# ls root/
yangqindaociyiyou
[root@localhost merged]# touch root/daociyiyouyangqin
[root@localhost merged]# docker exec -it wordpress /bin/bash
root@a91d43dd8947:/var/www/html# cd ;ls
daociyiyouyangqin yangqindaociyiyou


