
在 Docker 镜像清理操作(如 docker image prune)中,Untagged 表示仅移除镜像标签而保留镜像层,Deleted 表示镜像层本身被彻底删除;二者关键区别在于是否影响底层只读镜像数据。
在 docker 镜像清理操作(如 `docker image prune`)中,`untagged` 表示仅移除镜像标签而保留镜像层,`deleted` 表示镜像层本身被彻底删除;二者关键区别在于是否影响底层只读镜像数据。
Docker 的镜像模型基于分层存储 + 标签引用机制:镜像本身是只读的层(layers)集合,而标签(tag)只是指向某个镜像 ID(即 sha256:...)的可变指针。因此,“删除一个标签”和“删除一个镜像”在语义和实际效果上截然不同。
✅ Untagged:仅解绑标签,镜像数据完好无损
当你执行 docker rmi nginx:latest,而该镜像同时被 nginx:v1.25 引用时,Docker 会返回类似如下响应:
[
{"Untagged": "nginx:latest"},
{"Deleted": "sha256:abc123..."}
]
⚠️ 注意:此处 不会出现 Deleted 字段 —— 因为 nginx:latest 只是一个标签,其底层镜像仍被 nginx:v1.25 持有,故仅标记为 Untagged。镜像层(包括所有文件系统层和元数据)完全保留,磁盘空间不释放。
✅ Deleted:镜像层被真正回收(无任何标签引用)
只有当某镜像 ID 不再被任何本地标签、构建缓存或容器快照引用,且满足 prune 条件(如未被任何容器使用、无 dangling 标签),Docker 才会真正删除其底层层数据。此时响应中会出现 Deleted 字段,例如:
[{"Deleted": "sha256:def456..."}]
该操作将触发层数据的 GC(垃圾回收),释放对应磁盘空间。
? 验证示例
# 拉取同一镜像并打多个标签
docker pull alpine:3.19
docker tag alpine:3.19 myrepo/alpine:dev
docker tag alpine:3.19 myrepo/alpine:prod
# 查看镜像列表(注意 IMAGE ID 相同)
docker images --format "{{.Repository}}:{{.Tag}}\t{{.ID}}" | grep alpine
# 输出示例:
# alpine:3.19 sha256:1a2b3c...
# myrepo/alpine:dev sha256:1a2b3c...
# myrepo/alpine:prod sha256:1a2b3c...
# 删除其中一个标签
docker rmi myrepo/alpine:dev
# → 响应含 "Untagged": "myrepo/alpine:dev",但 sha256:1a2b3c... 仍在
# 再删另一个标签,只剩 alpine:3.19
docker rmi myrepo/alpine:prod
# 此时若 alpine:3.19 也不存在,则整个镜像层可能被 Deleted(取决于是否 dangling)
# 强制清理所有悬空镜像(dangling)
docker image prune -f
# 此时才会真正触发 Deleted(对无标签的 <none>:<none> 镜像)</none></none>
⚠️ 注意事项
-
docker rmi默认不会删除正在运行容器所依赖的镜像,即使无标签;这是安全保护机制。 -
Untagged不等于“失效”——只要还有其他标签或构建缓存引用,该镜像仍可用于docker run或docker build。 -
Deleted是不可逆操作;一旦镜像层被删除,除非重新拉取或构建,否则无法恢复。 - 使用
docker system df -v可直观查看镜像层(Images)、构建缓存(Build Cache)和卷(Volumes)的实际磁盘占用,辅助判断哪些Untagged镜像仍占空间。
理解 Untagged 与 Deleted 的差异,是高效管理 Docker 存储、避免误删生产镜像、以及优化 CI/CD 镜像缓存策略的关键基础。











