docker存储
docker存储
1 docker volume类型
docker分层结构
如图所示,容器是由最上面可读可写的容器层,以及若干个只读镜像层组成,创建容器时,容器中的
数据都来自镜像层。这样的分层机构最大的特点是写时复制:
1、容器中新生成的数据会直接存放在容器层,也可以称之为可写层。
2、修改容器中现有的数据会先从镜像层将数据复制到容器层,修改后的数据就会直接保存在容器层,而
镜像层数据不会有任何变化。
3、如果多个镜像层中有相同的命名文件,在容器层只会看到最上面镜像层的内容。

联合挂载技术
Docke镜像采用这种分层构建设计,能使镜像结构和容器的创建,共享和分发变得非常高效,每个镜
像层可以称之为layer,这些layer被存放在了/var/lib/docker/volume//目录下,这里
的storage-driver可以有很多种,比如AUFS、OverlayFS、VFS、Brtfs等。可以通过docker info命令查
看存储驱动,通常Ubuntu类的系统默认采用的是AUFS,Centos7.1+系列采用的是OverlayFS。
OverlayFS是一种堆叠文件系统,它依赖并建立在其它的文件系统之上(例如ext4fs和xfs等等),并
不直接参与磁盘空间结构的划分,仅仅将原来底层文件系统中不同的目录进行合并,然后向用户呈现,这
也就是联合挂载技术,如图所示。 而Linux内核为Docker提供的OverlayFS驱动有两种:overlay和
overlay2。而overlay2是相对于overlay的一种改进,在inode利用率方面比overlay更有效。但是overlay
有环境需求:Docker版本17.06.02+,宿主机文件系统需要是ext4或xfs格式。

