1166 字
6 分钟
myapp Staging 部署问题与解决速查
这篇从 frappe_docker/STAGING_DEPLOYMENT.zh-CN.md 整理,所有真实服务器信息都用占位符替换。
推荐发布流程
分支模型:
feature/* -> develop -> main -> build/deploy/release建议:
main只放稳定、可部署版本develop做日常集成测试feature/*/fix/*做单个功能或修复- staging 镜像优先基于
main、tag 或明确 commit - 只有临时调试才建议直接用
develop
当前 staging 方案
流程:
Lint-> Build myapp staging image-> Push to GHCR-> Deploy staging stack by SSH-> 首次建站 init-site.sh-> 后续升级自动 bench migrate核心原则:
- 服务器只保留部署骨架
- 不再在服务器挂载
apps/myapp源码目录 myapp烘焙进镜像- 首次部署允许“容器起来但站点未初始化”
GitHub Actions Secrets
常见 secrets:
STAGING_SSH_HOSTSTAGING_SSH_PORTSTAGING_SSH_USERSTAGING_SSH_PRIVATE_KEYGHCR_USERNAMEGHCR_TOKENSTAGING_SITE_ADMIN_PASSWORD注意:
STAGING_SSH_PRIVATE_KEY必须是完整私钥- 不能填
.pub - 不能只填一行公钥
- 建议使用无 passphrase 的 CI 专用 key
GHCR_TOKEN至少需要读取 packages 的权限
生成 CI key:
ssh-keygen -t ed25519 -N "" -C "github-actions-staging" -f ~/.ssh/github_actions_staging_ci本地验证:
ssh -i ~/.ssh/github_actions_staging_ci -p <port> <user>@<host>首次部署顺序
推荐顺序:
1. Lint2. Build myapp staging image3. Deploy staging stack4. init-site.sh 创建站点5. check-staging.sh 检查原因:
bench new-site依赖 backend / db / redis 容器- 所以必须先把基础栈启动起来
首次部署后出现这些情况是正常的:
- 镜像正常拉取
- 容器栈成功启动
- 首页返回
404 /api/method/ping返回404- deploy 脚本跳过
migrate
这通常表示基础栈已启动,但站点还没创建。
首次建站
cd /srv/frappe_dockerSITE_NAME=staging.example.com \ADMIN_PASSWORD='<admin-password>' \./deploy/staging/init-site.sh底层动作:
bench new-site <site>bench --site <site> install-app erpnextbench --site <site> install-app myappbench --site <site> migrate建站完成后,后续 deploy 就可以自动 migrate。
CORS 修改与验证
如果浏览器端要直接访问 staging 后端,需要把完整 origin 加入 Frappe 的 allow_cors。
实际读取文件通常是容器内:
/home/frappe/frappe-bench/sites/common_site_config.json修改后至少重启:
docker compose -p staging restart backend frontend websocket验证预检请求:
curl -sS -X OPTIONS -D - -o /dev/null \ -H "Origin: https://frontend.example.com" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: content-type" \ https://erpnext.example.com/api/method/login生效时应看到:
Access-Control-Allow-Origin: https://frontend.example.comAccess-Control-Allow-Credentials: true注意:CORS 放开只代表浏览器能发请求,不代表跨站 Cookie / Session 一定稳定。长期使用更推荐同主域名方案。
直接访问 IP 返回 404
现象:
curl -I http://127.0.0.1:28080返回 404,但:
curl -I -H 'Host: staging.example.com' http://127.0.0.1:28080返回 200。
原因:
- Frappe / Nginx 按
Host头路由站点 - 直接访问 IP 时 Host 不是站点名
- 所以没有命中对应 site
解决:
FRAPPE_SITE_NAME_HEADER=staging.example.com然后重启 staging。
常见问题:SSH 失败
现象:
missing server hostunable to authenticate常见原因:
STAGING_SSH_*secrets 不完整- 私钥内容错误
- 端口或用户名带空格/换行
- 服务器
authorized_keys没有对应公钥
解决:
- workflow 增加 secrets 校验
- 使用 CI 专用 SSH key
- 本地先用同一把 key 验证能登录服务器
常见问题:git pull 被拒绝
现象:
Your local changes would be overwritten by merge可能原因:
- 服务器上的脚本只有文件 mode 变化,例如
100644 -> 100755
解决:
cd /srv/frappe_dockergit checkout -- deploy/staging/*.shgit pull --ff-only origin main常见问题:No module named myapp
现象:
ModuleNotFoundError: No module named 'myapp'原因:
- staging 还在沿用开发态 compose
- compose 挂载了宿主机
./apps/myapp - 服务器没有这份源码目录
- bind mount 把镜像内置的
myapp覆盖掉
解决:
- staging 使用专用 compose
- 不挂载服务器上的
apps/myapp - 让
myapp来自镜像
常见问题:数据库端口冲突
现象:
Bind for 0.0.0.0:3307 failed: port is already allocated解决:
- staging 数据库不映射宿主机端口
- 或使用 staging 专用 compose 覆盖端口配置
常见问题:migrate 时站点不存在
现象:
Error: 404 Not Found: staging.example.com does not exist.原因:
- 第一次部署只启动了基础栈
- 站点尚未
new-site
解决:
- deploy 脚本先检查站点是否存在
- 不存在就跳过 migrate
- 先执行
init-site.sh
常见问题:formatter 导致 CI 失败
现象:
files were modified by this hook原因:
- 不是业务逻辑错误
- 是 prettier / shfmt / shellcheck 认为格式还没对齐
建议:
- 改 Markdown / YAML / JSON 后关注 prettier
- 改 shell 脚本后关注 shfmt 和 shellcheck
- CI 日志里未显示
(unchanged)的文件,通常就是被 formatter 修改过的文件
常见问题:恢复后短暂 503
可能原因:
- 数据恢复后站点仍处于 maintenance mode
解决:
bench --site <site> set-maintenance-mode offrestore 脚本也应该在末尾自动关闭维护模式、执行 migrate 并清缓存。
备份与恢复
升级前备份:
SITE_NAME=all ./deploy/staging/backup-staging.sh恢复:
SITE_NAME=staging.example.com \RESTORE_DIR=/srv/frappe_docker/tmp/restore-localhost-YYYYMMDD \./deploy/staging/restore-staging.sh注意:
- 数据跟着 site 走,不是跟着 app 走
- 恢复会覆盖目标站点数据库和文件
- 不要恢复清理前的旧备份
- 恢复前确认备份时间点
myapp Staging 部署问题与解决速查
https://r-gc.github.io/posts/notes/frappe/myapp-staging-deploy-pitfalls/