Files
xiaoxia-saas/scripts/ci/docker_build_push.sh
T
xiaoxia a64037881a
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2m20s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m28s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 3m16s
AI Code Review / AI Code Review (pull_request) Successful in 1m59s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m13s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m59s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m8s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m45s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m8s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 9m25s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m16s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 16m45s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 28s
perf(ci): 流水线提速 - 路径过滤/持久builder缓存/依赖缓存卷/部署job迁移ci-l2
1. build-staging 路径过滤:纯前端改动只构建Web,纯后端只构建API/Worker;
   未重建镜像通过 retag-staging-skipped job 将分支tag retag为新SHA推送,Watchtower链路不变
2. deploy-staging、acr-cleanup runs-on 从 runtime-builder 改为 ci-l2,释放构建槽
3. buildx 改为宿主机持久 builder(ci-builder-persist)+buildkit命名卷缓存,
   job结束不再prune,Worker镜像同样接入buildx缓存
4. validate/unit-test/frontend-test 的 pip/npm 依赖通过宿主机命名卷持久化缓存
   (runner config 挂载 ci-pip-cache/xiaoxia-npm-cache/act-toolcache)
5. 不影响生产构建/发版/canary 相关 job
2026-08-29 11:28:12 +08:00

119 lines
3.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 通用Docker镜像构建+推送脚本
# 缓存策略(2026-08 起):
# - buildx 使用宿主机持久 builder (ci-builder-persist),层缓存保存在
# buildkit 容器/命名卷中,跨 job 共享、job 结束不清理
# - registry cache 仅作为冷启动兜底读取
# - 额外 tag(如分支 tag :develop)通过 EXTRA_TAGS 环境变量传入,随构建一并推送
# 用法: docker_build_push.sh [--no-cache] <Dockerfile> <image_tag> <cache_ref> [build_arg...]
# 环境变量:
# EXTRA_TAGS 空格分隔的额外 tag(完整 image:tag 引用),可选
set -eu
# 单次 build 超时时间(秒),防止 docker buildx build 无限挂起
BUILD_TIMEOUT=1500
# 持久 builder 名(宿主机级,所有 CI job 共享;由 ensure_persistent_builder.sh 维护)
BUILDER_NAME="ci-builder-persist"
NO_CACHE_FLAG=""
if [ "$1" = "--no-cache" ]; then
NO_CACHE_FLAG="--no-cache"
shift
echo "模式: --no-cache (不使用缓存,全新构建)"
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
# 确保持久 builder 存在并使用(幂等)
if ! docker buildx inspect "$BUILDER_NAME" > /dev/null 2>&1; then
echo "持久 builder 不存在,创建中..."
docker buildx create --name "$BUILDER_NAME" --driver docker-container \
--driver-opt network=host \
--buildkitd-flags "--allow-insecure-entitlement network.host" \
--platform linux/amd64
fi
docker buildx use "$BUILDER_NAME"
docker buildx inspect "$BUILDER_NAME" --bootstrap
# 组装额外 tag 参数
EXTRA_TAG_FLAGS=""
EXTRA_TAG_LIST=""
if [ -n "${EXTRA_TAGS:-}" ]; then
for t in $EXTRA_TAGS; do
EXTRA_TAG_FLAGS="$EXTRA_TAG_FLAGS -t $t"
EXTRA_TAG_LIST="$EXTRA_TAG_LIST $t"
done
fi
build_with_cache_retry() {
local attempt=1
local max_attempts=2
while [ $attempt -le $max_attempts ]; do
local build_output
local exit_code
set +e
build_output=$(timeout ${BUILD_TIMEOUT} docker buildx build \
$NO_CACHE_FLAG \
$BUILD_ARGS \
--cache-from "type=registry,ref=${CACHE_REF}" \
-f "${DOCKERFILE}" \
-t "${IMAGE_TAG}" \
$EXTRA_TAG_FLAGS \
--push \
. 2>&1)
exit_code=$?
set -e
if [ $exit_code -eq 0 ]; then
echo "$build_output"
return 0
fi
# 超时退出(exit code 124
if [ $exit_code -eq 124 ]; then
echo "❌ Docker build TIMEOUT after ${BUILD_TIMEOUT}s - build hung and was killed"
echo "$build_output" | tail -20
return $exit_code
fi
# 检测到缓存/快照损坏类错误,重建 builder 后重试
if echo "$build_output" | grep -qE "parent snapshot.*not found|snapshot.*does not exist|cache.*corrupt|failed to compute cache key|no such file or directory.*cache"; then
echo "$build_output"
echo ""
echo "⚠️ builder 缓存异常,重建持久 builder 后重试 (attempt $attempt/$max_attempts)..."
docker buildx rm "$BUILDER_NAME" >/dev/null 2>&1 || true
docker buildx create --name "$BUILDER_NAME" --driver docker-container \
--driver-opt network=host \
--buildkitd-flags "--allow-insecure-entitlement network.host" \
--platform linux/amd64
docker buildx use "$BUILDER_NAME"
docker buildx inspect "$BUILDER_NAME" --bootstrap
attempt=$((attempt + 1))
else
echo "$build_output"
return $exit_code
fi
done
return 1
}
echo "=== Build & push image (persistent builder cache) ==="
echo "Builder: ${BUILDER_NAME} (persistent)"
echo "Registry cache(from): ${CACHE_REF}"
echo "Image tag: ${IMAGE_TAG}"
[ -n "$EXTRA_TAG_LIST" ] && echo "Extra tags: ${EXTRA_TAG_LIST}"
echo "Timeout: ${BUILD_TIMEOUT}s"
echo ""
build_with_cache_retry
echo ""
echo "Image pushed: ${IMAGE_TAG}"
[ -n "$EXTRA_TAG_LIST" ] && echo "Also pushed: ${EXTRA_TAG_LIST}"
echo ""
echo "Build completed: ${IMAGE_TAG}"