From 90ed11c4da91107ef61f102109752373ce96a36b Mon Sep 17 00:00:00 2001 From: chengkml <45121067+chengkml@users.noreply.github.com> Date: Sat, 16 May 2026 14:23:23 +0800 Subject: [PATCH] fix(ci): switch deploy images to cn registry --- .github/workflows/main.yml | 31 +++++++++++++++++++------------ MEMORY.md | 1 + deploy/pro-deploy/.env | 4 ++-- memory/2026-05-16.md | 25 +++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 memory/2026-05-16.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b35c243..168601e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,10 +12,10 @@ concurrency: permissions: contents: read - packages: write env: - REGISTRY: ghcr.io + REGISTRY: ${{ vars.REGISTRY || 'crpi-u265r07n4blchcqo.cn-shanghai.personal.cr.aliyuncs.com' }} + REGISTRY_NAMESPACE: ${{ vars.REGISTRY_NAMESPACE || 'ck-registry' }} jobs: build-and-push: @@ -32,26 +32,27 @@ jobs: id: vars shell: bash run: | - OWNER_LC="${GITHUB_REPOSITORY_OWNER,,}" - echo "api_image=${{ env.REGISTRY }}/${OWNER_LC}/fquiz-api" >> "$GITHUB_OUTPUT" - echo "web_image=${{ env.REGISTRY }}/${OWNER_LC}/fquiz-web" >> "$GITHUB_OUTPUT" + NS="${{ env.REGISTRY_NAMESPACE }}" + echo "api_image=${{ env.REGISTRY }}/${NS}/fquiz-api" >> "$GITHUB_OUTPUT" + echo "web_image=${{ env.REGISTRY }}/${NS}/fquiz-web" >> "$GITHUB_OUTPUT" echo "image_tag=${GITHUB_SHA}" >> "$GITHUB_OUTPUT" - name: 安装 Buildx uses: docker/setup-buildx-action@v3 - - name: 登录 GHCR + - name: 登录镜像仓库 uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} - name: 构建并推送 API 镜像 uses: docker/build-push-action@v6 with: context: ./api file: ./api/Dockerfile + pull: true push: true build-args: | PIP_INDEX_URL=${{ secrets.PIP_INDEX_URL || vars.PIP_INDEX_URL || 'https://pypi.org/simple' }} @@ -67,6 +68,7 @@ jobs: with: context: ./web file: ./web/Dockerfile + pull: true push: true build-args: | NEXT_PUBLIC_API_BASE_URL=${{ vars.NEXT_PUBLIC_API_BASE_URL || 'http://127.0.0.1:8000' }} @@ -88,6 +90,8 @@ jobs: SERVER_USER: ${{ secrets.SERVER_USER || vars.SERVER_USER }} SERVER_SSH_KEY: ${{ secrets.SERVER_SSH_KEY }} SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | set -euo pipefail [ -n "${SERVER_HOST}" ] || { echo "::error::缺少 SERVER_HOST(请在 Secrets 或 Variables 中配置)"; exit 1; } @@ -96,6 +100,8 @@ jobs: echo "::error::缺少登录凭据:请至少配置 SERVER_SSH_KEY 或 SERVER_PASSWORD" exit 1 fi + [ -n "${REGISTRY_USERNAME}" ] || { echo "::error::缺少 REGISTRY_USERNAME"; exit 1; } + [ -n "${REGISTRY_PASSWORD}" ] || { echo "::error::缺少 REGISTRY_PASSWORD"; exit 1; } - name: 拉取代码 uses: actions/checkout@v4 @@ -141,8 +147,9 @@ jobs: IMAGE_TAG: ${{ needs.build-and-push.outputs.image_tag }} NEXT_PUBLIC_API_BASE_URL: ${{ vars.NEXT_PUBLIC_API_BASE_URL || 'http://127.0.0.1:8000' }} FLOWER_BASIC_AUTH: ${{ secrets.FLOWER_BASIC_AUTH || vars.FLOWER_BASIC_AUTH || 'admin:admin' }} - GHCR_USERNAME: ${{ github.actor }} - GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REGISTRY: ${{ env.REGISTRY }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} with: host: ${{ secrets.SERVER_HOST || vars.SERVER_HOST }} username: ${{ secrets.SERVER_USER || vars.SERVER_USER }} @@ -151,7 +158,7 @@ jobs: command_timeout: 45m key: ${{ secrets.SERVER_SSH_KEY }} password: ${{ secrets.SERVER_PASSWORD }} - envs: DEPLOY_PATH,API_IMAGE,WEB_IMAGE,IMAGE_TAG,NEXT_PUBLIC_API_BASE_URL,FLOWER_BASIC_AUTH,GHCR_USERNAME,GHCR_TOKEN + envs: DEPLOY_PATH,API_IMAGE,WEB_IMAGE,IMAGE_TAG,NEXT_PUBLIC_API_BASE_URL,FLOWER_BASIC_AUTH,REGISTRY,REGISTRY_USERNAME,REGISTRY_PASSWORD script: | set -euo pipefail export DOCKER_CLIENT_TIMEOUT="${DOCKER_CLIENT_TIMEOUT:-600}" @@ -176,7 +183,7 @@ jobs: FLOWER_BASIC_AUTH=${FLOWER_BASIC_AUTH} ENV - echo "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USERNAME}" --password-stdin + echo "${REGISTRY_PASSWORD}" | docker login "${REGISTRY}" -u "${REGISTRY_USERNAME}" --password-stdin COMPOSE_CMD="docker compose" if ! docker compose version >/dev/null 2>&1; then diff --git a/MEMORY.md b/MEMORY.md index 44601ec..437c0a4 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -50,6 +50,7 @@ - 宿主机 DB 暴露端口统一走 `POSTGRES_PORT`(默认 `5434`),用于规避与宿主机已有 PostgreSQL(常见 `5432`)冲突;容器内连接仍保持 `db:5432`。 - CORS 来源控制采用“双轨配置”:`API_CORS_ORIGINS`(精确列表)+ `API_CORS_ORIGIN_REGEX`(正则,可选);`API_CORS_ORIGINS` 支持 `*` 和通配符域名并在后端转换为 `allow_origin_regex`。 - GitHub Actions 使用 `appleboy/ssh-action` 部署时,慢网环境需显式设置 `command_timeout`(建议 `45m`)并为 `docker compose pull` 增加重试,避免出现 `Run Command Timeout` 直接中断发布。 +- 生产发布默认不再依赖 `ghcr.io`:工作流镜像仓库统一通过 `REGISTRY` / `REGISTRY_NAMESPACE` 控制,默认指向阿里云个人版容器仓库 `crpi-u265r07n4blchcqo.cn-shanghai.personal.cr.aliyuncs.com/ck-registry`;CI 与远端部署均使用 `REGISTRY_USERNAME` / `REGISTRY_PASSWORD` 登录同一仓库,避免服务器侧访问 GHCR 出现 `Get "https://ghcr.io/v2/": EOF`。 - `docker compose up -d` 不会重建 `build` 类型服务镜像;开发链路默认使用 `deploy/dev-deploy/compose.yml`,前端代码变更后需执行 `docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml up --build -d web`(必要时先 `docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml build --no-cache web`)。 - `api` 构建若在拉取 `docker.m.daocloud.io/library/python:3.11-slim` 时出现 manifest `EOF`,优先重试 `docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml build api`;若持续失败,可在 `deploy/dev-deploy/.env` 覆盖 `PYTHON_BASE_IMAGE=python:3.11-slim` 走 Docker Hub 兜底。 diff --git a/deploy/pro-deploy/.env b/deploy/pro-deploy/.env index 4521160..83b693f 100644 --- a/deploy/pro-deploy/.env +++ b/deploy/pro-deploy/.env @@ -1,7 +1,7 @@ COMPOSE_PROJECT_NAME=fquiz -API_IMAGE=ghcr.io/chengkml/fquiz-api:latest -WEB_IMAGE=ghcr.io/chengkml/fquiz-web:latest +API_IMAGE=crpi-u265r07n4blchcqo.cn-shanghai.personal.cr.aliyuncs.com/ck-registry/fquiz-api:latest +WEB_IMAGE=crpi-u265r07n4blchcqo.cn-shanghai.personal.cr.aliyuncs.com/ck-registry/fquiz-web:latest POSTGRES_IMAGE=docker.m.daocloud.io/pgvector/pgvector:pg16 REDIS_IMAGE=docker.m.daocloud.io/library/redis:7-alpine diff --git a/memory/2026-05-16.md b/memory/2026-05-16.md new file mode 100644 index 0000000..ae541e1 --- /dev/null +++ b/memory/2026-05-16.md @@ -0,0 +1,25 @@ +## Work Log - 发布链路切换国内镜像仓库(2026-05-16) + +- 背景: + - 当前 `dev` 分支 GitHub Actions 发布阶段在远端执行 `docker login ghcr.io` / `docker compose pull` 时失败。 + - 典型报错为:`Error response from daemon: Get "https://ghcr.io/v2/": EOF`。 + - 参考仓库 `multica-ck` 已采用“可配置国内镜像仓库 + 账号密码登录”的工作流模式。 + +- 本次改动: + - `/.github/workflows/main.yml` + - 将工作流默认镜像仓库从固定 `ghcr.io` 改为 `REGISTRY` / `REGISTRY_NAMESPACE` 可配置模式。 + - 默认值对齐 `multica-ck`:`crpi-u265r07n4blchcqo.cn-shanghai.personal.cr.aliyuncs.com/ck-registry`。 + - 构建推送阶段改为使用 `REGISTRY_USERNAME` / `REGISTRY_PASSWORD` 登录镜像仓库。 + - 部署阶段新增镜像仓库凭据校验,并将远端 `docker login ghcr.io` 改为登录 `${REGISTRY}`。 + - API / Web 镜像构建补充 `pull: true`,降低 runner 侧基底镜像陈旧风险。 + - `/deploy/pro-deploy/.env` + - 将默认 `API_IMAGE` / `WEB_IMAGE` 从 GHCR 地址替换为阿里云个人版容器仓库地址,保证非 CI 手工部署默认也不再回落到 GHCR。 + +- 验证: + - `git diff --check -- .github/workflows/main.yml deploy/pro-deploy/.env` 通过,无空白/格式错误。 + - 仓库内已清除工作流与生产部署默认镜像中的 `ghcr.io` 活动引用。 + - 本次未直接触发 GitHub Actions 真实发布,远端连通性需在下一次 CI 执行中验证。 + +- 风险与关注点: + - GitHub 仓库需预先配置 `REGISTRY_USERNAME` / `REGISTRY_PASSWORD` Secrets,否则构建登录阶段会失败。 + - 若未来镜像仓库或命名空间变化,只需更新仓库 Variables `REGISTRY` / `REGISTRY_NAMESPACE`,无需再改工作流逻辑。