Docker 空间使用分析和清理
用户在使用 Docker 部署业务一段时间后,可能会发现宿主节点的磁盘容量持续增长,甚至将磁盘空间耗尽进而引发宿主机异常,进而对业务造成影响。 本文先对 Docker 的空间分析与清理进行说明,然后对容器的磁盘容量限制与使用建议做简要说明。
典型问题场景
用户发现 Docker 宿主机的磁盘空间使用率非常高。通过 du 逐层分析,发现是 Volume 或 overlay2 等目录占用了过高空间。示例如下:
# 根据使用的存储驱动的不同,相应目录会有所不同:
[root@node3 docker]# du -h --max-depth=1 |sort
104K ./network
13M ./image
20K ./plugins
24G ./overlay2 # 这个目录占用了非常高的磁盘磁盘空间
25G .
283M ./volumes
4.0K ./swarm
4.0K ./tmp
4.0K ./trust
518M ./containers
空间使用分析
遇到此类问题,可以参阅如下步骤进行空间分析,定位占用过高空间的业务来源。
分析 Docker 空间分布
Docker 的内置 CLI 指令 docker system df
,可用于查询镜像(Images)、容器(Containers)和本地卷(Local Volumes)等空间使用大户的空间占用情况。 示例输出如下:
[root@node3 docker]# docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 17 12 2.713 GB 1.144 GB (42%)
Containers 15 12 10.75 GB 0 B (0%)
Local Volumes 8 4 282.9 MB 241.8 MB (85%)
查看空间占用细节
可以进一步通过 -v
参数查看空间占用细节,以确定具体是哪个镜像、容器或本地卷占用了过高空间。示例输出如下:
[root@node3 docker]# docker system df -v
# 镜像的空间使用情况
Images space usage:
REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS
busybox latest 6ad733544a63 5 days ago 1.129 MB 0 B 1.129 MB 1
nginx latest b8efb18f159b 3 months ago 107.5 MB 107.5 MB 0 B 4
ubuntu latest 14f60031763d 3 months ago 119.5 MB 0 B 119.5 MB 0
alpine 3.3 606fed0878ec 4 months ago 4.809 MB 0 B 4.809 MB 0
tutum/curl latest 01176385d84a 3 years ago 224.4 MB 0 B 224.4 MB 1
# 容器的空间使用情况
Containers space usage:
CONTAINER ID IMAGE COMMAND LOCAL VOLUMES SIZE CREATED STATUS NAMES
d1da451ceeab busybox "ping 127.0.0.1" 0 10.7 GB About an hour ago Up About an hour dstest
956ae1d241e8 nginx:latest "nginx -g 'daemon ..." 0 26 B 3 months ago Up 3 months localTest_restserver_2
74973d237a06 nginx:latest "nginx -g 'daemon ..." 0 2 B 3 months ago Up 3 months
# 本地卷的空间使用情况
Local Volumes space usage:
VOLUME NAME LINKS SIZE
83ba8747f4172a3c02a15f85b71e1565affca59f01352b4a94e0d28e65c26d1c 0 830 B
a479c303b278f1442f66644f694a554aac630e72b7a27065a11ef85c4d87b648 0 22.16 MB
79a25b6376e0d6587d8f4f24e08f9467981f04daad14bf3353a12d727d065503 1 18.83 MB
空间清理
自动清理
可以通过 Docker 内置的 CLI 指令 docker system prune
来进行自动空间清理。
Tips :
不同状态的镜像
- 已使用镜像(used image): 指所有已被容器(包括已停止的)关联的镜像。即 docker ps -a 看到的所有容器使用的镜像。
- 未引用镜像(unreferenced image):没有被分配或使用在容器中的镜像,但它有 Tag 信息。
- 悬空镜像(dangling image):未配置任何 Tag (也就无法被引用)的镜像,所以悬空。这通常是由于镜像 build 的时候没有指定 -t 参数配置 Tag 导致的。比如:
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 6ad733544a63 5 days ago 1.13 MB # 悬空镜像(dangling image)
挂起的卷(dangling Volume)
类似的,dangling=true 的 Volume 表示没有被任何容器引用的卷。
docker system prune 自动清理说明:
-
该指令默认会清除所有如下资源:
- 已停止的容器(container)
- 未被任何容器所使用的卷(volume)
- 未被任何容器所关联的网络(network)
- 所有悬空镜像(image)。
- 该指令默认只会清除悬空镜像,未被使用的镜像不会被删除。
- 添加
-a 或 --all
参数后,可以一并清除所有未使用的镜像和悬空镜像。 - 可以添加
-f 或 --force
参数用以忽略相关告警确认信息。 - 指令结尾处会显示总计清理释放的空间大小。
操作示例:
[root@node3 docker]# docker system prune --help
Usage: docker system prune [OPTIONS]
Remove unused data
Options:
-a, --all Remove all unused images not just dangling ones
-f, --force Do not prompt for confirmation
--help Print usage
[root@node3 docker]# docker system prune -a
WARNING! This will remove:
- all stopped containers
- all volumes not used by at least one container
- all networks not used by at least one container
- all images without at least one container associated to them
Are you sure you want to continue? [y/N] y
Deleted Containers:
c09c31c49491ee7f2324160e43947917940221b4e6cc1274906def640a7a631f
2aa0180e1a0f4c2c64349a6ed969651052373e7a9471050dce9015701cf1b957
6d18003b06823c5d76d807a319387b06680fc93d0a32bc29c1cea4c07e8d515d
Deleted Volumes:
a479c303b278f1442f66644f694a554aac630e72b7a27065a11ef85c4d87b648
79a25b6376e0d6587d8f4f24e08f9467981f04daad14bf3353a12d727d065503
Deleted Images:
untagged: tutum/curl:latest
untagged: tutum/curl@sha256:b6f16e88387acd4e6326176b212b3dae63f5b2134e69560d0b0673cfb0fb976f
deleted: sha256:01176385d84aeb1d40ed18c6d3f952abf40d2d2b4aa98fcf0a8a4b01010fb9a9
deleted: sha256:c84f85637212412c1d46d1dd50f789df2c3b44678ee3fee6a820888e734f9b5a
untagged: test:lastest
deleted: sha256:794ff09332586a091514eb3d1c44990244e57e34adc71d4b4334c0674a1377e9
deleted: sha256:636a1e7769d2242556243e9a21fb96bb878ab5b94c41ff485667252c968b375e
Total reclaimed space: 1.565 GB
手工清理
网络清理
网络配置通常占用的空间非常低,略过。
镜像清理
如果通过 docker system df 分析,是镜像占用了过高空间。则可以根据业务情况,评估相关镜像的使用情况。对于悬空和未使用的镜像, 可以使用如下指令手工清理:
# 删除所有悬空镜像,但不会删除未使用镜像:
docker rmi $(docker images -f "dangling=true" -q)
# 删除所有未使用镜像和悬空镜像。
# 【说明】:轮询到还在被使用的镜像时,会有类似"image is being used by xxx container"的告警信息,所以相关镜像不会被删除,忽略即可。
docker rmi $(docker images-q)
卷清理
如果通过 docker system df 分析,是卷占用了过高空间。则可以根据业务情况,评估相关卷的使用情况。对于未被任何容器调用的卷(-v 结果信息中,"LINKS" 显示为 0),可以使用如下指令手工清理:
# 删除所有未被任何容器关联引用的卷:
docker volume rm $(docker volume ls -qf dangling=true)
# 也可以直接使用如下指令,删除所有未被任何容器关联引用的卷(但建议使用上面的方式)
# 【说明】轮询到还在使用的卷时,会有类似"volume is in use"的告警信息,所以相关卷不会被删除,忽略即可。
docker volume rm $(docker volume ls -q)
容器清理
如果通过 docker system df 分析,是某个容器占用了过高空间。则可以根据业务情况,评估相关容器的业务归属并进行处理。对于已停止或其它异常状态的容器,可以结合 -f 或 --filter
筛选器,使用类似如下指令来手工清理:
# 删除所有已退出的容器
docker rm -v $(docker ps -aq -f status=exited)
# 删除所有状态为 dead 的容器
docker rm -v $(docker ps -aq -f status=dead)
更多关于 ps 指令支持的筛选器信息,可以参阅官方文档。
在用空间资源分析
对于还在使用的空间资源,可以参阅如下说明做进一步排查分析。
镜像空间分析
如果某个镜像占用了过高空间,则可以通过如下方式做进一步空间分析:
- 通过 docker system df 获取占用过高空间的镜像信息。
- 基于相应镜像创建测试容器。
- exec 进入容器后,结合 du 等 shell 指令做进一步空间分析,定位出占用最高空间的目录或文件。
- 结合业务情况做进一步处理,重新 build 镜像。
示例:
[root@node3]# docker exec -it dstest sh
/ # du -h | head
8.0K ./root
32.0K ./etc
4.0K ./usr/sbin
8.0K ./usr
10.0G ./home/java/logs
10.0G ./home/java
10.0G ./home
1.1M ./bin
0 ./dev/shm
0 ./dev/mqueue
容器空间分析
如果某个运行中的容器占用了过高空间,则可以通过如下方式做进一步空间分析:
Tips :
容器的只读层与镜像层的空间占用情况
一个容器的占用的总空间,包含其最顶层的读写层(writable layer)和底部的只读镜像层(base image layer,read-only)。更多相关说明,可以参阅官方文档。
可以通过 docker ps 的-s
参数来分别显示二者的空间占用情况,进而判断相应容器的空间占用主要是来自原始镜像,还是运行中产生。
示例:
# 如下容器的原始镜像占用了 422MB 空间,实际运行过程中只占用了 2B 空间:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE
ac39128ccbc0 registry.aliyuncs.com/acs-sample/wordpress:4.6 "/entrypoint.sh ap..." 3 months ago Up 11 days 0.0.0.0:32779->80/tcp Web_web_4 2 B (virtual 422 MB)
容器空间占用的分析步骤:
- 通过 docker system df 获取占用过高空间的容器信息。
- 通过前述
-s
参数确认到底是底层镜像,还是运行过程中产生的数据占用了过高空间。 - exec 进入容器,结合 du 等 shell 指令做进一步空间分析,定位出占用最高空间的目录或文件。
- 结合业务情况做进一步处理。
引申:Docker 磁盘空间限制与使用建议
磁盘空间限制
使用 Device Mapper 存储驱动限制容器磁盘空间
如果使用 Device Mapper 作为底层存储驱动,则可以通过 Docker daemon 的如下参数来全局限制单个容器占用空间的大小:
-
--storage-opt dm.basesize=20G
表示限制单个容器最多占用 20G 空间,将应用于任何新建容器。
更多关于 Device Mapper 存储驱动的说明,可以参阅官方文档。
使用 btrfs 存储驱动限制容器磁盘空间
btrfs 驱动主要使用 btrfs 所提供的 subvolume 功能来实现。一个容器会对应一个 subvolume。针对容器对应的 subvolume 启用并配置 quota 即可限制其磁盘空间。示例配置:
btrfs qgroup limit -e 50G /var/lib/docker/btrfs/subvolumes/<CONTAINER_ID>
btrfs 还有其它很好的特性,比如可以在线扩容(在线加入一块新的块设备,来扩充整个文件系统的大小)。更多关于 btrfs 存储驱动的说明,可以参阅官方文档。
外挂 LVM 卷
如果使用的是其它不支持对单个容器的磁盘容量进行限制的存储驱动,则可以考虑如下通用方案:
- 通过 LVM 方式创建一个指定容量的卷,然后挂载到宿主操作系统上特定目录。最后通过 --volume 参数来让容器来挂载使用相应目录。
注意:该方案的前提条件是,容器中所有落盘操作要全部落到上述 "--volume" 参数指定的卷中,否则容器还会占用默认 aufs 所在盘的空间,进而造成统计不准。
Docker 存储使用建议
细化的存储使用最佳实践与采用的存储驱动(storage driver)类型强相关,您可以参阅官方文档做相关了解,本文不做进一步细化说明。
通用的存储使用建议如下:
- 容器内的业务日志务必配置轮询覆写,或者使用日志驱动将日志输出到外部存储。避免日志文件持续增长,占用过高磁盘空间。
- 结合外部监控对宿主机的磁盘空间使用情况进行监控和告警。
- 可以参阅文档 如何给容器服务的Docker增加数据盘来扩容默认 Docker 存储空间。
- 转载自 :https://developer.aliyun.com/article/272173
上一篇: 1 个空间资源培训课程
下一篇: Docker 空间使用分析和清理
推荐阅读
-
NotificationManagerService 的使用细节和原理分析(二)
-
使用 Docker 和 Homeassistant,让家庭用电更轻松,帮您省电省钱
-
树莓派 4B 使用 docker 安装 kafka 和 kafka-manger
-
35 岁实现财务*,腾讯程序员手握2300万提前退休?-1000万房产、1000万腾讯股票、加上300万的现金,一共2300万的财产。有网友算了一笔账,假设1000万的房产用于自住,剩下1300万资产按照平均税后20-50万不等进行计算,大约花上26-60年左右的时间才能赚到这笔钱。也就是说,普通人可能奋斗一辈子,才能赚到这笔钱。在很多人还在为中年危机而惶惶不可终日的时候,有的人的35岁,就已经安全着陆,试问哪个打工人不羡慕?但问题是有这样财富积累必然有像样的实力做靠山。没有人可以不劳而获。 看到这里,肯定有人说,那么对于普通人来说,卷可能真就成了唯一的出路。但是卷也有轻松的卷,“偷懒”的卷法,对于程序员而言,刨除掉一时无法改掉的开会传统占用的大部分时间,如何把有限的时间和精力放在真正重要的架构设计、需求设计上,而不是重复的造*,编码、改bug、手动测试。因此在科技改变生活的今天,学会使用AI工具成为程序员们的必备技能。 以全栈式全自动的软件开发工具飞算SoFlu软件机器人为例,作为全球首款面向微服务架构设计和最佳实践的软件机器人,SoFlu软件机器人改变了原来手工编码的作业模式,通过可视化拖拽方式以及参数配置就能实现等同于编写复杂代码的业务逻辑,在设计业务逻辑时就完成了微服务应用开发,做到“业务即图,图即代码”,实现“软件开发,十倍提效”。 而作为飞算SoFlu软件机器人的一个重要组成部分,FuncGPT(慧函数)支持所有类型函数创建。通过自然语言描述Java函数需求,实时生成高质量、高可读性的Java函数代码。生成代码可直接复制到IDEA,或一键导入Java全自动开发工具函数库。 FuncGPT(慧函数)具有五大核心能力: ● 自然语言:通过自然语言即可生成函数,降低软件开发门槛。 ● 秒级函数开发:全自动秒级开发函数,秒级完成,效率千倍提升。 ● 一站式函数开发应用:函数生成即可直接应用,效率、安全有保障。 ● 质量可靠:生成的函数代码符合业界规范、具备良好的可读性,符合最优解。 ● 灵活生成:可以根据开发人员的具体需求生成并支持调整和修改。 以“将文件流转换为File对象”这个需求为例,以下是FuncGPT(慧函数)秒级生成的代码: / 类名:FileConverter // 函数名:convertStreamToFile // 函数功能:将文件流转换为File对象 // POM依赖包:无 import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; public class FileConverter { /** * 将文件流转换为File对象 * @param inputStream 文件流 * @param filePath 文件路径 * @param fileName 文件名 * @return 转换后的File对象 * @throws IOException 如果发生I/O异常 */ public static File convertStreamToFile(InputStream inputStream, String filePath, String fileName) throws IOException { File file = new File(filePath + File.separator + fileName); // 创建File对象 try (FileOutputStream outputStream = new FileOutputStream(file)) { // 创建文件输出流 byte buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { // 从文件流读取数据并写入文件 outputStream.write(buffer, 0, bytesRead); } } return file; // 返回转换后的File对象 } } // 函数示例 // 将文件流转换为File对象示例 // 入参:inputStream,文件流 // 入参:filePath,文件路径 // 入参:fileName,文件名 // 出参:file,转换后的File对象 // 调用示例: // InputStream inputStream = new FileInputStream("example.txt"); // String filePath = "C:\\Users\\User\\Documents"; // String fileName = "example.txt"; // File file = FileConverter.convertStreamToFile(inputStream, filePath, fileName); // System.out.println(file.getAbsolutePath); // 输出结果:例如,将文件流转换为File对象后,文件的绝对路径为:C:\Users\User\Documents\example.txt // 则输出结果为:C:\Users\User\Documents\example.txt 通过分析,不难发现以上代码:
-
使用 ClickHouse("窗口功能")快速实施同比和环比分析
-
大数据分析工具 Power BI (VII):DAX 使用场景和常用功能
-
文本分析--使用 jieba 库进行中文分词和去活字(附案例研究)
-
使用 Docker 和 Streamlit 构建和部署由 LangChain 支持的聊天应用程序
-
正负偏差变量 即 d2+、d2- 分别表示决策值中超出和未达到目标值的部分。而 di+、di- 均大于 0 刚性约束和目标约束(柔性目标约束有偏差) 在多目标规划中,>=/<= 在刚性约束中保持不变。当需要将约束条件转换为柔性约束条件时,需要将 >=/<= 更改为 =(因为已经有 d2+、d2- 用来表示正负偏差),并附加上 (+dii-di+) 注意这里是 +di、-di+!之所以是 +di,-di+,是因为需要将目标还原为最接近的原始刚性约束条件 优先级因素和权重因素 对多个目标进行优先排序和优先排序 目标规划的目标函数 是所有偏差变量的加权和。值得注意的是,这个加权和都取最小值。而 di+ 和 dii- 并不一定要出现在每个不同的需求层次中。具体分析需要具体问题具体分析 下面是一个例子: 题目中说设备 B 既要求充分利用,又要求尽可能不加班,那么列出的时间计量表达式即为:min z = P3 (d3- + d3 +) 使用 + 而不是 -d3 + 的原因是:正负偏差不可能同时存在,必须有 di+di=0 (因为判定值不可能同时大于目标值和小于目标值),而前面是 min,所以只要取 + 并让 di+ 和 dii- 都为正值即可。因此,得出以下规则: 最后,给出示例和相应的解法: 问题:某企业生产 A 和 B 两种产品,需要使用 A、B、C 三种设备。下表显示了与工时和设备使用限制有关的产品利润率。问该企业应如何组织生产以实现下列目标? (1) 力争利润目标不低于 1 500 美元; (2) 考虑到市场需求,A、B 两种产品的生产比例应尽量保持在 1:2; (3)设备 A 是贵重设备,严禁超时使用; (4)设备 C 可以适当加班,但要控制;设备 B 要求充分利用,但尽量不加班。 从重要性来看,设备 B 的重要性是设备 C 的三倍。 建立相应的目标规划模型并求解。 解:设企业生产 A、B 两种产品的件数分别为 x1、x2,并建立相应的目标计划模型: 以下为顺序求解法,利用 LINGO 求解: 1 级目标: 模型。 设置。 variable/1..2/:x;! s_con_num/1...4/:g,dplus,dminus;!所需软约束数量(g=dplus=dminus 数量)及相关参数; s_con(s_con_num);! s_con(s_con_num,variable):c;!软约束系数; 结束集 数据。 g=1500 0 16 15. c=200 300 2 -1 4 0 0 5; 结束数据 min=dminus(1);!第一个目标函数;!对应于 min=z 的第一小部分;! 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); !使用设置完成的数据构建软约束表达式; ! !软约束表达式 @for(variable:@gin(x)); !将变量约束为整数; ! 结束 此时,第一级目标的最优值为 0,第一级偏差为 0: 第二级目标: !求 dminus(1)=0,然后求解第二级目标。 模型。 设置。 变量/1..2/:x;!设置:变量/1..2/:x; ! s_con_num/1...4/:g,dplus,dminus;!软约束数量及相关参数; s_con(s_con_num(s_con_num));! s_con(s_con_num,variable):c;! 软约束系数; s_con(s_con_num,variable):c;! 结束集 数据。 g=1500 0 16 15; c=200 300 2 -1 4 0 0 5; 结束数据 min=dminus(2)+dplus(2);!第二个目标函数 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); ! 软约束表达式;! dminus(1)=0; !第一个目标结果 @for(variable:@gin(x)); ! 结束 此时,第二个目标的最优值为 0,偏差为 0: 第三目标 !求 dminus(2)=0,然后求解第三个目标。 模型。 设置。 变量/1..2/:x;!设置:变量/1..2/:x; ! s_con_num/1...4/:g,dplus,dminus;!软约束数量及相关参数; s_con(s_con_num(s_con_num));! s_con(s_con_num,variable):c;! 软约束系数; s_con(s_con_num,variable):c;! 结束集 数据。 g=1500 0 16 15; c=200 300 2 -1 4 0 0 5; 结束数据 min=3*dminus(3)+3*dplus(3)+dminus(4);!第三个目标函数。 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); ! 软约束表达式;! dminus(1)=0; !第一个目标约束条件; ! dminus(2)+dplus(2)=0; !第二个目标约束条件 @for(variable:@gin(x));! 结束 最终结果为 x1=2,x2=4,dplus(1)=100,最优利润为
-
使用 Python 11.6 进行数据分析的重采样和频率转换 (I)