背景

在长期运行的 Docker 服务器环境中,常见两类资产同时存在:

  • 正在运行的服务栈(多个容器组成的应用)
  • 暂时停用但未来仍会启用的服务(容器已删除,数据卷与镜像作为冷备保留)

如果仅依据“容器是否在运行”来判断镜像是否可删除,极易误删冷备镜像,给后续恢复带来额外成本。因此,有必要建立一套以服务栈(stack)为核心的镜像与容器管理方法

本文记录一次完整的排查与整理过程,目标不是“尽可能删除”,而是确保不误删任何未来仍需使用的镜像


一、基础原则

在该环境中采用如下原则:

  1. 容器运行状态不是删除依据
    • stopped / exited 容器依然可能代表未来会恢复的服务
    • 容器已删除 ≠ 服务已弃用
  2. 镜像分为三类资产
    • 正在运行的服务镜像(Active)
    • 冷备镜像(Cold Standby,未来会再用)
    • 明确弃用镜像(Retired)
  3. 任何清理操作都必须由人工决策,而非自动推断

二、列出所有镜像(事实基线)

使用带 digest 的镜像列表作为“真实库存”:

docker images --digests

该输出用于确认:

  • 系统中实际存在的镜像
  • 是否存在多版本堆积
  • 是否有本地构建镜像(digest 为 <none>

三、列出所有容器(不区分运行/停止)

容器列表是“镜像引用关系”的唯一事实来源:

docker ps -a --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.CreatedAt}}'

在该环境中,当前不存在 exited 容器,所有服务均处于运行状态。但这并不改变后续判断逻辑。


四、用“栈(Compose Project)视角”理解容器结构

相比单个容器视角,“栈”更符合真实服务结构。通过 com.docker.compose.project 标签,可将容器按栈分组。

栈视图生成命令

docker ps --format '{{.Label "com.docker.compose.project"}}\t{{.Names}}\t{{.Image}}' \
| sort \
| awk -F'\t' '{
  p=$1; if(p=="" ) p="(no-compose)";
  if(p!=last){ if(NR>1) print ""; print "== " p " =="; last=p }
  printf " - %-35s  %s\n", $2, $3
}'

五、当前运行中的服务栈清单(严格脱敏)

为避免暴露具体应用指纹,本节仅以抽象栈类别记录容器结构与数量,不出现任何可被直接识别的服务名称、镜像名或项目名。

  • Stack-A(单容器工具类):1 个容器
  • Stack-B(实时通信类):4 个容器
  • Stack-C(邮件系统类):18 个容器
  • Stack-D(管理界面类):1 个容器
  • Stack-E(即时通信类):2 个容器
  • Stack-F(远程访问类):2 个容器
  • Stack-G(本地构建类):1 个容器
  • Stack-H(文档处理类):1 个容器

该视图仅用于说明“以栈为单位进行管理”的方法论,而非展示具体部署细节。


Leave a Reply

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