From ccb01ade3dadaf211fab000f0665a3456b8a0fe6 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Mon, 13 Jul 2026 10:28:59 +0800 Subject: [PATCH] =?UTF-8?q?ci:=20Docker=E9=95=9C=E5=83=8F=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E6=8C=89=E5=88=86=E6=94=AF=E9=9A=94=E7=A6=BB=20-=20de?= =?UTF-8?q?velop=E5=86=99=E5=9B=9E=E7=BC=93=E5=AD=98,=20feature=E5=88=86?= =?UTF-8?q?=E6=94=AF=E5=8F=AA=E8=AF=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 核心改动:按 GITHUB_REF_NAME 判断分支,develop/main 读写缓存,feature 分支只读不写 - 防止feature分支修改requirements等依赖文件时污染主缓存,导致develop构建偶发50min+ - 新增 npm 缓存 volume,web构建 node_modules 持久化,减少 npm ci 下载时间 - 缓存 tag 从 release 改为 develop,语义更清晰 - 重构 build_with_cache 函数,消除三份重复的 buildx 命令 --- scripts/build_release_images.sh | 128 ++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 41 deletions(-) diff --git a/scripts/build_release_images.sh b/scripts/build_release_images.sh index 7c4d08450..dc691dacb 100755 --- a/scripts/build_release_images.sh +++ b/scripts/build_release_images.sh @@ -3,11 +3,20 @@ set -eu VERSION="${1:-${RELEASE_VERSION:-}}" if [ -z "$VERSION" ]; then - echo "Usage: $0 " - echo "Example: $0 v0.1.5" + echo "Usage: $0 [staging|production]" + echo "Example: $0 v0.1.5 production" + echo " $0 abc1234 staging" exit 1 fi +# 环境参数:staging 或 production(默认 production) +BUILD_ENV="${2:-production}" +case "$BUILD_ENV" in + staging) NGINX_CONF_FILE="infra/docker/nginx-staging.conf" ;; + *) NGINX_CONF_FILE="infra/docker/nginx-production.conf" ;; +esac +echo "Build environment: $BUILD_ENV → nginx config: $NGINX_CONF_FILE" + ROOT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)" cd "$ROOT_DIR" @@ -21,7 +30,8 @@ fi # ---- Registry 配置 ---- REGISTRY="${REGISTRY:-git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas}" CACHE_REGISTRY="${CACHE_REGISTRY:-git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas}" -CACHE_TAG="${CACHE_TAG:-release}" +# 主缓存 tag:develop 分支构建时写入,所有分支读取 +CACHE_TAG_PRIMARY="${CACHE_TAG:-develop}" API_IMAGE="xiaoxia-saas-api:$VERSION" WORKER_IMAGE="xiaoxia-saas-worker:$VERSION" @@ -36,6 +46,7 @@ REGISTRY_WEB="${REGISTRY}/xiaoxia-saas-web:$VERSION" USE_CACHE=0 USE_PUSH=0 +CACHE_WRITE=0 # 检查 buildx 和 Registry 认证 if docker buildx version >/dev/null 2>&1; then @@ -45,58 +56,93 @@ if docker buildx version >/dev/null 2>&1; then docker buildx use default 2>/dev/null || true fi -echo "=== Building API image ===" +# ---- 缓存读写策略(按分支隔离)---- +# 默认只读不写,防止 feature 分支污染主缓存 +# 只有 develop/main 分支才写回缓存 +BRANCH_NAME="${GITHUB_REF_NAME:-${CI_COMMIT_BRANCH:-unknown}}" if [ "$USE_CACHE" -eq 1 ]; then - docker buildx build \ - --cache-from "type=registry,ref=${CACHE_REGISTRY}/api-cache:${CACHE_TAG},ignore-error=true" \ - --cache-to "type=registry,ref=${CACHE_REGISTRY}/api-cache:${CACHE_TAG},mode=max" \ - -f infra/docker/api.Dockerfile \ - -t "$API_IMAGE" -t "$API_LATEST" \ - --load \ - . -else - docker build --pull=false -f infra/docker/api.Dockerfile -t "$API_IMAGE" -t "$API_LATEST" . + case "$BRANCH_NAME" in + develop|main) + CACHE_WRITE=1 + echo "Cache strategy: READ+WRITE (branch=$BRANCH_NAME, cache_tag=$CACHE_TAG_PRIMARY)" + ;; + *) + CACHE_WRITE=0 + echo "Cache strategy: READ-ONLY (branch=$BRANCH_NAME, cache_tag=$CACHE_TAG_PRIMARY)" + ;; + esac fi +build_with_cache() { + # usage: build_with_cache + IMG_NAME="$1" + DOCKERFILE="$2" + shift 2 + EXTRA_ARGS="$*" + + CACHE_FROM="type=registry,ref=${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY},ignore-error=true" + + if [ "$CACHE_WRITE" -eq 1 ]; then + CACHE_TO="type=registry,ref=${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY},mode=max" + echo " cache: read+write from ${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY}" + else + CACHE_TO="" + echo " cache: read-only from ${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY}" + fi + + if [ "$USE_CACHE" -eq 1 ]; then + if [ -n "$CACHE_TO" ]; then + docker buildx build \ + $EXTRA_ARGS \ + --cache-from "$CACHE_FROM" \ + --cache-to "$CACHE_TO" \ + -f "$DOCKERFILE" \ + -t "$IMG_NAME:$VERSION" \ + --load \ + . + else + docker buildx build \ + $EXTRA_ARGS \ + --cache-from "$CACHE_FROM" \ + -f "$DOCKERFILE" \ + -t "$IMG_NAME:$VERSION" \ + --load \ + . + fi + else + docker build --pull=false $EXTRA_ARGS -f "$DOCKERFILE" -t "$IMG_NAME:$VERSION" . + fi +} + +echo "=== Building API image ===" +build_with_cache "api" "infra/docker/api.Dockerfile" \ + "--build-arg APP_VERSION=$VERSION" +docker tag "$API_IMAGE" "$API_LATEST" + echo "=== Building Worker image ===" -if [ "$USE_CACHE" -eq 1 ]; then - docker buildx build \ - --cache-from "type=registry,ref=${CACHE_REGISTRY}/worker-cache:${CACHE_TAG},ignore-error=true" \ - --cache-to "type=registry,ref=${CACHE_REGISTRY}/worker-cache:${CACHE_TAG},mode=max" \ - -f infra/docker/worker.Dockerfile \ - -t "$WORKER_IMAGE" -t "$WORKER_LATEST" \ - --load \ - . -else - docker build --pull=false -f infra/docker/worker.Dockerfile -t "$WORKER_IMAGE" -t "$WORKER_LATEST" . -fi +build_with_cache "worker" "infra/docker/worker.Dockerfile" \ + "--build-arg APP_VERSION=$VERSION" +docker tag "$WORKER_IMAGE" "$WORKER_LATEST" echo "=== Building Web image (with buildx cache) ===" -# 先构建前端产物 +# 先构建前端产物(使用持久化 npm 缓存卷) +NPM_CACHE_VOLUME="xiaoxia-npm-cache" +if ! docker volume inspect "$NPM_CACHE_VOLUME" >/dev/null 2>&1; then + docker volume create "$NPM_CACHE_VOLUME" >/dev/null + echo " Created npm cache volume: $NPM_CACHE_VOLUME" +fi + docker run --rm \ -v "$PWD:/workspace" \ + -v "$NPM_CACHE_VOLUME:/workspace/apps/web/node_modules" \ -w /workspace/apps/web \ docker.m.daocloud.io/library/node:20 \ sh -lc "npm ci && npm run build" test -f apps/web/dist/index.html -if [ "$USE_CACHE" -eq 1 ]; then - docker buildx build \ - --cache-from "type=registry,ref=${CACHE_REGISTRY}/web-cache:${CACHE_TAG},ignore-error=true" \ - --cache-to "type=registry,ref=${CACHE_REGISTRY}/web-cache:${CACHE_TAG},mode=max" \ - -f infra/docker/web-artifact.Dockerfile \ - --build-arg NGINX_CONF=infra/docker/nginx-production.conf \ - -t "$WEB_IMAGE" \ - --load \ - . -else - docker build --pull=false \ - -f infra/docker/web-artifact.Dockerfile \ - --build-arg NGINX_CONF=infra/docker/nginx-production.conf \ - -t "$WEB_IMAGE" \ - . -fi +build_with_cache "web" "infra/docker/web-artifact.Dockerfile" \ + "--build-arg NGINX_CONF=$NGINX_CONF_FILE" # Push 到 Registry if [ "$USE_PUSH" -eq 1 ]; then