From 33a027e809c4575600ffbb8ed339f92dc4f5d548 Mon Sep 17 00:00:00 2001 From: yinjianm Date: Wed, 25 Mar 2026 03:28:45 +0800 Subject: [PATCH] ci(config): add GHCR image publish workflow Publish frontend, backend, and remote-gateway images to GHCR on pushes to main and manual runs. Also update docker-compose to pull the three service images from ghcr.io instead of Docker Hub. --- .github/workflows/docker-publish.yml | 63 +++++++++ .helloagents/CHANGELOG.md | 1 + .../proposal.md | 123 ++++++++++++++++++ .../202603250317_ghcr-docker-publish/tasks.md | 51 ++++++++ .helloagents/archive/_index.md | 4 +- .helloagents/context.md | 2 +- .helloagents/modules/workspace-root.md | 10 +- docker-compose.yml | 6 +- 8 files changed, 252 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/docker-publish.yml create mode 100644 .helloagents/archive/2026-03/202603250317_ghcr-docker-publish/proposal.md create mode 100644 .helloagents/archive/2026-03/202603250317_ghcr-docker-publish/tasks.md diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..cdadf7d --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,63 @@ +name: Docker Publish + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + packages: write + +env: + REGISTRY: ghcr.io + +jobs: + publish: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - service: frontend + dockerfile: packages/frontend/Dockerfile + - service: backend + dockerfile: packages/backend/Dockerfile + - service: remote-gateway + dockerfile: packages/remote-gateway/Dockerfile + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/nexus-terminal-${{ matrix.service }} + tags: | + type=raw,value=latest + type=sha,format=short,prefix=sha- + + - name: Build and push ${{ matrix.service }} + uses: docker/build-push-action@v6 + with: + context: . + file: ${{ matrix.dockerfile }} + platforms: linux/amd64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max,scope=${{ matrix.service }} diff --git a/.helloagents/CHANGELOG.md b/.helloagents/CHANGELOG.md index e6bbb9e..83e8701 100644 --- a/.helloagents/CHANGELOG.md +++ b/.helloagents/CHANGELOG.md @@ -3,3 +3,4 @@ ## [Unreleased] - 2026-03-25:初始化 `.helloagents/` 知识库骨架与首批模块文档,不代表源码功能变更。 +- 2026-03-25:新增 GHCR Docker 发布 workflow,并将 `docker-compose.yml` 的三个业务镜像切换到 `ghcr.io/micah123321/*`。 diff --git a/.helloagents/archive/2026-03/202603250317_ghcr-docker-publish/proposal.md b/.helloagents/archive/2026-03/202603250317_ghcr-docker-publish/proposal.md new file mode 100644 index 0000000..54e0c2a --- /dev/null +++ b/.helloagents/archive/2026-03/202603250317_ghcr-docker-publish/proposal.md @@ -0,0 +1,123 @@ +# 变更提案: ghcr-docker-publish + +## 元信息 +```yaml +类型: 新功能 +方案类型: implementation +优先级: P1 +状态: 草稿 +状态说明: 已实施并归档 +创建: 2026-03-25 +``` + +--- + +## 1. 需求 + +### 背景 +当前仓库没有自动构建并发布 Docker 镜像的 GitHub Actions,根目录 `docker-compose.yml` 仍引用 Docker Hub 上的 `heavrnl/*` 镜像。为了让提交到 `main` 后可以自动生成当前仓库对应的镜像,需要接入 GitHub Container Registry(GHCR)发布链路,并把本地编排切换到仓库所有者名下的 GHCR 镜像。 + +### 目标 +- 在 `main` 分支推送后,自动构建 `frontend`、`backend`、`remote-gateway` 三个 `amd64` 镜像并推送到 GHCR。 +- 每次 `main` 推送同时发布 `latest` 与 `sha-` 两类标签。 +- 将根目录 `docker-compose.yml` 切换为引用 `ghcr.io/micah123321/nexus-terminal-{frontend,backend,remote-gateway}:latest`。 + +### 约束条件 +```yaml +时间约束: 无 +性能约束: 仅考虑 linux/amd64,暂不引入多架构构建 +兼容性约束: 现有三个 Dockerfile 必须继续可用,compose 中的服务名、端口和环境变量保持不变 +业务约束: 使用 GitHub 官方 Actions 与 GHCR;提交到 main 后自动发布 latest 和 sha 标签 +``` + +### 验收标准 +- [ ] `.github/workflows/` 下新增可在 `main` push 时构建并推送三类镜像的 workflow +- [ ] workflow 发布的镜像仓库为 `ghcr.io/micah123321/nexus-terminal-{frontend,backend,remote-gateway}` +- [ ] 每次 `main` push 至少生成 `latest` 和 `sha-` 两类标签 +- [ ] `docker-compose.yml` 中三个业务镜像已切换到上述 GHCR 地址 + +--- + +## 2. 方案 + +### 技术方案 +新增一个基于 `docker/setup-buildx-action`、`docker/login-action`、`docker/metadata-action` 和 `docker/build-push-action` 的 GitHub Actions workflow。workflow 在 `push` 到 `main` 时执行,使用 GitHub 提供的 `GITHUB_TOKEN` 登录 GHCR,按三个独立 job 分别构建 `frontend`、`backend`、`remote-gateway` 镜像。每个 job 都显式指定 `platforms: linux/amd64`,并通过 metadata action 生成 `latest` 与 `sha-` 标签。随后更新根 `docker-compose.yml` 中的镜像引用到当前仓库 owner 的 GHCR 镜像。 + +### 影响范围 +```yaml +涉及模块: + - workspace-root: 新增 workflow,更新 docker-compose 镜像来源 + - frontend: 使用现有 Dockerfile 作为 GHCR 构建输入 + - backend: 使用现有 Dockerfile 作为 GHCR 构建输入 + - remote-gateway: 使用现有 Dockerfile 作为 GHCR 构建输入 +预计变更文件: 2 +``` + +### 风险评估 +| 风险 | 等级 | 应对 | +|------|------|------| +| workflow 使用 `GITHUB_TOKEN` 推送 GHCR 失败(仓库包权限未开启) | 中 | 在 workflow 中显式声明 `packages: write`,并沿用官方登录动作 | +| 某个 Dockerfile 在 GitHub Actions 环境下构建失败 | 中 | 保持各镜像独立 job,便于快速定位失败服务 | +| compose 切到 GHCR 后,用户若未登录私有包仓库将拉取失败 | 低 | 默认假设目标仓库包可公开读取;若后续设为私有,再补充部署说明 | + +--- + +## 3. 技术设计(可选) + +### 架构设计 +```mermaid +flowchart TD + A[push main] --> B[GitHub Actions workflow] + B --> C[build frontend image] + B --> D[build backend image] + B --> E[build remote-gateway image] + C --> F[GHCR] + D --> F + E --> F + G[docker-compose.yml] --> F +``` + +### API设计 +N/A + +### 数据模型 +N/A + +--- + +## 4. 核心场景 + +### 场景: main 分支自动发布镜像 +**模块**: workspace-root +**条件**: 向 `main` 分支推送提交。 +**行为**: GitHub Actions 自动构建三个服务的 `linux/amd64` 镜像并推送到 GHCR,同时生成 `latest` 和 `sha-` 标签。 +**结果**: 仓库发布链路与部署编排使用同一组 GHCR 镜像来源。 + +### 场景: 本地 compose 拉取远程镜像 +**模块**: workspace-root +**条件**: 部署环境执行 `docker compose pull` 或 `docker compose up`。 +**行为**: `docker-compose.yml` 直接从 `ghcr.io/micah123321/*` 拉取三个业务镜像。 +**结果**: compose 不再依赖旧的 Docker Hub 镜像命名。 + +--- + +## 5. 技术决策 + +### ghcr-docker-publish#D001: 使用 GHCR + main push 自动发布 latest 和 sha 标签 +**日期**: 2026-03-25 +**状态**: ✅采纳 +**背景**: 需要在不引入额外制品系统的前提下,把当前仓库的 Docker 镜像发布链路收口到 GitHub。 +**选项分析**: +| 选项 | 优点 | 缺点 | +|------|------|------| +| A: GHCR + `latest` + `sha-` | 与 GitHub 仓库权限一体化,既有稳定标签又可精确追溯到提交 | 会额外产生较多镜像标签 | +| B: 仅发布 `latest` | 配置最简单 | 无法精确回滚到指定提交 | +**决策**: 选择方案 A +**理由**: 该方案兼顾可追溯性与部署便利性,适合当前“提交即发布”的需求。 +**影响**: 影响 `.github/workflows` 和根 `docker-compose.yml`,后续部署默认从 GHCR 拉取镜像。 + +--- + +## 6. 成果设计 + +N/A diff --git a/.helloagents/archive/2026-03/202603250317_ghcr-docker-publish/tasks.md b/.helloagents/archive/2026-03/202603250317_ghcr-docker-publish/tasks.md new file mode 100644 index 0000000..8e1ce47 --- /dev/null +++ b/.helloagents/archive/2026-03/202603250317_ghcr-docker-publish/tasks.md @@ -0,0 +1,51 @@ +# 任务清单: ghcr-docker-publish + +```yaml +@feature: ghcr-docker-publish +@created: 2026-03-25 +@status: completed +@mode: R2 +``` + +## 进度概览 + +| 完成 | 失败 | 跳过 | 总数 | +|------|------|------|------| +| 4 | 0 | 0 | 4 | + +--- + +## 任务列表 + +### 1. 发布工作流 + +- [√] 1.1 在 `.github/workflows/docker-publish.yml` 中新增 main push 触发的 GHCR 发布 workflow | depends_on: [] +- [√] 1.2 为 workflow 配置 `frontend`、`backend`、`remote-gateway` 三个镜像的 `linux/amd64` 构建与 `latest`/`sha-` 标签 | depends_on: [1.1] + +### 2. 部署编排 + +- [√] 2.1 在 `docker-compose.yml` 中把三个业务镜像切换到 `ghcr.io/micah123321/nexus-terminal-{frontend,backend,remote-gateway}:latest` | depends_on: [1.2] + +### 3. 验证与知识库同步 + +- [√] 3.1 检查 workflow 与 compose 语法/内容一致性,并记录已知限制 | depends_on: [2.1] + +--- + +## 执行日志 + +| 时间 | 任务 | 状态 | 备注 | +|------|------|------|------| +| 2026-03-25 03:17 | 方案包创建 | 完成 | 创建 implementation 类型方案包并进入开发实施 | +| 2026-03-25 03:24 | 1.1 / 1.2 | 完成 | 新增 GHCR 发布 workflow,main push 发布 latest 和 sha 标签 | +| 2026-03-25 03:24 | 2.1 | 完成 | docker-compose 三个业务镜像切换到 ghcr.io/micah123321 | +| 2026-03-25 03:25 | 3.1 | 完成 | 已人工复核 workflow 与 compose;本机缺少 docker,未执行 `docker compose config` | + +--- + +## 执行备注 + +> 记录执行过程中的重要说明、决策变更、风险提示等 + +- 由于当前环境无 Python 解释器,方案包由主代理按模板直接创建。 +- 本机缺少 Docker CLI,compose 未做命令级语法验证;workflow 也未运行 `actionlint`。 diff --git a/.helloagents/archive/_index.md b/.helloagents/archive/_index.md index 78f22fb..25710f4 100644 --- a/.helloagents/archive/_index.md +++ b/.helloagents/archive/_index.md @@ -7,12 +7,12 @@ | 时间戳 | 名称 | 类型 | 涉及模块 | 决策 | 结果 | |--------|------|------|---------|------|------| -| 暂无 | - | - | - | - | - | +| 202603250317 | ghcr-docker-publish | implementation | workspace-root | ghcr-docker-publish#D001 | ✅完成 | ## 按月归档 ### 2026-03 -- 暂无已归档方案 +- [202603250317_ghcr-docker-publish](./2026-03/202603250317_ghcr-docker-publish/) - 新增 GHCR 镜像发布 workflow 并切换 compose 镜像来源 ## 结果状态说明 - ✅ 完成 diff --git a/.helloagents/context.md b/.helloagents/context.md index c939e9c..94f94bf 100644 --- a/.helloagents/context.md +++ b/.helloagents/context.md @@ -15,7 +15,7 @@ 语言: TypeScript, Vue, Node.js 框架: Vue 3, Vite, Express 5 包管理器: npm workspaces -构建工具: Vite(frontend), TypeScript 编译(backend/remote-gateway), Docker Compose(部署) +构建工具: Vite(frontend), TypeScript 编译(backend/remote-gateway), GitHub Actions + GHCR(镜像发布), Docker Compose(部署) ``` ### 主要依赖 diff --git a/.helloagents/modules/workspace-root.md b/.helloagents/modules/workspace-root.md index 9e848e2..76f988d 100644 --- a/.helloagents/modules/workspace-root.md +++ b/.helloagents/modules/workspace-root.md @@ -2,7 +2,7 @@ ## 职责 -管理仓库根目录的 npm workspaces、共享依赖、`patch-package` 补丁应用以及 Docker Compose 部署编排。该模块不是业务运行时服务,但决定了三个子包如何安装、构建和协同运行。 +管理仓库根目录的 npm workspaces、共享依赖、`patch-package` 补丁应用、GitHub Actions 发布流程以及 Docker Compose 部署编排。该模块不是业务运行时服务,但决定了三个子包如何安装、构建、发布和协同运行。 ## 接口定义(可选) @@ -13,6 +13,7 @@ |----------|------|--------|------| | `package.json#workspaces` | `packages/*` | npm workspace 列表 | 声明后端、前端、远程网关三个子包属于同一工作区。 | | `package.json#postinstall` | 无 | shell 命令 | 安装依赖后自动执行 `patch-package`。 | +| `.github/workflows/docker-publish.yml` | GitHub push / workflow_dispatch 事件 | GHCR 镜像 | 在 `main` 推送时发布三个 `linux/amd64` 业务镜像到 GHCR。 | | `docker-compose.yml` | 环境变量、卷、端口映射 | 服务编排 | 统一启动 `frontend`、`backend`、`remote-gateway`、`guacd`。 | ### 数据结构 @@ -31,9 +32,14 @@ ### 容器化部署 **条件**: 使用根目录 `docker-compose.yml` 启动服务。 -**行为**: `frontend` 暴露 `18111:80`,`backend` 读取根 `.env` 并挂载 `./data:/app/data`,`remote-gateway` 依赖 `guacd` 和 `backend`。 +**行为**: `frontend` 暴露 `18111:80`,`backend` 读取根 `.env` 并挂载 `./data:/app/data`,`remote-gateway` 依赖 `guacd` 和 `backend`,三个业务镜像默认从 `ghcr.io/micah123321` 拉取。 **结果**: Web 入口、REST API、远程桌面网关与 `guacd` 形成完整运行拓扑。 +### 镜像自动发布 +**条件**: 向 `main` 分支推送代码,或在 GitHub Actions 手动触发 workflow。 +**行为**: `.github/workflows/docker-publish.yml` 使用各子包现有 Dockerfile 构建 `linux/amd64` 镜像,并向 GHCR 发布 `latest` 与 `sha-` 标签。 +**结果**: 仓库镜像发布链路与 compose 使用的镜像来源保持一致。 + ## 依赖关系 ```yaml diff --git a/docker-compose.yml b/docker-compose.yml index c380f73..24d1e92 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: frontend: - image: heavrnl/nexus-terminal-frontend:latest + image: ghcr.io/micah123321/nexus-terminal-frontend:latest container_name: nexus-terminal-frontend ports: - "18111:80" @@ -11,7 +11,7 @@ services: - nexus-terminal-network backend: - image: heavrnl/nexus-terminal-backend:latest + image: ghcr.io/micah123321/nexus-terminal-backend:latest container_name: nexus-terminal-backend env_file: - .env @@ -24,7 +24,7 @@ services: - nexus-terminal-network remote-gateway: - image: heavrnl/nexus-terminal-remote-gateway:latest + image: ghcr.io/micah123321/nexus-terminal-remote-gateway:latest container_name: nexus-terminal-remote-gateway environment: GUACD_HOST: guacd