chore(ci): add automatic Docker image cleanup after builds
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
Deploy / Build Production Runtime Images (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
Deploy / Production Browser E2E (push) Has been cancelled

- Add scripts/cleanup_old_images.sh: keeps only last 2 versions
  per service (api/worker/web), removes old local tags and registry
  blobs via Registry API, prunes dangling images
- Add cleanup step to deploy.yml build-production-runtime-images job
  with if:always() to ensure cleanup runs even on build failure
- Prevents disk space exhaustion from accumulated Docker images
  and Registry blobs on the build server
This commit is contained in:
CI Test
2026-06-30 06:58:48 +08:00
parent afea0a7566
commit d934e0e322
2 changed files with 78 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
#!/bin/sh
# cleanup_old_images.sh
# 清理构建服务器上的旧 Docker 镜像和 Registry 旧版本
# 保留最近 KEEP_VERSIONS 个版本(默认 2
# 在 CI 构建完成后调用,防止磁盘空间耗尽
set -eu
KEEP_VERSIONS="${KEEP_VERSIONS:-2}"
REGISTRY_HOST="${REGISTRY_HOST:-172.30.18.198:5000}"
SERVICES="xiaoxia-saas-api xiaoxia-saas-worker xiaoxia-saas-web"
echo "=== Docker Image Cleanup ==="
echo "Keeping last ${KEEP_VERSIONS} versions per service"
echo ""
for svc in $SERVICES; do
# 收集所有 v0.N.N 格式的版本号(去重,按版本号排序)
versions=$(docker images --format "{{.Repository}}:{{.Tag}}" | \
grep "${svc}" | \
grep -E "v[0-9]+\.[0-9]+\.[0-9]+" | \
sed -E "s/.*:${svc}:(v[0-9]+\.[0-9]+\.[0-9]+).*/\1/" | \
sed -E "s/.*:v([0-9]+\.[0-9]+\.[0-9]+).*/v\1/" | \
sort -t. -k1,1V -k2,2n -k3,3n | \
uniq)
total=$(echo "$versions" | grep -c "^v" || true)
if [ "$total" -gt "$KEEP_VERSIONS" ]; then
remove_count=$((total - KEEP_VERSIONS))
to_remove=$(echo "$versions" | head -n "$remove_count")
echo "[Registry] Cleaning old blobs for ${svc}..."
for ver in $to_remove; do
repo_name=$(echo "$svc" | sed "s/xiaoxia-saas-//")
manifest_url="http://admin:Xiaoxia2026@localhost:5000/v2/${repo_name}/manifests/${ver}"
digest=$(curl -sI -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "$manifest_url" | grep -i "^docker-content-digest:" | tr -d "\r" | awk "{print \$2}")
if [ -n "$digest" ]; then
curl -s -X DELETE -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "http://admin:Xiaoxia2026@localhost:5000/v2/${repo_name}/manifests/${digest}" > /dev/null 2>&1 || true
echo " Deleted registry tag: ${svc}:${ver}"
fi
done
echo "[Local] Removing old local images for ${svc}..."
for ver in $to_remove; do
docker rmi "${svc}:${ver}" 2>/dev/null && echo " Removed local: ${svc}:${ver}" || true
docker rmi "${REGISTRY_HOST}/${svc}:${ver}" 2>/dev/null && echo " Removed registry-ref: ${REGISTRY_HOST}/${svc}:${ver}" || true
done
else
echo "[${svc}] ${total} version(s) found, within keep limit (${KEEP_VERSIONS})"
fi
echo ""
done
# 清理悬空镜像(构建中间层)
echo "=== Pruning dangling images ==="
pruned=$(docker image prune -f 2>&1)
echo "$pruned" | tail -1
# 清理 dev 标签的旧层(dev 标签会被下次构建覆盖)
echo ""
echo "=== Cleanup complete ==="
echo "Current images:"
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep -E "(xiaoxia|REPOSITORY)" || true