Gitea 可移植部署包
把博客相关的代码托管(Gitea)+ CI 执行器(act_runner)+ 又拍云同步打包成一套 docker-compose, 目标:任何一台机器上,复制文件 + 一条命令就能拉起整套环境,彻底告别「迁移要半天手工操作」。
背景:境外那台 2C2G 服务器(23.254.236.47)十一月到期,且后续可能没时间慢慢迁移。 这个部署包就是把「迁移成本」从「半天手工」压到「copy + up」。
包含哪些服务
| 服务 | 镜像 | 说明 |
|---|---|---|
| gitea | gitea/gitea:1.28.0-rootless |
代码托管 + CI 调度。SQLite 单文件,数据全在 data/gitea/ |
| runner | gitea/act_runner:0.2.11 |
Gitea Actions 执行器,跑博客构建/部署 |
| upyun-sync | alpine:3.20 |
又拍云同步(原 1Panel 计划任务「又拍云同步(国内中转)」,容器化后不再依赖面板) |
| write-server | (可选,默认注释) | 写作后台,源码在仓库根 write-server/ |
不在本部署包里的(它们有自己的形态,不适合塞进 compose):
| 服务 | 形态 | 为什么不在 |
|---|---|---|
| 博客站点 | 静态文件 + CDN | 构建产物由 runner 推给 EdgeOne / 又拍云,不是常驻服务 |
| 评论后端 artalk-cf | Cloudflare Workers | 无服务器,wrangler deploy 部署,见 blog-admin/ |
| write-server | 独立 Docker | 可选纳入,见 compose 注释 |
目录结构
gitea-backup/
├── docker-compose.yml # 核心:三个服务 + 网络
├── .env.example # 变量模板(复制成 .env)
├── .gitignore # 忽略 .env 和 data/
├── README.md # 本文档
├── scripts/
│ ├── backup.sh # 一键备份:gitea dump + 打包 data 卷
│ └── restore.sh # 一键恢复
└── data/ # 数据卷(git 忽略,迁移时打包)
├── gitea/ # Gitea 数据(gitea.db + app.ini + 仓库)
├── runner/ # act_runner 配置
└── upyun-sync/ # 同步脚本 + upx + cos_sign.py
首次部署(新机器)
1. 准备代码和数据
# 克隆仓库(含 gitea-backup)
git clone <你的仓库> && cd <仓库>/gitea-backup
# 迁移数据:从旧机器把数据卷 rsync 过来
# (旧机器 23.254.236.47 上)
rsync -av --progress /opt/gitea/data/ 新机器:/path/to/gitea-backup/data/gitea/
# 又拍云同步目录同理:
rsync -av --progress /opt/upyun-sync/ 新机器:/path/to/gitea-backup/data/upyun-sync/
2. 配置
cp .env.example .env
# 编辑 .env:填域名、端口、又拍云密码
3. 启动
docker compose up -d
docker compose ps # 确认三个服务都 healthy/running
4. 注册 runner(首次必做)
# 到 Gitea 后台:站点管理 → Actions → Runners → 创建 runner → 复制注册 token
# 把 token 填进 .env 的 RUNNER_REGISTRATION_TOKEN,然后:
docker compose up -d --force-recreate runner
# 回到后台确认 runner 已在线(绿色)
备份
bash scripts/backup.sh
# 产物:backups/gitea-dump-<时间戳>.zip(含 gitea dump + app.ini)
# backups/data-<时间戳>.tar.gz(含完整 data 卷)
gitea dump 会导出仓库 + 用户 + 配置 + secrets(加密),是最完整的一站式备份。
恢复(灾难场景)
bash scripts/restore.sh backups/gitea-dump-<时间戳>.zip
# 或手动:把 data 卷解回 data/,然后 docker compose up -d
从旧机器迁移的完整清单(十一月到期前照着做)
- 新机器装 docker + docker compose
rsync旧机器/opt/gitea/data→ 新机器data/gitea/rsync旧机器/opt/upyun-sync→ 新机器data/upyun-sync/cp .env.example .env并填好docker compose up -d- 后台重新注册 runner(token 会变)
- DNS 把
gitea.usj.cc指向新机器 IP - 验证:
git push一次,看 Actions 是否正常构建部署
⚠️ 第 6 步 runner token 每次重新注册都会变,旧 token 作废,必须在后台重新拿。
关于「又拍云同步」的容器化说明
原 1Panel 计划任务是 bash /opt/upyun-sync/sync.sh,每分钟跑一次,负责:
从 COS 拉构建产物 → 解压 → upx sync 到又拍云 → purge → 刷多吉云。
容器化后逻辑不变,只是用 while sleep 60 循环替代了 cron(不再依赖 1Panel)。
注意:sync.sh 里如果还引用 COS(cos_sign.py 签 COS 地址),说明 COS 还没砍;
如果已改为「拉 Gitea artifact」,则 cos_sign.py 可以删掉。