fix(ci): 修复registry不稳定导致镜像构建失败 - 解耦缓存推送与镜像构建

问题:
- Worker镜像构建因registry缓存推送时连接断开(use of closed network connection)而失败
- docker buildx exporting cache to registry阶段大层传输超时
- 缓存推送失败导致整个构建失败,镜像其实已经构建完成

修复:
1. 创建scripts/ci/docker_build_push.sh通用构建脚本
2. 镜像构建与缓存推送解耦:先构建+推送镜像(只读缓存)保证成功
3. 再单独尝试推送缓存,自动重试3次,失败不影响主构建结果
4. 缓存使用zstd压缩+oci-mediatypes减小传输体积
5. 缓存引用改为按分支名区分,支持多分支独立缓存

涉及:全部6个镜像构建job(staging/production x api/worker/web)
This commit is contained in:
XiaoXia Bot
2026-07-15 11:46:52 +08:00
parent 7c8748ece6
commit 085f48ecd6
2 changed files with 91 additions and 6 deletions
+85
View File
@@ -0,0 +1,85 @@
#!/bin/bash
# Docker镜像构建与推送脚本 - 处理registry不稳定问题
# 特性:
# 1. 构建+推送镜像(缓存只读模式)保证成功
# 2. 单独尝试推送缓存,失败不影响主构建
# 3. 缓存推送自动重试3次
# 4. zstd压缩减小缓存体积
set -eu
usage() {
echo "Usage: $0 <dockerfile> <image_tag> <cache_ref> [build_args...]"
echo " dockerfile: Dockerfile路径"
echo " image_tag: 完整镜像标签 (registry/repo:tag)"
echo " cache_ref: 缓存引用 (registry/repo-cache:branch)"
echo " build_args: 额外的--build-arg参数 (可选)"
exit 1
}
if [ $# -lt 3 ]; then
usage
fi
DOCKERFILE="$1"
IMAGE_TAG="$2"
CACHE_REF="$3"
shift 3
BUILD_ARGS=""
for arg in "$@"; do
BUILD_ARGS="$BUILD_ARGS --build-arg $arg"
done
CACHE_FROM="type=registry,ref=${CACHE_REF},ignore-error=true"
CACHE_TO="type=registry,ref=${CACHE_REF},mode=min,compression=zstd,oci-mediatypes=true"
echo "========================================"
echo "构建镜像: $IMAGE_TAG"
echo "Dockerfile: $DOCKERFILE"
echo "缓存引用: $CACHE_REF"
echo "========================================"
# Step 1: 构建并推送镜像(只读缓存,保证主构建成功)
echo ""
echo "[1/2] 构建并推送镜像 (只读缓存模式)..."
docker buildx build \
$BUILD_ARGS \
--cache-from "$CACHE_FROM" \
-f "$DOCKERFILE" \
-t "$IMAGE_TAG" \
--push \
.
echo "✅ 镜像构建并推送成功: $IMAGE_TAG"
# Step 2: 尝试推送缓存(失败不影响,重试3次)
echo ""
echo "[2/2] 尝试推送缓存到 registry (最多重试3次)..."
CACHE_PUSH_SUCCESS=false
for attempt in 1 2 3; do
echo " 缓存推送尝试 $attempt/3..."
if docker buildx build \
$BUILD_ARGS \
--cache-from "$CACHE_FROM" \
--cache-to "$CACHE_TO" \
-f "$DOCKERFILE" \
-t "$IMAGE_TAG" \
--push \
. 2>&1 | tail -5; then
CACHE_PUSH_SUCCESS=true
echo " ✅ 缓存推送成功 (第$attempt次尝试)"
break
else
echo " ⚠️ 缓存推送失败 (第$attempt次尝试),等待后重试..."
sleep $((attempt * 5))
fi
done
if [ "$CACHE_PUSH_SUCCESS" = false ]; then
echo ""
echo "⚠️ 缓存推送最终失败,跳过(不影响构建结果)"
echo " 下一次构建将使用旧缓存或无缓存构建"
fi
echo ""
echo "========================================"
echo "✅ 构建完成: $IMAGE_TAG"
echo "========================================"