悬挂镜像指未被任何标签指向的中间层镜像,可通过docker images -a或docker images -f "dangling=true"识别,应使用docker image prune安全清理,避免误删构建缓存或运行中容器依赖的层。

docker images -a 看到的 <none></none> 镜像就是悬挂镜像
悬挂镜像(dangling image)本质是没被任何标签(tag)指向的中间层镜像,通常是构建失败、重新打 tag 或 docker build --no-cache 后残留的。它们不显示在 docker images 默认输出里,但会占用磁盘空间。
执行 docker images -a 是最直接的方式——所有镜像层(含 <none></none>)都会列出,其中 REPOSITORY 和 TAG 均为 <none></none> 的行,就是典型的悬挂镜像。
- 注意:
docker images -f "dangling=true"也能过滤,但部分旧版 Docker(如 18.09 之前)不支持该 filter,-a更通用 - 别靠
IMAGE ID是否重复判断:多个 tag 可能共用同一 ID,但只要有一个 tag 指向它,就不是 dangling - 悬挂镜像的
CREATED时间往往非常接近,常成批出现,这是构建过程留下的线索
docker system df -v 能看清哪些层被谁引用
光知道有 <none></none> 镜像还不够,得确认它到底有没有被容器、构建缓存或其他镜像依赖。直接删错可能让后续 docker build 失败或容器启动异常。
docker system df -v 输出里,每个镜像层下面会列出 Tags 和 Shared Size,关键是看 Containers 和 Build Cache 字段:
- 如果某层的
Containers数 > 0,说明正有运行中或已停止的容器在用它,不能删 - 如果
Build Cache显示yes,代表它还在构建缓存链里,删了下次构建会变慢甚至失败 -
Shared Size小但Size大,大概率是基础层(如alpine:latest的 rootfs),即使没 tag 也别乱清
清理悬挂镜像要用 docker image prune,不是 rm
docker rmi 对 <none></none> 镜像无效——它只认 REPOSITORY:TAG 或完整 ID;强行用 ID 试会报错 Error response from daemon: conflict: unable to delete xxx (must be forced),而 --force 可能误删被引用的层。
正确做法是用 docker image prune:
-
docker image prune:仅删 dangling 镜像(默认行为,安全) -
docker image prune -f:跳过确认提示,适合脚本 -
docker image prune -a:删所有未被容器使用的镜像(危险!含带 tag 的),慎用 - 加
--filter "until=24h"可限制只删 24 小时前的 dangling 层,降低误伤风险
CI/CD 流水线里要主动清理,否则磁盘撑爆
GitLab CI、GitHub Actions 等环境常复用 runner,每次 docker build 都会产生新层,又不自动清理,几轮下来 /var/lib/docker 占满是常态。
建议在构建步骤末尾加清理逻辑:
- 简单场景:在
script最后加docker image prune -f - 更稳妥:先
docker system df -v | grep "Total Images" | awk '{print $3}'记录初始数量,清理后再比对,避免静默失败 - 别依赖
docker system prune -f:它会连网络、卷、构建缓存一起清,可能影响并发任务
真正麻烦的不是找不到悬挂镜像,而是它和构建缓存混在一起——删完发现下个 job 构建慢了三倍,这时候再查 docker system df -v 就晚了。










