#!/bin/sh set -eu VERSION="${1:-${RELEASE_VERSION:-}}" if [ -z "$VERSION" ]; then echo "Usage: $0 " echo "Example: $0 v0.1.5" exit 1 fi ROOT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)" cd "$ROOT_DIR" if docker ps --format "{{.Names}}" | grep -Eq "^(xiaoxia-(api|web|worker|postgres|redis)-production|gitea)$"; then if [ "${ALLOW_SHARED_PRODUCTION_BUILD_HOST:-false}" != "true" ]; then echo "Refusing to build runtime images on a host that is running production services." exit 1 fi 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}" API_IMAGE="xiaoxia-saas-api:$VERSION" WORKER_IMAGE="xiaoxia-saas-worker:$VERSION" WEB_IMAGE="xiaoxia-saas-web:$VERSION" API_LATEST="xiaoxia-saas-api:dev" WORKER_LATEST="xiaoxia-saas-worker:dev" # Registry 上的完整镜像名 REGISTRY_API="${REGISTRY}/xiaoxia-saas-api:$VERSION" REGISTRY_WORKER="${REGISTRY}/xiaoxia-saas-worker:$VERSION" REGISTRY_WEB="${REGISTRY}/xiaoxia-saas-web:$VERSION" USE_CACHE=0 USE_PUSH=0 # 检查 buildx 和 Registry 认证 if docker buildx version >/dev/null 2>&1; then if [ -n "${REGISTRY_TOKEN:-}" ]; then printf "%s" "${REGISTRY_TOKEN}" | docker login git.xiaoxiajianji.com -u xiaoxia --password-stdin 2>/dev/null && USE_CACHE=1 && USE_PUSH=1 fi docker buildx use default 2>/dev/null || true fi echo "=== Building API image ===" 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" . fi 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 echo "=== Building Web image (with buildx cache) ===" # 先构建前端产物 docker run --rm \ -v "$PWD:/workspace" \ -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 # Push 到 Registry if [ "$USE_PUSH" -eq 1 ]; then echo "=== Pushing images to Registry ===" docker tag "$API_IMAGE" "$REGISTRY_API" docker tag "$WORKER_IMAGE" "$REGISTRY_WORKER" docker tag "$WEB_IMAGE" "$REGISTRY_WEB" docker push "$REGISTRY_API" docker push "$REGISTRY_WORKER" docker push "$REGISTRY_WEB" echo "All images pushed to $REGISTRY" else echo "Registry push skipped (no auth token available)" fi echo "=== Build complete ===" docker images | grep "xiaoxia-saas.*:$VERSION"