Files

10 KiB
Raw Permalink Blame History

vps.git Docker 迁移方案 v1

目标

vps.git 上当前裸机部署的:

  • Gitea
  • Keycloak
  • MySQL

迁移为 Docker 版本,并满足以下约束:

  • giteakeycloakmysql 位于同一个 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

当前版本基线

  • Gitea1.22.4
  • Keycloak26.0.6
  • MySQL8.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.tophttp://localhost:3000
  • login.hangman-lab.tophttp://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.yamlCompose 主文件
  • .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 容器连接:

  • Hostmysql
  • Port3306
  • Database<keycloak_db>

对外行为保持不变

  • 域名:login.hangman-lab.top
  • RealmHangman-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. 停止旧 Giteasystemctl stop gitea
  3. 停止旧 Keycloaksystemctl stop keycloak
  4. 执行 Gitea 最终 SQL 导出
  5. 执行 Keycloak 最终 export
  6. 停止旧 MySQLsystemctl 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
  1. 执行 nginx -t
  2. 执行 systemctl reload nginx
  3. 执行完整验证

验证清单

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