2026年9月15日约 5 分钟阅读
GHCR 自动部署:首次启用复盘
自动部署:首次启用复盘(2026-09-15)
整理自首次把生产从「VPS 本地
docker compose up --build」切到「GitHub Actions 构建 → GHCR → VPS 只拉镜像」的实操。
运维清单仍以docs/vps-go-live.md为准;环境差异见docs/coolxu-com-deploy.md。
1. 目标与结果
| 项 | 内容 |
|---|---|
| 站点 | https://coolxu.com |
| Secret | GHCR_PULL_TOKEN |
| Variable(可选) | SITE_NAME / AUTHOR_NAME / SITE_URL |
- 手动 Run workflow 或 push
main,观察 build → deploy。 - VPS 不要
git reset --hard/ 整库git pull覆盖content/。宿主机 HEAD 停在旧分支没关系,应用以镜像为准。
2. 日常更新
- 功能改动经 PR:先合入
test,验证后再合入main(见项目约定)。 - 推到
main(或 Actions 里对 Deploy to GHCR and VPS 手动 Run)→ buildx 推latest+sha→ SSH 拉镜像 →up -d --no-build。 - 不要默认在 CloudCone 小内存机器上
next build。
3. 本次踩坑与修复
3.1 SITE_NAME 撇号导致 shell EOF
- 现象:首次手动 Run 失败在「解析站点构建参数」:
unexpected EOF while looking for matching '''。 - 根因:Variables 已是
CoolXu's Blog,但脚本写成SITE_NAME="${SITE_NAME_VAR:-CoolXu's Blog}",bash 在解析默认值时把撇号当成未闭合单引号。 - 修复:空值时用普通双引号赋缺省,不再把带撇号的字面量写进
${var:-...}(PR #1)。
3.2 Buffer 不能作为 BodyInit(TS2345)
- 现象:站点参数修好后,Docker/
npm run build挂在app/uploads/[...path]/route.ts。 - 根因:Next.js 16 + TypeScript 5.9 + 新版
@types/node下,Buffer<ArrayBufferLike>与 DOMBodyInit不兼容。 - 修复:响应体改为
Uint8Array.from(...)再交给NextResponse(PR #2)。 - 说明:该问题在 VPS 旧镜像上可能一直没暴露;一进 Actions 干净构建就会拦下,说明「先在 test/CI ## 4. 分支策略(本次之后的约定)
| 分支 | 用途 |
|---|---|
| 功能分支 | 开发;开 PR 目标分支为 test |
test | 集成验证:合并后看 CI/构建是否通过,必要时人工点开站点或读 Actions 日志 |
main | 生产:合并后自动 Deploy to GHCR and VPS |
禁止把未在 test 验证过的改动直接推进 main(紧急热修需在 PR/提交说明里写明原因)。
4. 回滚与备份
- 回滚镜像:对旧 SHA 设
IMAGE_TAG=<旧sha>再跑scripts/vps-deploy-from-ghcr.sh(镜像仍在 GHCR 的前提下),或对旧 commit 手动 Run workflow。 - 备份:异地保存
content/、public/uploads/、data/(可选私密保存.env)。不要依赖 Git 里的上传与统计库。 - 禁止:
docker compose down -v(会丢 Caddy 证书卷);公网映射 3000;git reset --hard覆盖 VPS 上后台写过的文章。
5. 相关链接
- 清单:
docs/vps-go-live.md - 环境记录:
docs/coolxu-com-deploy.md - 架构说明归档:
docs/agent-prompts/archive/2026-09-14-ghcr-auto-deploy.md - Workflow:
.github/workflows/deploy.yml - VPS 脚本:
scripts/vps-deploy-from-ghcr.sh
*文档日期:2026-09-15。密钥与 PAT 以 GitHub Secrets / 服务器 .env 为准,不要写进仓库或文章正文。*构建再进 main」很有价值。
6. 其它注意点
- AlmaLinux 上
get.docker.com可能拒装 → 用 Docker CE 的 CentOS/RHEL 源(见coolxu-com-deploy.md)。 - 权威 DNS 在西部数码,不在 CloudCone DNS 面板。
- 站名 / robots / sitemap 绝对地址是 镜像构建 ARG;只 recreate 容器不够。
- Secrets 不齐时:镜像可能已在 GHCR,但部署 job 会失败并列出缺项——看起来「构建绿了线上没动」。
| VPS | 117.55.235.105(CloudCone,AlmaLinux 8.9) |
| 仓库 | https://github.com/ET-coolxu/ETblog |
| 成功标准 | Actions 构建并推 GHCR;SSH 在 VPS 执行 scripts/vps-deploy-from-ghcr.sh;HTTPS 验收通过 |
| 最终线上镜像 | ghcr.io/et-coolxu/etblog:44aff5303b1d41ac088230fec770682c554c76b5 |
| 成功 run | https://github.com/ET-coolxu/ETblog/actions/runs/34940570204 |
验收摘要:
http://coolxu.com→ 308 到 HTTPS- 首页标题为 CoolXu's Blog(不是「个人博客」)
/robots.txt的 Sitemap 为https://coolxu.com/sitemap.xml- 草稿
/posts/unfinished-draft→ 404 /admin→ 登录页(非 500)- VPS 上
app/caddy均为 Up;应用镜像来自 GHCR,不再是本机构建的etblog-app
7. 流程(首次启用)
7.1 一次性准备
- 确认
main已含要上线的代码(含 GHCR workflow、scripts/vps-deploy-from-ghcr.sh、compose 的image:)。线上 Git 工作区曾长期跟test,自动化只跟main。 - 生成 Actions 专用 SSH 密钥对;公钥写入 VPS
root的~/.ssh/authorized_keys(权限700/600)。不要用登录密码当 Secret。 - GitHub → Settings → Secrets and variables → Actions 填写:
| 类型 | 名 | 用途 |
|---|---|---|
| Secret | VPS_HOST | 117.55.235.105 或 coolxu.com |
| Secret | VPS_USER | root |