惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
雷峰网
雷峰网
宝玉的分享
宝玉的分享
IT之家
IT之家
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Jina AI
Jina AI
博客园 - 叶小钗
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
云风的 BLOG
云风的 BLOG
美团技术团队
爱范儿
爱范儿
T
The Blog of Author Tim Ferriss
L
LangChain Blog
U
Unit 42
有赞技术团队
有赞技术团队
博客园_首页

博客园 - AlfredZhao

Oracle Property Graph 结合 In-Memory 的性能验证 sed 一条命令批量替换 SQL 文件路径 执行新项目 python 脚本前,先用 conda 建一个独立环境 Git 提交代码:从报错到 SSH 免密推送 GitHub 克隆他人私有仓库:从授权到下载 理解Oracle Property Graph:以账户转账示例完成图特性最小测试 APEX 无法分配 SH 用户?一个存储过程轻松解决 SH 中文化样例数据使用手册 Oracle 排除非业务表:一份能直接抄的“全量过滤”SQL 进程都杀了,为什么 `netstat` 还能看到端口? MAC 空间告急?Codex 的 156GB 缓存垃圾,这样清! 人工清理问题数据:先查准,再删除 TK(Trusted Knowledge)为何而生? 使用快捷键快速切换 Mac 外接显示器模式 客户环境 Nginx 配置:流式报表与超时排查要点 Security Central:数据库安全的统一控制与运营平台 Palantir 眼中的一次“订单可能延期”,如何成为实时决策的起点? 从一条订单消息到 Bronze、Silver、Gold:我的第一次 Kafka + Lakehouse 实验 UUID v4 与 v7:同样是唯一 ID,为什么数据库表现可能完全不同? 用 crontab 给 LLM 使用量装上“监控眼” DeepSeek 与 GPT API 价格调整:该关注什么? 查看 Oracle 数据库中的定时任务执行情况 Codex 专用用户登录后自动进入默认项目目录 Mac 小技巧:用方向键优雅处理超长网址 Oracle GDD 与 Raft:别把共识机制和数据主权混为一谈 在 Oracle APEX 中用 BGE_BASE 生成向量:从模型导入到历史数据更新 行业人+AI:真正有价值的四个关键要素 知识库文件解析失败:一次由 Domain Index 引发的定位记录 Unicode 码位数、UTF-8 字节数、中英文差异和 Oracle 长度别再混淆了 Skill 的使用:从路径到能力边界
Docker 删除 none 镜像:一次真实的清理记录
AlfredZhao · 2026-09-20 · via 博客园 - AlfredZhao

2026-09-20 07:21  AlfredZhao  阅读(0)  评论()    收藏  举报

笔者在服务器上执行 docker images 时,发现列表里堆了一排 <none> 镜像,占用从 511 MB 到 826 MB 不等。它们既没有仓库名,也没有标签,看起来像“幽灵”。这篇文章记录笔者如何定位根源并清理掉它们。

01 | none 镜像从哪来

<none>:<none> 常见于以下场景:构建新镜像时旧层被顶替(产生悬空镜像)、镜像被重新打标签后原标签被移走、多阶段构建的中间层、构建失败残留等。其中悬空镜像(dangling)通常可被 docker image prune 清理,而无标签镜像不一定。

笔者环境里,docker image prune -f 能清掉大部分悬空镜像,但有一条始终清不掉:

<none>  <none>  d989eed1eb19  8 days ago  825 MB

它反复出现,说明它可能并非能被 prune 直接清理的普通悬空层,需要进一步排查是否仍被容器引用,或是否被其他镜像作为父层依赖。

下面这张图概括了 none 镜像的两种来源,以及它们与“能否被 prune 清理”之间的关系:

flowchart TD A["docker images 出现 &lt;none&gt;:&lt;none&gt;"] --> B{来源判断} B -->|"构建新镜像,旧层被顶替"| C["悬空镜像 dangling"] B -->|"重新打标签,旧标签被移走"| D["无标签镜像"] C --> E{是否被容器引用} D --> E E -->|"无任何容器引用"| F["docker image prune -f 可清理"] E -->|"被停止的容器引用"| G["prune 跳过,删不掉"] G --> H["需先 docker rm 容器,再 docker rmi 镜像"]

02 | 为什么 prune 删不掉

docker image prune 默认只清理没有被任何容器引用的悬空(dangling)镜像;加 -a 后会删除所有未被任何容器使用的镜像(包括有标签但未被使用的镜像)。如果某个已停止的容器仍然指向这个镜像,prune 就会跳过它。

笔者检查后发现,根源是一个已经停止的容器 ontoforge_app_1。容器虽然停了,但它引用的镜像 ID 正是 d989eed1eb19,于是这个 none 镜像被“锁”住了。

从清理前后的对比可以更直观地看到这条“顽固”镜像的处境:

阶段 命令 结果
清理前 docker images 多条 <none> 镜像,其中 d989eed1eb19(825 MB)始终存在
批量清理 docker image prune -f 大部分悬空镜像被删除,d989eed1eb19 仍保留
定位根源 docker ps -a 查看已停止容器,确认 ontoforge_app_1 的 IMAGE 列指向 d989eed1eb19
删除容器 docker rm ontoforge_app_1 容器被移除,镜像解除占用
删除镜像 docker rmi d989eed1eb19 镜像及依赖层逐层删除

03 | 两步清理

思路很简单:先删掉占用镜像的容器,再删镜像。注意:删除容器前请确认该容器不再需要,并检查是否有需要保留的数据卷或挂载数据;生产环境建议先备份或在测试环境验证。

docker rm ontoforge_app_1
docker rmi d989eed1eb19

执行 docker rm 后,容器被移除;再执行 docker rmi,镜像及其依赖层被逐层删除,输出了一长串 Deleted: 记录。再次执行 docker images,那条 825 MB 的 none 镜像已经消失。如果 docker rmi 报错提示镜像仍被引用,可先用 docker ps -a --filter ancestor=d989eed1eb19 查找并处理相关容器。

整个清理流程可以归纳为下面几步:

flowchart LR A["docker images<br/>发现 none 镜像"] --> B["docker image prune -f<br/>批量清理悬空镜像"] B --> C{"目标 none 镜像<br/>是否仍存在"} C -->|"已删除"| D["清理完成"] C -->|"仍存在"| E["docker ps -a<br/>查找引用它的容器"] E --> F["docker rm 容器名"] F --> G["docker rmi 镜像ID"] G --> D

04 | 小结

遇到删不掉的 none 镜像,不要反复 prune。先确认是否有停止的容器还在引用它;确认该容器不再需要后,用 docker rm 清掉容器,再用 docker rmi 删除镜像即可。日常维护中,定期清理停止的容器,能避免这类镜像长期占着磁盘。

关注我,和AI一起成长~