Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写下面的只读层复制到读写层,该文件的只读版本依然存在,只是已经被读写层中该文件的副本所隐藏,即写时复制(COW)
机制。
卷为docker提供了独立于容器的数据管理机制:
程序
,把卷类比为动态内容,例如数据
,于是,镜像可以重用,而卷可以共享程序(镜像)
和数据(卷)
分离,以及程序(镜像)
和制作镜像的主机
分离,用户制作镜像时无须再考虑镜像运行的容器所在的主机环境。Docker的存储卷有两种类型:
dockerd
来管理,默认是宿主机上的/var/lib/docker/volumes/<volume ID>
为docker container run
命令使用-v
选项即可使用volume。
Bind moutn volume创建方式
root@node01:~# docker container run -i -t --rm --name bbox01 -v /data/pub/html:/data/html busybox:latest
/ # ls /data/html/
/ #
-v /data/pub/html:/data/html
分号前表示宿主机上的绑定目录,分号后表示容器内的绑定目录,目录如果不存在会自动创建。
如果要绑定多个目录关系,-v
选项可以使用多次。
到宿主机上查看是否有/data/pub/html
目录
root@node01:~# ls /data/pub/html/
root@node01:~# echo "hello..." > /data/pub/html/index.html
root@node01:~# ls /data/pub/html/
index.html
目录被自动创建,并且增加了一个文件,再回到容器内查看,也能查看到相应的文件
root@node01:~# docker container run -i -t --rm --name bbox01 -v /data/pub/html:/data/html busybox:latest
/ # ls /data/html/
/ # ls /data/html/
index.html
查看容器的详细信息可以看到mount的详细信息
root@node01:~# docker inspect bbox01
...
"Mounts": [
{
"Type": "bind",
"Source": "/data/pub/html",
"Destination": "/data/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...
Docker mananged volume创建方式
root@node01:~# docker container run -i -t --rm --name bbox01 -v /data/html busybox:latest
/ # ls /data/html/
/ # echo "hello word." > /data/html/index.html
/ #
-v /data/html
只有一个路径时表示的是容器内部的目录。
可以探测下存储卷在宿主机上的位置
root@node01:~# docker inspect bbox01
...
"Mounts": [
{
"Type": "volume",
"Name": "8c1be16f1b119faba6006b98b7763ce141f8fe2243cc2b970660aac0f33416a4",
"Source": "/var/lib/docker/volumes/8c1be16f1b119faba6006b98b7763ce141f8fe2243cc2b970660aac0f33416a4/_data",
"Destination": "/data/html",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
...
root@node01:~# docker inspect -f {{.Mounts}} bbox01 # 使用go模板语法进行过滤
[{volume 8c1be16f1b119faba6006b98b7763ce141f8fe2243cc2b970660aac0f33416a4 /var/lib/docker/volumes/8c1be16f1b119faba6006b98b7763ce141f8fe2243cc2b970660aac0f33416a4/_data /data/html local true }]
root@node01:~# cat /var/lib/docker/volumes/8c1be16f1b119faba6006b98b7763ce141f8fe2243cc2b970660aac0f33416a4/_data/index.html
hello word.
宿主机上的一个目录可以绑定给多个容器,即多个容器就可以通过这个存储卷进行数据共享,只需要在启动容器时通过-v
选项进行绑定即可。如果需要共享存储卷的容器较多时,每一个容器都需要-v HOST_DIR:CONTAINER_DIR
指定绑定关系,docker为了简化,在运行容器时可以复制其他容器的存储卷绑定关系来达到挂载与之相同的存储卷。
要想复制其他容器的存储卷绑定关系,使用--volumes-from
选项
先启动一个容器
root@node01:~# docker container run -i -t --rm --name bbox01 -v /data/pub/html:/data/html busybox:latest
/ # ls /data/html/
index.html
/ # cat /data/html/index.html
hello...
/ #
再启动另一个容器,使用--volumes-from
选项复制bbox01
的存储卷信息
root@node01:~# docker container run -i -t --rm --name bbox02 --volumes-from bbox01 busybox:latest
/ # ls /data/html/
index.html
/ # cat /data/html/index.html
hello...
同样可以使用docker inspect
命令查看两个容器存储卷的挂载信息。bbox02
同bbox01
容器实现了挂载相同的存储卷。
结合联盟式网络和存储卷复制的特性,可以实现这样一个架构,nginx + tomcat + mysql
,nginx反代到tomcat,tomcat与mysql进行交互,他们各自运行在一个容器中,通过联盟式网络让三者共享网络名称空间,外部请求nginx的容器地址,nginx与tomcat通信走lo接口,tomcat与mysql通信也走lo接口,网页存放与mysql的数据存放都通过存储卷绑定到宿主机上。
这种架构的实现,一般先制作一个基础架构
容器,该容器可以不处理于运行状态,只要创建好即可,它提供网络名称空间
,存储卷
等基础配置,nginx
,tomcat
和mysql
三个容器在启动时加入到基础架构
容器的网络名称空间,并复制它的存储卷信息。
这样灵活运用联盟网络和存储卷的复制特性可以演变出一些有趣的架构。
原文:https://blog.51cto.com/zhaochj/2536685