微服务架构下,如何通过Azure Pipelines自动清理Docker Hub冗余镜像?
作为一直在用微服务+Azure Pipelines做CI/CD的开发者,我完全懂你这种冗余镜像越堆越多的烦恼。下面分享几个我实际落地过的方案,你可以根据自己的场景选:
方案1:在Azure Pipelines中添加专属清理阶段(灵活可控)
这是我最常用的方式,直接在现有流水线里加一个Stage,构建推送完成后自动执行清理逻辑。步骤如下:
1. 配置Docker Hub访问凭据
首先在Azure Pipelines的项目库中添加Docker Hub的个人访问令牌(PAT)(别用密码,不安全),作为变量组或者流水线变量,比如命名为DOCKER_HUB_TOKEN和DOCKER_HUB_USERNAME。
2. 编写清理脚本(Bash示例)
在流水线里加一个Script任务,用Docker Hub的API来筛选并删除冗余镜像。比如我们可以保留最近5个构建的镜像,删除更早的:
# 获取Docker Hub认证令牌 TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username":"'"$DOCKER_HUB_USERNAME"'","password":"'"$DOCKER_HUB_TOKEN"'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) # 获取指定镜像的所有标签(这里替换成你的镜像名,比如my-service) TAGS=$(curl -s -H "Authorization: JWT $TOKEN" https://hub.docker.com/v2/repositories/$DOCKER_HUB_USERNAME/my-service/tags?page_size=100 | jq -r '.results[] | .name') # 将标签按时间排序(假设标签是用构建号/时间戳命名的,比如20240520-1234) # 如果你的标签命名规则不同,需要调整排序逻辑 SORTED_TAGS=$(echo "$TAGS" | sort -r) # 保留前5个,删除剩下的 COUNT=0 for TAG in $SORTED_TAGS; do if [ $COUNT -ge 5 ]; then echo "Deleting tag: $TAG" curl -s -X DELETE -H "Authorization: JWT $TOKEN" https://hub.docker.com/v2/repositories/$DOCKER_HUB_USERNAME/my-service/tags/$TAG/ fi COUNT=$((COUNT+1)) done
注意:如果你的镜像标签不是按时间/构建号排序的,需要修改排序逻辑,比如根据镜像创建时间来筛选,可以调用
/v2/repositories/<username>/<repo>/tags接口的last_updated字段来排序。
3. 集成到Azure Pipelines流水线
在你的YAML流水线里添加一个Stage,放在Build and Push之后:
stages: - stage: BuildAndPush # 你的构建推送逻辑... - stage: CleanupOldImages displayName: 'Cleanup Redundant Docker Images' dependsOn: BuildAndPush condition: succeeded() jobs: - job: Cleanup steps: - bash: | # 上面的清理脚本内容 env: DOCKER_HUB_USERNAME: $(DOCKER_HUB_USERNAME) DOCKER_HUB_TOKEN: $(DOCKER_HUB_TOKEN) displayName: 'Execute Docker Hub Cleanup Script'
方案2:利用Docker Hub内置的自动清理规则(简单省心)
如果不想写脚本,Docker Hub本身提供了自动清理功能,适合需求比较通用的场景:
- 登录Docker Hub,进入你的镜像仓库
- 找到Settings -> Repository cleanup
- 可以设置规则:比如保留最近N个镜像、保留最近X天的镜像,或者删除匹配特定标签的镜像(比如
dev-*的旧测试镜像) - 开启后,Docker Hub会自动按规则清理,不用依赖流水线
缺点:规则比较固定,没法做太定制化的清理(比如和Git分支关联的清理)
方案3:结合Git分支/标签策略清理(精准匹配)
如果你的镜像标签和Git分支、标签一一对应(比如镜像标签是feature-login-123对应同名分支),可以在流水线里只保留当前存在的分支/标签对应的镜像,删除其他的:
- 在流水线里获取当前项目的所有Git分支和标签
- 调用Docker Hub API列出所有镜像标签
- 找出不在Git分支/标签列表里的镜像标签,批量删除
这种方式适合严格遵循“代码分支存在则镜像保留”的场景,避免删除还在使用的镜像。
内容的提问来源于stack exchange,提问作者Lucky Rajput