data volume
默认情况下,在容器内创建的所有文件都存储在可写容器层上。这意味着,当该容器不再存在时,数
据将不会持久保存,并且如果另一个进程需要它,则可能很难从容器中取出数据。为了能够保存持久化数
据,Docker提出了volume的概念。
为了能够保存持久化数据,Docker提出了volume的概念。简单来说,volume就是目录或者文件,
它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于Docker Host文件系统上。
Docker为容器提供了两个选项来将文件存储在主机中,以便即使容器停止后文件也可以持久存储。
Volume类型:
– Bind mounts 宿主机——》容器
– Docker managed volume 容器——》宿主机
bind mounts
Bind mounts只需要在创建容器时,使用-v参数指明Docker host目录或文件和容器目录或文件映射的对应关系,
将本地的数据映射到容器内,可以使用多个-v映射多个目录或文件,还需要注意的是目录只能映射目录,文件只能映射
文件,不然会报错。实例如下:
1、在Docker host中创建目录,与容器的/usr/share/nginx/html目录做映射,在容器中/usr/share/nginx/html
目录已经存在,如果不存在,会自动创建路径,映射时会隐藏容器中原本的数据,取而代之的是Docker host上的
/html目录中的数据。
[root@ws ~]# mkdir /html
[root@ws ~]# cd /html/
[root@ws html]# ls
[root@ws html]# echo 123 > index.html
[root@ws html]# cat index.html
123
[root@ws html]# docker run -itd --name ws -P -v /html:/usr/share/nginx/html nginx:latest
e620986c98049b856672c0906c459144fd8e6e4b5cf3d26e89f03b7b62d4b9a5
[root@ws html]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e620986c9804 nginx:latest "/docker-entrypoint.…" 23 seconds ago Up 22 seconds 0.0.0.0:32768->80/tcp, :::32768->80/tcp ws
[root@ws html]# curl http://192.168.110.10:32768
123
[root@ws html]#
2、当Docker host上的数据发生了变化,容器中的数据也会随着发生变化,示例如下。
[root@ws ~]# echo 22222 > /html/index.html
[root@ws ~]# curl http://192.168.110.10:32768
22222
3、就算是把容器删除,也不会影响到Docker host上的数据,示例如下。
[root@ws ~]# docker rm ws -f
ws
[root@ws ~]# cat /html/index.html
22222
4、此外,Bind mounts还可以指定数据的读写权限,默认权限是可读可写,示例如下,在映射volume时,指定
容器中的文件权限只读,那么在容器内该文件只能被读取,无法修改,这样也提高了容器的安全性。
[root@ws ~]# docker run -itd --name ws -P -v /html/index.html:/usr/share/nginx/html/index.html:ro nginx:latest
d4691fb360c9d4e9d1774cb17a170c750e282ef7109d07728631c8e679d64d93
[root@ws ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4691fb360c9 nginx:latest "/docker-entrypoint.…" 15 seconds ago Up 14 seconds 0.0.0.0:32769->80/tcp, :::32769->80/tcp ws
[root@ws ~]# curl http://192.168.110.10:32769
22222
[root@ws ~]# docker exec -it ws /bin/bash
root@d4691fb360c9:/# cd /usr/share/nginx/html/
root@d4691fb360c9:/usr/share/nginx/html# ls
50x.html index.html
root@d4691fb360c9:/usr/share/nginx/html# echo 123 > index.html
bash: index.html: Read-only file system
通过上面的示例,我们已经理解了Bind mounts的使用,但是它也有自身的不足之处,使用时需要指定Docker
host上的文件或目录为源数据,这样就限制了容器的可移植性。例如,当需要把容器移动到其他的Docker host上的时
候,如果对方Docker host上没有源数据库,或者路径不相同,操作会失败
docker managed volume
第二种volume类型是由Docker管理的volume,与Bind mounts相比,Docker管理的volume在使用时不需要指
定Docker host路径,Docker管理的volume具有以下几个优点:
1、与Bind mounts相比,Docker管理的volume更易于备份或迁移。
2、用户可以使用Docker CLI命令或Docker API管理volume。
3、volume在Linux和Windows容器上均可工作。
4、可以在多个容器之间更安全地共享volume,提供volume加密功能。
6、可以通过容器预先填充新volume的内容。
实例如下:
1、通过-v告诉Docker需要一个volume,并将其mount到/usr/share/nginx/html目录,那么Docker会在
/var/lib/docker/volumes/目录下创建volume。
[root@ws ~]# docker run -itd --name ws -P -v /usr/share/nginx/html nginx:latest
a27cba34202c933dcf916b056e5384782d935829052c3c7750b935875855c06b
2、使用docker inspect查看容器的mounts部分,可以看到docker host上的
/var/lib/docker/volumes/a68f8571b3a92399f8a2507816e8bc744abe38cb430dcd3ff0fe54d322722365/_data目录已经挂在到容器中
/usr/share/nginx/html目录下,但是查看Docker host的volume中内容,内容是容器中的数据。也就是说使用Docker管理的volume,在做映射时,会把容
器中的数据映射到Docker host。

[root@ws ~]# ls /var/lib/docker/volumes/a68f8571b3a92399f8a2507816e8bc744abe38cb430dcd3ff0fe54d322722365/_data
50x.html index.html
3、我们修改volume中的数据,再访问,发现volume中修改的数据会同步到容器中的。
[root@ws ~]# cd /var/lib/docker/volumes/a68f8571b3a92399f8a2507816e8bc744abe38cb430dcd3ff0fe54d322722365/_data/
[root@ws _data]# ls
50x.html index.html
[root@ws _data]# echo 666 > index.html
[root@ws _data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a27cba34202c nginx:latest "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:32770->80/tcp, :::32770->80/tcp ws
[root@ws _data]# curl http://192.168.110.10:32770
666
4、我们还可以是使用docker volume命令查看docker管理的有哪些volume,并且还可以创建volume,示例如
下,创建一个volume,名为cyhuayu。在创建新的容器时,可以直接指定使用该volume。
[root@ws ~]# docker volume ls
DRIVER VOLUME NAME
local 0e9415cf26409bd68053d7786a65720e5b79e139938c3dcdd18fc385afeebc08
local 382b6383ac6660bad1af2475c4120c737245dd0da10b26835d530b5ab01e3117
local 4719e84a993a41db6f5a2fd416a01cc991a5ff1fd8525dcfbaad1cacc673112f
local 603492699b26c15e1162bee1121a7b0e8248bbeb0057f54dae11682a8168c2d3
local a68f8571b3a92399f8a2507816e8bc744abe38cb430dcd3ff0fe54d322722365
local a583fefaf5ed80c3c94af0ab2fad1e1b1d1a20a2cf78f4d6798c5327cfca17c7
local b1e901452a391e1fe1d8a8ad0b62957ee2388083e1fd2e5be1f53686639128c7
local b1451ac8472cc50f5c0c07dd00e566793a1db377eb38a18305960d0337dda12f
local bb8d0ef0be844ef771c0b2260da443e0faa1381b71d00c1bd58ee2f8fb32eebb
local bd0fab579f7b289be0de03a12d246d36632d67cf1d48d9ab545dd6b718798ea1
local e45430f078b9258de03ff8ae0caa0e9e9ac5337e654f1c264db4c88e386dfc78
[root@ws ~]# docker volume create ws
ws
[root@ws ~]# docker volume ls
DRIVER VOLUME NAME
local 0e9415cf26409bd68053d7786a65720e5b79e139938c3dcdd18fc385afeebc08
local 382b6383ac6660bad1af2475c4120c737245dd0da10b26835d530b5ab01e3117
local 4719e84a993a41db6f5a2fd416a01cc991a5ff1fd8525dcfbaad1cacc673112f
local 603492699b26c15e1162bee1121a7b0e8248bbeb0057f54dae11682a8168c2d3
local a68f8571b3a92399f8a2507816e8bc744abe38cb430dcd3ff0fe54d322722365
local a583fefaf5ed80c3c94af0ab2fad1e1b1d1a20a2cf78f4d6798c5327cfca17c7
local b1e901452a391e1fe1d8a8ad0b62957ee2388083e1fd2e5be1f53686639128c7
local b1451ac8472cc50f5c0c07dd00e566793a1db377eb38a18305960d0337dda12f
local bb8d0ef0be844ef771c0b2260da443e0faa1381b71d00c1bd58ee2f8fb32eebb
local bd0fab579f7b289be0de03a12d246d36632d67cf1d48d9ab545dd6b718798ea1
local e45430f078b9258de03ff8ae0caa0e9e9ac5337e654f1c264db4c88e386dfc78
local ws
[root@ws ~]# docker run -itd --name ws -P -v ws:/usr/share/nginx/html nginx:latest
d8bebb1927778e56983b5389d51d3ce76b0966c4dde76ae8f0d2c9683c22fe05
[root@ws ~]# cd /var/lib/docker/volumes/ws/
[root@ws ws]# ls
_data
[root@ws ws]# cd _data/
[root@ws _data]# ls
50x.html index.html
[root@ws _data]# echo 555 > index.html
[root@ws _data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8bebb192777 nginx:latest "/docker-entrypoint.…" 58 seconds ago Up 57 seconds 0.0.0.0:32771->80/tcp, :::32771->80/tcp ws
[root@ws _data]# curl http://192.168.110.10:32771
555
两种volume不同点
在使用docker volume命令创建volume时,volume默认都是存在在本地的,实际上本地的volume
就是一个目录。除此之外Docker还支持在外部存储系统上创建volume,比如:NFS、Ceph等。
目前我们已经学习了Docker的两种volume的理论和基本操作,它们两者之间的相同点都是使用
Docker host文件系统中的某个路径。不同点如下表所示:

2 容器之间数据共享
数据共享
实现容器间数据共享的方法如下:
– 第一种方法是将共享数据放在volume中,然后将其mount到多个容器。
– 第二种方法是使用volume container,volume container是用来为其他容器提供volume的容器。
这样可以提高容器的可移植性。
– 第三种方法是将数据打包到镜像中,然后通过–volumes-from共享
容器之间共享数据
第一种方法是将共享数据放在volume中,然后将其mount到多个容器。示例如下,创建由三个nginx容器组成的
web集群,使用相同的html文件。在使用-v指定volume时,可以是Docker host的路径或者是Docker创建的volume
[root@ws ~]# docker run -itd --name ws -p 8081:80 -v /html:/usr/share/nginx/html nginx:latest
64e99e829134909ac97c6052e33ccb6c34603af90becf26250320e10f609c554
[root@ws ~]# docker run -itd --name ws1 -p 8082:80 -v /html:/usr/share/nginx/html nginx:latest
f02863bfd4510fcec453f7e5bfd3526af6ea862903479fd20306b81522da339f
[root@ws ~]# docker run -itd --name ws3 -p 8083:80 -v /html:/usr/share/nginx/html nginx:latest
1605bd618915da89c71061b0bc98de21358784abc59077abe3987bd02888f97c
[root@ws ~]# curl http://192.168.110.10:8081
22222
[root@ws ~]# curl http://192.168.110.10:8082
22222
[root@ws ~]# curl http://192.168.110.10:8083
22222
[root@ws ~]# echo 111 > /html/index.html
[root@ws ~]# curl http://192.168.110.10:8083
111
[root@ws ~]# curl http://192.168.110.10:8082
111
[root@ws ~]# curl http://192.168.110.10:8081
111
volume container
第二种方法是使用volume container,volume container是用来为其他容器提供volume的容器。这样可以提高容
器的可移植性。
创建volume container,容器名为ws_data,使用-v指定了volume,提供html文件。需要注意的是,这里使用的
是docker create创建的容器,也就是说容器只是创建了,并未启动,因为volume container只是提供数据,自身并不
需要运行
[root@ws ~]# docker create --name ws_data -v /html/:/usr/share/nginx/html busybox:latest
fee82906dcbde70d9abe82d383d8ba7185d26405b9e6799ab083deb39b61df2a
[root@ws ~]# docker run -itd --name ws1 -p 8081:80 --volumes-from ws_data nginx:latest
2472448cb82b764f35421b161511bbd5b5629626cc949547950461f6273fb1d5
[root@ws ~]# docker run -itd --name ws2 -p 8082:80 --volumes-from ws_data nginx:latest
153a52a40cd512e6a9c7db186afeae2daf22d65426189174be9ef6330c6587a1
[root@ws ~]# docker run -itd --name ws3 -p 8083:80 --volumes-from ws_data nginx:latest
dfc13781e582a43b152f7b913de5b5309397bea14e7d7612b0dc730218bb0a5d
通过docker inspect查看容器信息中的Mounts部分,可以看到新创建的nginx容器已经使用了ws_data容器所提供
的volume。经过验证三个nginx容器中的html文件一样。
[root@ws ~]# curl http://192.168.110.10:8081
111
[root@ws ~]# curl http://192.168.110.10:8082
111
[root@ws ~]# curl http://192.168.110.10:8083
111
与第一种实现数据共享的方法相比,不必再为每个容器指定volemu,所有volume都在volume container 中定义
好了,容器只需与volume container关联,实现了容器与Docker host的解耦
data-packed volume container
volume container的数据归根到底还是在Docker host里,对容器的可移植性有一定的限制。这里可以使用datapacked
volume container。其原理是将数据打包到镜像中,然后通过–volumes-from共享。
示例如下,使用Dockerfile构建镜像,将Docker host中的数据进行打包。ADD指令是将html目录中的数据添加到
容器目录/usr/share/nginx/html中。VOLUME指令的作用与-v效果相同,用来创建volume,并且会把
/usr/share/nginx
/html目录中的数据复制到volume中。
[root@ws ~]# mkdir html
[root@ws ~]# echo 1123 > html/index.html
[root@ws ~]# vim Dockerfile
[root@ws ~]# cat Dockerfile
FROM busybox:latest
ADD html /usr/share/nginx/html
VOLUME /usr/share/nginx/html
CMD ["/bin/bash"]
[root@ws ~]# docker build -t ws1 .
[+] Building 0.4s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 135B 0.0s
=> [internal] load metadata for docker.io/library/busybox:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 75B 0.0s
=> [1/2] FROM docker.io/library/busybox:latest 0.0s
=> [2/2] ADD html /usr/share/nginx/html 0.1s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:d305131fee14755c40e5c092faff5ed48dfcf8b6f57ef141e8031a0152905bb2 0.0s
=> => naming to docker.io/library/ws1 0.0s
使用新构建的镜像创建data-packed volume container,创建新的nginx容器,使用参数–volumes-from
指定使用ws_data123容器提供的volume。
[root@ws ~]# docker create --name ws_data123 ws1:latest
1683a1fbe76900dc23eff3ad8dd67ecde6dc985a01e9bd94caff89a4e246f862
[root@ws ~]# docker run -itd --name ws1 -p 8081:80 --volumes-from ws_data123 nginx:latest
c5dded3cab45e78b889fa83dc49ad940a11bdc64e983e0db75421a5753a901fe
[root@ws ~]# docker run -itd --name ws2 -p 8082:80 --volumes-from ws_data123 nginx:latest
1a692726aee4ea936fecc719c945e3d0bfe5829ac6572279bad28fb11dc4ee8c
[root@ws ~]# curl http://192.168.110.10:8081
1123
[root@ws ~]# curl http://192.168.110.10:8082
1123
更多推荐



所有评论(0)