1)回顾Storage Driver
Docker镜像是采用分层结构的,如下图:
当基于镜像启动一个容器,容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存储在这些层中,分层结果最大的特性: copy-on-write (分发高效)
- 当启动容器后,由一个容器层,数据会直接存放在最上面的容器层
- 当修改容器里现有的数据,会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层,镜像层保持不变
- 如果多个层有命名相同的文件,用户只能看到最上面的那一层文件
存储驱动: 实现多层数据的堆叠并未用户提供合并后的统一视图
Docker支持多种存储驱动,比如aufs,overlayfs2等
[root@blog-xhaihua ~]# docker infoClient:Debug Mode: falseServer:Containers: 9Running: 7Paused: 0Stopped: 2Images: 9Server Version: 19.03.13Storage Driver: overlay2Backing Filesystem: xfsSupports d_type: trueNative Overlay Diff: false#Centos系统: overlay2
对于某些容器,直接将数据由storage driver维护的层中是很好的选择,比如哪些无状态应用(无状态应用: 数据不需要持久化的),但是对于有状态应用(比如MySQL,redis,mongodb等),数据由storage driver维护的层中,就不合适,因为如下:
- 容器异常终止,存储在容器里的数据会丢失
- 数据无法持久化
因此Docker引入另一种存储机制: Data Volume
2)存储卷类型

2.1)绑定挂载存储卷
定义: 主机文件系统上用户指定位置,将Host主机上已存在的目录或文件mount到容器
例如:
把宿主机htdocs目录挂载到容器的/usr/local/apache2/htdocs[root@blog-xhaihua ~]# docker run -itd -p 82:80 -v ~/htdocs:/usr/local/apache2/hddocs httpd7a478bd418dd1b8663fa060c41e405143f300db51138c2a11a327e80db17f112[root@blog-xhaihua ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES7a478bd418dd httpd "httpd-foreground" 5 seconds ago Up 3 seconds 0.0.0.0:82->80/tcp zealous_cartwright-v的格式: <宿主机目录>:<容器目录> 如果容器目录存在数据,原有数据会被隐藏,取而代之的是宿主机目录下的数据
应用场景: 比较适合需要试用特殊挂载点的工作站
缺点: 灵活性查,需要指定hosts文件系统的特定路径,限制了容器的移植性
2.2)Docker管理存储卷
定义: 当执行docker run 使用-v选项,只需要指定容器目录中的挂载点,不需要执行宿主机目录,管理卷即可创建
[root@blog-xhaihua ~]# docker run -itd --name test -p 82:80 -v /usr/local/apache2/hddocs httpd# docker inspect test"Mounts": [{"Type": "volume","Name": "682c8ad7cc4542eda4b33a019da21f52d78fd977512ed669524e4df3ff34ef98","Source": "/data/docker/volumes/682c8ad7cc4542eda4b33a019da21f52d78fd977512ed669524e4df3ff34ef98/_data","Destination": "/usr/local/apache2/htdocs","Driver": "local","Mode": "","RW": true,"Propagation": ""}],[root@blog-xhaihua _data]# cd /data/docker/volumes/682c8ad7cc4542eda4b33a019da21f52d78fd977512ed669524e4df3ff34ef98/_data[root@blog-xhaihua _data]# lsindex.html特点: 原有容器里的数据,不会被隐藏,会被复制到volume中
3)数据共享
3.1)容器与host宿主机共享数据
- bind mount和docker managed volume
- docker cp (docker cp 宿主机文件 容器ID:容器文件)
3.2)容器之间共享数据
- 将共享数据放到bind mount,然后挂载到多个容器
- 卷容器(常用)
4)卷容器(volume container)
volume container专门为其他容器提供volume的容器,它提供的卷可以是bind mount,也可以是Docker managed volume
通过Docker managed volume#创建卷容器[root@blog-xhaihua _data]# docker create -v /pagedata --name html busyboxa48aee435dbc175660398d613a711a93f8ab55732877bff53aef8c68a946a2f9#启动容器,通过--volumes-from挂载[root@blog-xhaihua _data]# docker run -itd --volumes-from html nginx:1.16f047388265b9f08a8a43802ae8dd2fafdfc5bc55cf2823e1d9fa332a0d96672b#查看[root@blog-xhaihua _data]# docker run -itd --volumes-from html nginx:1.16f047388265b9f08a8a43802ae8dd2fafdfc5bc55cf2823e1d9fa332a0d96672b[root@blog-xhaihua _data]# docker exec -it f04 sh# df -hFilesystem Size Used Avail Use% Mounted onoverlay 40G 6.6G 34G 17% /tmpfs 64M 0 64M 0% /devtmpfs 916M 0 916M 0% /sys/fs/cgroupshm 64M 0 64M 0% /dev/shm/dev/vda1 40G 6.6G 34G 17% /pagedata#通过docker inspect html找到存储目录,然后进入存储目录,创建一个index.html,然后进入容器查看,发现多了一个文件[root@blog-xhaihua _data]# cd /data/docker/volumes/0a20602a2aa5cfd90acf6aa25b19e8831ccc4bfe13a3edc3327f8a0fd4525fc5/_data[root@blog-xhaihua _data]# ls[root@blog-xhaihua _data]# echo "111" > index.html[root@blog-xhaihua _data]# docker exec -it f04 sh# ls /pagedataindex.html
注意:
- docker rm 删除容器的时候,加上-v参数,会将容器使用到的volume一并删除
- 如果删除容器不加-v,就会产生孤儿volume,通过docker volume ls进行维护
4)如何清理Docker占用的磁盘空间
如果Docker一不小心把磁盘空间全占满了,你的服务也就算玩完了
用于查看Docker的磁盘使用情况docker system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLEImages 147 36 7.204GB 3.887GB (53%)Containers 37 10 104.8MB 102.6MB (97%)Local Volumes 3 3 1.421GB 0B (0%)Build Cache 0B 0B可知,Docker镜像占用了7.2GB磁盘,Docker容器占用了104.8MB磁盘,Docker数据卷占用了1.4GB磁盘。docker system prune命令可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)docker system prune -a命令清理得更加彻底,可以将没有容器使用Docker镜像都删掉。注意,这两个命令会把你暂时关闭的容器,以及暂时没有用到的Docker镜像都删掉了
手动清理Docker镜像/容器/数据卷
删除所有关闭的容器:docker ps -a | grep Exit | cut -d ' ' -f 1 | xargs docker rm删除所有dangling镜像(即无tag的镜像):docker rmi $(docker images | grep "^<none>" | awk "{print $3}")删除所有dangling数据卷(即无用的Volume):docker volume rm $(docker volume ls -qf dangling=true)
