需求
- 同一仓库(repo相同,tag不同)保存最近7份image,删除多余的历史image
您可以将此代码保存为 clean_docker_repo_tags.sh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #!/bin/bash
usage() { echo "使用方法: $0 [check|delete]" echo " check : 预览将被删除的镜像标签(按仓库保留最新7个,其余预览删除)" echo " delete : 真正执行删除操作" exit 1 }
if [ $# -ne 1 ]; then usage fi
MODE=$1
if [ "$MODE" != "check" ] && [ "$MODE" != "delete" ]; then echo "错误: 未知的参数 '$MODE'" usage fi
TMP_FILE="/tmp/repo_tags_to_delete.txt" > "$TMP_FILE"
docker images --format "{{.Repository}} {{.CreatedAt}} {{.Tag}}" | \ sort -k1,1 -k2,2r -k3,3r | \ awk ' { repo = $1 tag = $NF # 如果换了一个新的镜像仓库(Repository),计数器清零 if (repo != current_repo) { current_repo = repo count = 0 } count++ # 每个仓库超过 7 个的标签,将其加入处理列表 if (count > 7) { # 排除没有标签的虚无镜像 <none> if (tag != "<none>" && repo != "<none>") { print repo ":" tag } } }' > "$TMP_FILE"
if [ -s "$TMP_FILE" ]; then if [ "$MODE" == "check" ]; then echo "=== [CHECK 模式] 以下镜像标签将被删除(每个仓库已保留最新的7个) ===" cat "$TMP_FILE" echo "==================================================================" echo "提示: 以上仅为预览。如果确认无误,请运行: $0 delete" elif [ "$MODE" == "delete" ]; then echo "=== [DELETE 模式] 开始清理多余的镜像标签 ===" while read -r tag_to_del; do echo "正在删除: $tag_to_del" docker rmi "$tag_to_del" done < "$TMP_FILE" echo "=== 清理完成 ===" fi else echo "没有发现需要清理的旧标签(所有仓库的标签数量均未超过 7 个)。" fi
rm -f "$TMP_FILE"
|
脚本关键点
- 分组依据改变:按照
Repository(镜像仓库名,例如 harbor.xxx.com/.../xxx-auto-ocr)进行分组。
- 排序逻辑更新:将同一个仓库下的所有镜像按照
CreatedAt(创建时间)进行降序排序。最新推入或生成的镜像会排在最上面(计数器 1~7 属于它们,安全保留)。
- 安全过滤:自动过滤掉
Repository 或 Tag 为 <none> 的悬空镜像(Dangling Images),防止误操作(如需清理悬空镜像,建议单独使用 docker image prune)。
如何使用?
- 赋予执行权限:
1
| chmod +x clean_docker_repo_tags.sh
|
- 先运行
check 预览:
1
| ./clean_docker_repo_tags.sh check
|
- 确认无误后,运行
delete 真正执行删除:
1
| ./clean_docker_repo_tags.sh delete
|