清理linux上历史image脚本

需求

  • 同一仓库(repo相同,tag不同)保存最近7份image,删除多余的历史image

clean_docker_repo_tags.sh

您可以将此代码保存为 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"

# 1. 获取所有镜像,提取 Repository, CreatedAt, Tag
# 格式化输出: Repository CreatedAt(包含日期和时间) Tag
# 按 Repository 分组,并按 CreatedAt 降序(最新创建的排在前面)
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"

# 2. 根据模式执行对应逻辑
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"


脚本关键点

  1. 分组依据改变:按照 Repository(镜像仓库名,例如 harbor.xxx.com/.../xxx-auto-ocr)进行分组。
  2. 排序逻辑更新:将同一个仓库下的所有镜像按照 CreatedAt(创建时间)进行降序排序。最新推入或生成的镜像会排在最上面(计数器 1~7 属于它们,安全保留)。
  3. 安全过滤:自动过滤掉 RepositoryTag<none> 的悬空镜像(Dangling Images),防止误操作(如需清理悬空镜像,建议单独使用 docker image prune)。

如何使用?

  1. 赋予执行权限:
1
chmod +x clean_docker_repo_tags.sh
  1. 先运行 check 预览:
1
./clean_docker_repo_tags.sh check
  1. 确认无误后,运行 delete 真正执行删除:
1
./clean_docker_repo_tags.sh delete