Files

527 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# vps.git Docker 迁移方案 v1
## 目标
`vps.git` 上当前裸机部署的:
- Gitea
- Keycloak
- MySQL
迁移为 Docker 版本,并满足以下约束:
- `gitea``keycloak``mysql` 位于同一个 Docker 网络
- MySQL 只保留一个容器实例,但实例内分两个独立库:
- `<gitea_db>`
- `<keycloak_db>`
- 宿主机 `nginx` 架构不变,继续保留在宿主机上
- Gitea 直接挂载现有数据目录
- Keycloak 从 H2 迁移到 MySQL
- 敏感信息统一放在 `.env`
- Docker 部署根目录放在 `~/git-kc`
- 本次迁移不顺手升级大版本,优先保持现有版本基线
- 本次迁移默认先不启用 Git over SSH仅保证 HTTPS Git 正常
---
## 当前现状摘要
### 服务现状
宿主机当前运行:
- `nginx`
- `gitea.service`
- `keycloak.service`
- `mysql.service`
### 监听关系
- `nginx`:对外 `80/443`
- `gitea`:宿主机监听 `3000`
- `keycloak`:宿主机监听 `8443`
- `mysql`:宿主机监听 `localhost:3306`
### 当前数据位置
- Gitea 配置:`/etc/gitea/app.ini`
- Gitea 数据:`/var/lib/gitea`
- Keycloak 配置:`/opt/keycloak/conf/keycloak.conf`
- Keycloak H2 数据:`/opt/keycloak/data/h2`
- MySQL 数据:`/var/lib/mysql`
### 当前版本基线
- Gitea`1.22.4`
- Keycloak`26.0.6`
- MySQL`8.0.x`
迁移时保持同代版本,不使用 `latest`
---
## 目标架构
### 宿主机保留
- `nginx`
- 当前证书与域名
- 宿主机 SSH 运维入口
### Docker 内运行
- `mysql`
- `gitea`
- `keycloak`
三者放在同一个 Docker 网络中,例如:
- `git-kc-net`
### 端口策略
- `mysql`
- 不对宿主机发布端口
- 仅允许 Docker 内部网络访问
- `gitea`
- 发布到 `localhost:3000`
- `keycloak`
- 发布到 `localhost:8080`
### nginx 反代目标
- `git.hangman-lab.top``http://localhost:3000`
- `login.hangman-lab.top``http://localhost:8080`
说明:
- Gitea 迁移后,对外域名不变
- Keycloak 迁移后,对外域名不变
- Keycloak 容器内不再自行持有 HTTPSTLS 由宿主机 nginx 负责终止
---
## 部署目录设计
Docker 部署根目录:
- `~/git-kc`
建议结构:
- `~/git-kc/compose.yaml`
- `~/git-kc/.env`
- `~/git-kc/backups/`
- `~/git-kc/mysql/`
- `~/git-kc/gitea/`
- `~/git-kc/keycloak/`
- `~/git-kc/keycloak/import/`
- `~/git-kc/docs/`
用途说明:
- `compose.yaml`Compose 主文件
- `.env`:敏感配置
- `backups/`:迁移专用备份
- `gitea/`Gitea 容器使用的配置副本
- `keycloak/import/`Keycloak realm 导入文件
- `docs/`:迁移记录与回滚说明
---
## 数据与配置保留策略
### Gitea
Gitea 采用“保留原数据目录,容器挂载使用”的方式:
- 直接挂载现有数据目录:`/var/lib/gitea`
配置文件策略:
- 不直接原地修改宿主机当前使用的 `/etc/gitea/app.ini`
- 先复制一份到:`~/git-kc/gitea/app.ini`
- Docker Gitea 使用这份配置副本
- 原始 `/etc/gitea/app.ini` 保留不动,用于快速回滚
### Keycloak
Keycloak 不直接复用当前运行目录作为 Docker 运行目录,而是:
1. 从旧 Keycloak 执行 realm export
2. 在 Docker Keycloak 中导入 realm
3. 新容器改用 MySQL 存储
旧目录保留:
- `/opt/keycloak/conf`
- `/opt/keycloak/data/h2`
### MySQL
MySQL 不直接接管旧宿主机 datadir而采用逻辑导出 / 导入迁移:
- 导出旧 `<gitea_db>`
- 在 Docker MySQL 内创建新实例环境
- 导入 `<gitea_db>`
- 新建 `<keycloak_db>`
---
## 数据库设计
Docker MySQL 容器内使用一个实例,分为两个独立数据库:
- `<gitea_db>`
- `<keycloak_db>`
分别创建独立账户:
- `gitea`
- `keycloak`
权限原则:
- `gitea` 仅访问 `<gitea_db>`
- `keycloak` 仅访问 `<keycloak_db>`
字符集与排序规则保持与当前环境一致:
- `utf8mb4`
- `utf8mb4_0900_ai_ci`
说明:
- 是“共用一个 MySQL 容器实例”
- 不是“共用同一个 database/schema”
---
## Gitea 容器设计
### 运行目标
迁移后保持:
- 域名不变
- 数据目录不变
- 仓库、用户、OIDC、package 等数据保留
- 本次先不启用 Git over SSH
### 配置原则
基于现有 `app.ini` 的副本进行调整,重点改动:
- `[database] HOST`
-`localhost:3306`
- 改为 `mysql:3306`
其余核心配置尽量保持不变,例如:
- `ROOT_URL`
- `APP_DATA_PATH`
- `repository ROOT`
- `oauth2/openid`
- `security`
- `service`
- `package/lfs/queue`
### 端口
- 宿主机:`localhost:3000`
- 容器内:`3000`
### SSH 策略
本次迁移默认:
- 不启用 Git over SSH
- 不抢占宿主机 `22`
- 所有 Git 操作先走 HTTPS
- Gitea 配置中应显式关闭 SSH例如 `DISABLE_SSH = true`;若存在 `START_SSH_SERVER`,则设为 `false`
后续如需恢复 Git over SSH再单独设计第二阶段方案。
---
## Keycloak 容器设计
### 迁移原则
Keycloak 从:
- 裸机
- H2
- 自身提供 HTTPS 8443
迁移为:
- Docker
- MySQL
- 容器内部 HTTP
- 宿主机 nginx 负责 TLS 终止
### 数据库连接
Keycloak 容器连接:
- Host`mysql`
- Port`3306`
- Database`<keycloak_db>`
### 对外行为保持不变
- 域名:`login.hangman-lab.top`
- Realm`Hangman-Lab`
- OIDC issuer 保持不变
- 尽量保持原有 client 与集成关系不变
### 端口
- 宿主机:`localhost:8080`
- 容器内:`8080`
### 容器配置原则
通过 `.env` 注入:
- `KC_DB=mysql`
- `KC_DB_URL_HOST=mysql`
- `KC_DB_URL_DATABASE=<keycloak_db>`
- `KC_DB_USERNAME`
- `KC_DB_PASSWORD`
- `KC_HOSTNAME=login.hangman-lab.top`
- `KC_HTTP_ENABLED=true`
- `KC_PROXY_HEADERS=xforwarded`
说明:
- Docker Keycloak 不再自行持有 TLS 证书
- nginx 负责 HTTPS
---
## nginx 变更原则
宿主机 nginx 架构保持不变。
### Gitea
继续反代到:
- `http://localhost:3000`
如容器沿用相同宿主端口Gitea 对应 nginx 配置可能无需变更。
### Keycloak
需要把 upstream 从:
- `https://localhost:8443`
改为:
- `http://localhost:8080`
并保留以下头:
- `Host`
- `X-Real-IP`
- `X-Forwarded-For`
- `X-Forwarded-Proto`
---
## 迁移实施步骤
### Phase A准备阶段
1.`vps.git` 上安装 Docker Engine 与 Docker Compose Plugin
2. 创建目录:
- `~/git-kc`
- `~/git-kc/backups`
- `~/git-kc/mysql`
- `~/git-kc/gitea`
- `~/git-kc/keycloak/import`
- `~/git-kc/docs`
3. 编写 `compose.yaml``.env`
4. 复制 Gitea 当前配置:
- `/etc/gitea/app.ini``~/git-kc/gitea/app.ini`
5. 调整 Gitea 容器配置副本中的数据库地址
6. 准备 Keycloak 容器参数
7. 预拉取固定版本镜像
### Phase B备份阶段
正式切换前执行迁移专用备份:
1. 备份 `/etc/gitea/app.ini`
2. 记录并确认 `/var/lib/gitea` 当前状态
3. 导出 Gitea 数据库:`mysqldump <gitea_db>`
4. 从旧 Keycloak 导出 realm / users
5. 备份 nginx 相关站点配置
说明:
- 即使整机已有备份,仍建议保留迁移专用备份,以便快速回滚
### Phase C切换阶段
建议顺序:
1. 进入维护窗口
2. 停止旧 Gitea`systemctl stop gitea`
3. 停止旧 Keycloak`systemctl stop keycloak`
4. 执行 Gitea 最终 SQL 导出
5. 执行 Keycloak 最终 export
6. 停止旧 MySQL`systemctl stop mysql`
7. 启动 Docker MySQL
8. 初始化 Docker MySQL
- 创建 `<gitea_db>`
- 创建 `<keycloak_db>`
- 创建 `gitea` 用户
- 创建 `keycloak` 用户
9. 导入 Gitea SQL 到 Docker MySQL
10. 启动 Docker Keycloak并导入 realm
11. 启动 Docker Gitea
12. 修改 nginx 的 Keycloak upstream
-`https://localhost:8443`
- 改为 `http://localhost:8080`
13. 执行 `nginx -t`
14. 执行 `systemctl reload nginx`
15. 执行完整验证
---
## 验证清单
### Gitea
- `https://git.hangman-lab.top/` 可访问
- 首页正常
- 用户可登录
- 仓库列表正常
- 既有仓库可见
- Package 功能正常
- HTTPS clone 正常
- HTTPS push 正常
- OIDC 登录可正常跳转到 Keycloak 并返回
### Keycloak
- `https://login.hangman-lab.top/` 可访问
- Realm `Hangman-Lab` 正常
- OIDC discovery 正常
- 管理后台可登录
- 普通用户可登录
- 原有 client 保留
- issuer 与原环境一致
### MySQL
- `<gitea_db>` 表完整
- `<keycloak_db>` 表完整
- Gitea 可正常连接数据库
- Keycloak 可正常连接数据库
- 容器重启后数据不丢失
### nginx
- HTTPS 证书正常
- 无重定向循环
- 无 mixed content
- 代理头工作正常
---
## 回滚方案
如果迁移后验证失败,按以下顺序回滚:
1. 停止 Docker 容器:
- `gitea`
- `keycloak`
- `mysql`
2. 恢复 nginx 的 Keycloak upstream
- 改回 `https://localhost:8443`
3. 启动旧宿主机服务:
- `systemctl start mysql`
- `systemctl start keycloak`
- `systemctl start gitea`
4. 执行 `nginx -t`
5. 执行 `systemctl reload nginx`
回滚前提:
- 不删除旧数据
- 不覆盖旧宿主配置
- Gitea 使用配置副本而不是原地覆盖
- MySQL 使用逻辑迁移而不是直接接管 datadir
---
## 主要风险点
### 1. Keycloak H2 → MySQL
这是整个迁移中最高风险点。
控制策略:
- 必须走 export / import
- 不采用“直接改 DB 配置试运行”的方式
### 2. Gitea 与 Keycloak 的 OIDC 一致性
控制策略:
- 不改域名
- 不改 realm 名称
- 不改 issuer
- 尽量不重建 client
### 3. Gitea 直接挂载旧目录
控制策略:
- 切换时必须先彻底停止旧 Gitea
- 避免新旧环境同时访问同一数据目录
### 4. Keycloak 容器改为 HTTP
控制策略:
- 确保 nginx 传递正确代理头
- 确保 Keycloak hostname 与 proxy 配置正确
- 仅绑定到 `localhost`
---
## 已确定的关键决策
- 宿主机 nginx 架构不动
- Docker 部署根目录使用 `~/git-kc`
- Gitea 直接挂载现有数据目录
- MySQL 采用逻辑迁移,不直接接管旧 datadir
- Keycloak 改为 MySQL走 export / import 迁移
- 敏感信息统一放 `.env`
- 版本先保持现状,不升级大版本
- Git over SSH 本次先不启用;必要时后续单独设计第二阶段方案
---
## 结论
本方案的核心原则是:
- 先完成 Docker 化迁移
- 保持外部域名与功能语义不变
- 优先控制风险与保留回滚能力
- 不把“迁移”与“升级”混在同一轮进行
在此基础上,下一步可进一步补充:
- `compose.yaml` 草案
- `.env` 模板
- 精确到命令级的实施 checklist