1. 项目概述:为什么这个错误总在最要命的时候爆发?
“no space left on device”——这行红字,我见过太多次了。它从不挑时间:凌晨三点部署关键服务时弹出来,CI/CD流水线卡在 docker build 最后一步时跳出来,甚至你刚想本地调试一个新功能, docker run 直接报错退出。那种手心冒汗、鼠标悬停在 rm -rf /var/lib/docker 上又不敢点下去的窒息感,老Docker用户都懂。
但我要先说清楚:这不是Docker的bug,而是它在用最直白的方式告诉你——你的存储系统正在崩溃边缘。它背后藏着两种完全不同的病理机制:一种是“肚子饿”,物理磁盘块真被填满了;另一种是“得了厌食症”,明明胃里还有大把空间,可负责管理每份食物的“餐具编号本”(也就是inodes)已经写满,连一张新餐巾纸都登记不上。这两种情况的诊断路径、处理手法、甚至误操作后果,全都不一样。你要是只盯着 df -h 看,90%的概率会走错方向,删掉一堆东西后发现空间没涨多少,反而把某个正在跑的监控容器日志给清空了,告警邮件瞬间刷屏。
我干运维和容器平台支撑十年,经手过从单机开发环境到上千节点K8s集群的所有Docker存储问题。最深的教训就是: 所有看似“快速解决”的暴力清理,都是在给下一次更严重的故障埋雷。 比如有人一上来就 docker system prune -a --volumes ,结果把生产数据库的挂载卷删了,回滚都没法回;也有人看到 /var/lib/docker/overlay2 目录巨大,直接 rm -rf ,导致所有镜像层索引损坏,整个Docker引擎直接瘫痪。这些都不是危言耸听,是我亲手修过的坑。
所以这篇指南,不是给你一堆命令让你复制粘贴,而是带你重建一套完整的“Docker存储健康检查思维”。我会拆解每一个诊断命令背后的逻辑——为什么 df -H 要看 /dev/sdf 而不是 /var/lib/docker ?为什么 docker system df -v 里那个 RECLAIMABLE 列比 SIZE 列重要十倍? truncate -s 0 和 rm 在日志文件上操作,为什么一个安全一个致命?这些细节,决定了你是能优雅地把问题扼杀在萌芽,还是在深夜被电话叫醒,一边重启服务器一边祈祷数据没丢。
如果你现在正对着终端里那行红色报错发呆,别慌。接下来的内容,就是按真实排障顺序写的:从第一眼看到报错,到最终彻底预防,每一步都带着我在生产环境里踩过的坑、验证过的参数、以及那些文档里绝不会写的“小动作”。
2. 核心诊断逻辑:先分清是“饿”还是“病”,再动手
2.1 为什么必须跳过直觉,从底层文件系统开始?
很多人一看到“No Space Left”,第一反应是 docker images 看看有没有几百个没用的镜像,或者 docker ps -a 找找有没有几十个stop状态的容器。这就像医生不量血压不查血常规,光问“你是不是头疼”,然后直接开止痛药。Docker只是应用层,它的存储压力最终都会传导到宿主机的文件系统上。而Linux文件系统有两个独立的资源池: 数据块(blocks) 和 索引节点(inodes) 。它们互不干扰,却都能单独导致“no space left”。
- 数据块耗尽 :好比你家冰箱塞满了,再也放不进一盒牛奶。
df -H显示Use%接近100%,这是最直观的情况。 - inode耗尽 :好比你家厨房的“食材登记本”写满了。冰箱里可能还空着一半,但登记本上最后一行已经被划掉,你买回来的牛奶根本没法记上名字,系统就拒绝存放——这就是
df -i显示IUse%为100%的场景。
提示:在CI/CD服务器、Node.js构建环境、PHP应用服务器上,inode耗尽比磁盘耗尽更常见。因为
npm install会生成数万个node_modules里的小文件,PHP session默认存到/tmp,每次请求都新建一个session文件,几天下来就能把几百万个inodes吃光。而此时df -H可能还显示“Free: 25G”,极具迷惑性。
所以诊断的第一步,永远不是碰Docker命令,而是摸清宿主机的底细。这个动作花不了30秒,但能避免你后面浪费两小时。
2.2 三步定位法:精准锁定问题根源
第一步:全局磁盘与inode扫描(5秒)
打开终端,敲入:
df -H && echo "---" && df -i
这个组合命令会同时输出磁盘使用率和inode使用率。重点看三列:
| 文件系统 | Size | Use% | IUse% |
|---|---|---|---|
/dev/sda1 |
50G | 92% | 45% |
/dev/sdf |
64G | 98% | 99% |
- 如果某一行的
Use%和IUse%都接近100%,恭喜你,问题很明确,就是磁盘块耗尽。 - 如果
Use%只有60%,但IUse%是100%,那问题100%出在inode上,别再看du -sh /var/lib/docker了,那是无效劳动。 - Docker Desktop用户注意 :你在Mac或Windows上看到的
/dev/sdf或/dev/vda,不是你宿主机的硬盘,而是Docker Desktop虚拟机内部的虚拟磁盘。它的Use%高,说明VM里的空间满了,但你宿主机的/分区可能还很空。这时候df -H的输出位置,就是你要盯死的目标。
第二步:Docker专属空间画像(10秒)
确认了是磁盘还是inode问题后,下一步是让Docker自己“交待”钱花在哪了。执行:
docker system df -v
这个命令的输出结构,是理解Docker存储的关键。它分成四个板块:Images、Containers、Local Volumes、Build Cache。每个板块里都有三列核心数据:
- SIZE :当前占用的物理空间大小。
- RECLAIMABLE :这部分空间可以被安全释放,且 不影响任何正在运行的容器 。
- TAGS :镜像的标签数量,0表示“dangling”(悬空),即没有标签也没有容器引用的中间层。
实操心得:我见过太多人只看
SIZE列,看到Build Cache占了40G就慌了,其实只要RECLAIMABLE是40G,说明这些缓存全是“死的”,删了立刻见效。而如果Containers的RECLAIMABLE是0,但SIZE有20G,那就说明这20G是某个正在跑的容器的可写层,你不能动它,得去查是哪个容器在疯狂写日志或临时文件。
第三步:穿透式深度扫描(30秒,仅Linux原生环境)
如果你用的是原生Linux(非Docker Desktop),并且前两步没找到明显元凶,就需要钻到 /var/lib/docker 内部看看到底谁在“囤货”。执行:
sudo du -h --max-depth=1 /var/lib/docker 2>/dev/null | sort -h
这个命令会列出 /var/lib/docker 下一级子目录的大小,比如:
1.2G /var/lib/docker/overlay2
8.4G /var/lib/docker

321

被折叠的 条评论
为什么被折叠?



