name: Build and Push to ACR on: push: branches: [ main ] release: types: [ published ] workflow_dispatch: inputs: image_tag: description: "Tag to push (leave empty to use 'latest')" required: false default: "" also_latest: description: "Also tag & push :latest when a custom tag is provided" required: false default: "false" jobs: docker: runs-on: [buildx] steps: - name: Checkout uses: actions/checkout@v4 - name: Resolve TAG id: meta env: INPUT_TAG: ${{ github.event.inputs.image_tag || '' }} ALSO_LATEST: ${{ github.event.inputs.also_latest || 'false' }} run: | set -euo pipefail TAG="${INPUT_TAG:-}" if [ -z "$TAG" ]; then TAG="latest"; fi # 规范化 TAG="$(printf '%s' "$TAG" \ | tr '[:upper:]' '[:lower:]' \ | sed -E 's#[^a-z0-9._-]#-#g; s#/+#-#g; s#^[.-]+##; s#[.-]+$##')" TAG="${TAG:0:128}" echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "also_latest=${ALSO_LATEST}" >> "$GITHUB_OUTPUT" echo "Resolved TAG: $TAG, also_latest: ${ALSO_LATEST}" - name: Login to Aliyun ACR env: ACR_REGISTRY: ${{ secrets.ACR_REGISTRY }} ACR_USERNAME: ${{ secrets.ACR_USERNAME }} ACR_PASSWORD: ${{ secrets.ACR_PASSWORD }} run: | set -euo pipefail docker logout "$ACR_REGISTRY" || true echo "$ACR_PASSWORD" | docker login "$ACR_REGISTRY" \ --username "$ACR_USERNAME" --password-stdin # 可选:清理历史 builder,避免同名冲突 - name: Cleanup old builder (optional) run: docker buildx rm bk-proxy 2>/dev/null || true # 起用于构建的代理(compose 里带 profiles: ["build"]) - name: Start proxy (compose profile: build) run: | docker compose -f docker/compose.proxy.yml --profile build up -d --wait proxy # 双保险再探测一次,避免刚好切换配置/订阅时返回 200 但还没就绪 for i in $(seq 1 30); do if curl -sf http://127.0.0.1:9090/version >/dev/null; then break fi sleep 1 done # 创建 buildx(buildkitd 挂到 buildnet,自身也走 proxy) - name: Create & use buildx in buildnet (with proxy) run: | docker buildx create \ --name bk-proxy \ --driver docker-container \ --driver-opt network=buildnet \ --driver-opt env.http_proxy=http://build_proxy:7890 \ --driver-opt env.https_proxy=http://build_proxy:7890 \ --use docker buildx inspect --bootstrap # 构建镜像(通过容器代理) - name: Build Docker Image (via container proxy) env: IMAGE: ${{ secrets.ACR_REGISTRY }}/${{ secrets.ACR_NAMESPACE }}/${{ vars.IMAGE_NAME }} TAG: ${{ steps.meta.outputs.tag }} ALSO_LATEST: ${{ steps.meta.outputs.also_latest }} run: | set -euo pipefail # 构建时如需要“同时打 latest”,这里顺带加一个 tag(仅当 TAG 不是 latest 且 also_latest=true) EXTRA_TAGS=() if [ "$TAG" != "latest" ] && [ "${ALSO_LATEST}" = "true" ]; then EXTRA_TAGS+=( -t "${IMAGE}:latest" ) fi docker buildx build \ --progress=plain \ --build-arg http_proxy=http://build_proxy:7890 \ --build-arg https_proxy=http://build_proxy:7890 \ --build-arg HTTP_PROXY=http://build_proxy:7890 \ --build-arg HTTPS_PROXY=http://build_proxy:7890 \ --build-arg NO_PROXY=localhost,127.0.0.1 \ --load \ -t "${IMAGE}:${TAG}" \ "${EXTRA_TAGS[@]}" \ -f docker/Dockerfile . # (可选)停掉代理 - name: Stop proxy if: always() run: docker compose -f docker/compose.proxy.yml --profile build down -v - name: Push Docker Image env: IMAGE: ${{ secrets.ACR_REGISTRY }}/${{ secrets.ACR_NAMESPACE }}/${{ vars.IMAGE_NAME }} TAG: ${{ steps.meta.outputs.tag }} ALSO_LATEST: ${{ steps.meta.outputs.also_latest }} run: | set -euo pipefail echo "Pushing ${IMAGE}:${TAG}" docker push "${IMAGE}:${TAG}" # 若选择 also_latest=true 且本次 TAG 不是 latest,则一起推 latest if [ "$TAG" != "latest" ] && [ "${ALSO_LATEST}" = "true" ]; then echo "Also pushing ${IMAGE}:latest" docker push "${IMAGE}:latest" fi