背景

在长期运行的 Docker 环境中,随着容器的反复创建、删除与重建,系统中可能残留未被任何容器使用的卷(volume)。
这些卷如果不加区分地清理,存在误删有效数据的风险;如果完全不清理,又会造成系统状态不透明。

本文记录一次严格、可验证的 Docker 卷清理过程,目标是:

  • 只识别未被任何容器使用的卷
  • 不误伤仍被容器引用的数据卷
  • 使用 Docker 原生命令完成交叉验证

一、初步筛选:dangling volume

Docker 提供了对“悬空卷(dangling volume)”的定义:

未被任何容器引用的卷

使用以下命令列出:

docker volume ls -qf dangling=true

输出结果为两个卷 ID:

14ab1c74859f7ed722d8f58fe8ff3fd455ebff535dd1e25bc3ca068c11118207
ebd2fa33478f081d936fa489320acf27f0aed14ea2c9f9f40fb36997eecf2635

该步骤只能说明:

这些卷当前没有被容器引用

但仍需要进一步验证它们的空间占用与引用状态。


二、空间与引用状态交叉验证

通过 docker system df -v 查看本地卷的使用情况,并重点关注两项信息:

  • LINKS:被多少个容器引用
  • SIZE:实际占用磁盘空间
docker system df -v | sed -n '/Local Volumes space usage:/,$p'

关键结果如下(节选):

VOLUME NAME                                                        LINKS     SIZE
ebd2fa33478f081d936fa489320acf27f0aed14ea2c9f9f40fb36997eecf2635   0         90.07kB
14ab1c74859f7ed722d8f58fe8ff3fd455ebff535dd1e25bc3ca068c11118207   0         7.706kB

可以确认:

  • 两个卷的 LINKS = 0
  • 占用空间极小(总计 < 100 kB)
  • 不属于任何业务数据卷

三、判断结论

综合两次验证结果:

卷 IDLINKSSIZE状态
14ab1c74859f…07.7 kB未被使用
ebd2fa33478…090 kB未被使用

结论:

  • 这两个卷未被任何运行中或已停止的容器引用
  • 不属于 Mailcow / Rocket.Chat / Ollama / OpenWebUI 等核心服务
  • 可安全视为“孤儿卷”

四、安全删除方式

明确目标卷后,采用精确删除而非批量清理:

docker volume rm \
  14ab1c74859f7ed722d8f58fe8ff3fd455ebff535dd1e25bc3ca068c11118207 \
  ebd2fa33478f081d936fa489320acf27f0aed14ea2c9f9f40fb36997eecf2635

该方式的优点是:

  • 不依赖 docker volume prune
  • 不会影响未来可能被使用的卷
  • 删除目标完全可控、可审计

五、实践原则总结

在 Docker 卷管理中,建议遵循以下原则:

  1. 不凭感觉删除卷
  2. 所有删除动作需满足:
    • dangling=true
    • LINKS=0
  3. 优先使用:
    • 精确列出 → 人工确认 → 精确删除
  4. 业务卷(数据库、模型、用户数据)必须有:
    • 明确命名
    • 明确 compose 归属

结语

Docker 的“卷”本质上是数据生命周期管理问题
清理不是目的,确认状态与可控性才是。

通过最少的命令、最明确的交叉验证,可以在不引入风险的前提下保持系统整洁。

Leave a Reply

Your email address will not be published. Required fields are marked *