1)回顾Storage Driver

Docker镜像是采用分层结构的,如下图:
image.png
当基于镜像启动一个容器,容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存储在这些层中,分层结果最大的特性: copy-on-write (分发高效)

  • 当启动容器后,由一个容器层,数据会直接存放在最上面的容器层
  • 当修改容器里现有的数据,会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层,镜像层保持不变
  • 如果多个层有命名相同的文件,用户只能看到最上面的那一层文件

存储驱动: 实现多层数据的堆叠并未用户提供合并后的统一视图
Docker支持多种存储驱动,比如aufs,overlayfs2等

  1. [root@blog-xhaihua ~]# docker info
  2. Client:
  3. Debug Mode: false
  4. Server:
  5. Containers: 9
  6. Running: 7
  7. Paused: 0
  8. Stopped: 2
  9. Images: 9
  10. Server Version: 19.03.13
  11. Storage Driver: overlay2
  12. Backing Filesystem: xfs
  13. Supports d_type: true
  14. Native Overlay Diff: false
  15. #Centos系统: overlay2

对于某些容器,直接将数据由storage driver维护的层中是很好的选择,比如哪些无状态应用(无状态应用: 数据不需要持久化的),但是对于有状态应用(比如MySQL,redis,mongodb等),数据由storage driver维护的层中,就不合适,因为如下:

  • 容器异常终止,存储在容器里的数据会丢失
  • 数据无法持久化

因此Docker引入另一种存储机制: Data Volume

2)存储卷类型

image.png
2.1)绑定挂载存储卷
定义: 主机文件系统上用户指定位置,将Host主机上已存在的目录或文件mount到容器
例如:

  1. 把宿主机htdocs目录挂载到容器的/usr/local/apache2/htdocs
  2. [root@blog-xhaihua ~]# docker run -itd -p 82:80 -v ~/htdocs:/usr/local/apache2/hddocs httpd
  3. 7a478bd418dd1b8663fa060c41e405143f300db51138c2a11a327e80db17f112
  4. [root@blog-xhaihua ~]# docker ps
  5. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  6. 7a478bd418dd httpd "httpd-foreground" 5 seconds ago Up 3 seconds 0.0.0.0:82->80/tcp zealous_cartwright
  7. -v的格式: <宿主机目录>:<容器目录> 如果容器目录存在数据,原有数据会被隐藏,取而代之的
  8. 是宿主机目录下的数据

应用场景: 比较适合需要试用特殊挂载点的工作站
缺点: 灵活性查,需要指定hosts文件系统的特定路径,限制了容器的移植性

2.2)Docker管理存储卷
image.png
定义: 当执行docker run 使用-v选项,只需要指定容器目录中的挂载点,不需要执行宿主机目录,管理卷即可创建

  1. [root@blog-xhaihua ~]# docker run -itd --name test -p 82:80 -v /usr/local/apache2/hddocs httpd
  2. # docker inspect test
  3. "Mounts": [
  4. {
  5. "Type": "volume",
  6. "Name": "682c8ad7cc4542eda4b33a019da21f52d78fd977512ed669524e4df3ff34ef98",
  7. "Source": "/data/docker/volumes/682c8ad7cc4542eda4b33a019da21f52d78fd977512ed669524e4df3ff34ef98/_data",
  8. "Destination": "/usr/local/apache2/htdocs",
  9. "Driver": "local",
  10. "Mode": "",
  11. "RW": true,
  12. "Propagation": ""
  13. }
  14. ],
  15. [root@blog-xhaihua _data]# cd /data/docker/volumes/682c8ad7cc4542eda4b33a019da21f52d78fd977512ed669524e4df3ff34ef98/_data
  16. [root@blog-xhaihua _data]# ls
  17. index.html
  18. 特点: 原有容器里的数据,不会被隐藏,会被复制到volume

绑定挂载和管理卷的不同点,如下图:
image.png

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

  1. 通过Docker managed volume
  2. #创建卷容器
  3. [root@blog-xhaihua _data]# docker create -v /pagedata --name html busybox
  4. a48aee435dbc175660398d613a711a93f8ab55732877bff53aef8c68a946a2f9
  5. #启动容器,通过--volumes-from挂载
  6. [root@blog-xhaihua _data]# docker run -itd --volumes-from html nginx:1.16
  7. f047388265b9f08a8a43802ae8dd2fafdfc5bc55cf2823e1d9fa332a0d96672b
  8. #查看
  9. [root@blog-xhaihua _data]# docker run -itd --volumes-from html nginx:1.16
  10. f047388265b9f08a8a43802ae8dd2fafdfc5bc55cf2823e1d9fa332a0d96672b
  11. [root@blog-xhaihua _data]# docker exec -it f04 sh
  12. # df -h
  13. Filesystem Size Used Avail Use% Mounted on
  14. overlay 40G 6.6G 34G 17% /
  15. tmpfs 64M 0 64M 0% /dev
  16. tmpfs 916M 0 916M 0% /sys/fs/cgroup
  17. shm 64M 0 64M 0% /dev/shm
  18. /dev/vda1 40G 6.6G 34G 17% /pagedata
  19. #通过docker inspect html找到存储目录,然后进入存储目录,创建一个index.html,然后进入容器查看,发现多了一个文件
  20. [root@blog-xhaihua _data]# cd /data/docker/volumes/0a20602a2aa5cfd90acf6aa25b19e8831ccc4bfe13a3edc3327f8a0fd4525fc5/_data
  21. [root@blog-xhaihua _data]# ls
  22. [root@blog-xhaihua _data]# echo "111" > index.html
  23. [root@blog-xhaihua _data]# docker exec -it f04 sh
  24. # ls /pagedata
  25. index.html

注意:

  • docker rm 删除容器的时候,加上-v参数,会将容器使用到的volume一并删除
  • 如果删除容器不加-v,就会产生孤儿volume,通过docker volume ls进行维护

4)如何清理Docker占用的磁盘空间

如果Docker一不小心把磁盘空间全占满了,你的服务也就算玩完了

  1. 用于查看Docker的磁盘使用情况
  2. docker system df
  3. TYPE TOTAL ACTIVE SIZE RECLAIMABLE
  4. Images 147 36 7.204GB 3.887GB (53%)
  5. Containers 37 10 104.8MB 102.6MB (97%)
  6. Local Volumes 3 3 1.421GB 0B (0%)
  7. Build Cache 0B 0B
  8. 可知,Docker镜像占用了7.2GB磁盘,Docker容器占用了104.8MB磁盘,Docker数据卷占用了1.4GB磁盘。
  9. docker system prune命令可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)
  10. docker system prune -a命令清理得更加彻底,可以将没有容器使用Docker镜像都删掉。注意,这两个命令会把你暂时关闭的容器,
  11. 以及暂时没有用到的Docker镜像都删掉了

手动清理Docker镜像/容器/数据卷

  1. 删除所有关闭的容器:
  2. docker ps -a | grep Exit | cut -d ' ' -f 1 | xargs docker rm
  3. 删除所有dangling镜像(即无tag的镜像):
  4. docker rmi $(docker images | grep "^<none>" | awk "{print $3}")
  5. 删除所有dangling数据卷(即无用的Volume):
  6. docker volume rm $(docker volume ls -qf dangling=true)