merge: 同步项目配置草稿修复
This commit is contained in:
@@ -1,48 +1,95 @@
|
||||
# CTMS 分支环境安装配置指南
|
||||
# CTMS 安装步骤向导
|
||||
|
||||
本文定义 `dev`、`main`、`release` 三类分支对应的推荐部署环境、配置文件、初始化步骤与验证命令。分支本身不会自动切换运行模式,实际模式由后端环境变量 `ENV` 决定。
|
||||
按目标分支选择对应章节执行:
|
||||
|
||||
## 分支与环境映射
|
||||
- [dev 分支安装](#dev-分支安装)
|
||||
- [main 分支安装](#main-分支安装)
|
||||
- [release 分支安装](#release-分支安装)
|
||||
|
||||
| 分支 | 分支定位 | 推荐环境 | 后端 `ENV` | 用途 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `dev` | 日常开发与集成 | 开发环境 | `development` | 功能开发、联调、自测、内部集成 |
|
||||
| `main` | 下一版本候选 | 预发布 / 验收环境 | `production` | 回归测试、验收、发布候选验证 |
|
||||
| `release` | 当前稳定生产线 | 生产环境 | `production` | 正式生产部署、生产 hotfix |
|
||||
## 安装前准备
|
||||
|
||||
推广路径保持为:
|
||||
三个分支都先完成本节。
|
||||
|
||||
```text
|
||||
feature/* -> dev -> main -> release
|
||||
### 1. 准备安装目录
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/ctms
|
||||
cd /opt/ctms
|
||||
```
|
||||
|
||||
不要把 `release` 当作日常开发分支使用。`main` 应只接收已经准备进入候选版本范围的变更。
|
||||
### 2. 安装 Docker
|
||||
|
||||
## 公共前置条件
|
||||
Linux 可使用 Docker Engine 或 Docker Desktop。安装完成后确认 Docker Compose v2 可用:
|
||||
|
||||
所有环境都需要:
|
||||
|
||||
- Docker 与 Docker Compose
|
||||
- 可写的 `pg_data/` 数据目录
|
||||
- 端口 `8888`、`8000`、`5432` 未被占用
|
||||
- 后端镜像可安装 `backend/requirements.txt` 中的依赖
|
||||
- 前端镜像可执行 `npm ci` 与 `npm run build`
|
||||
|
||||
当前 compose 服务拓扑:
|
||||
|
||||
```text
|
||||
nginx -> backend -> db
|
||||
```bash
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
对外入口:
|
||||
如果当前用户不能执行 Docker 命令,将用户加入 `docker` 组后重新登录:
|
||||
|
||||
- 前端:`http://localhost:8888`
|
||||
- 后端 API:同域 `/api/v1/*`
|
||||
- 健康检查:`http://localhost:8888/health`
|
||||
```bash
|
||||
sudo usermod -aG docker "$USER"
|
||||
```
|
||||
|
||||
## dev 分支:开发环境
|
||||
macOS 安装 Docker Desktop 后执行:
|
||||
|
||||
`dev` 默认用于本地开发和内部集成,推荐使用 `ENV=development`。
|
||||
```bash
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
### 3. 安装基础工具
|
||||
|
||||
Linux:
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y git openssl curl lsof
|
||||
```
|
||||
|
||||
macOS:
|
||||
|
||||
```bash
|
||||
brew install git openssl curl
|
||||
```
|
||||
|
||||
### 4. 检查端口
|
||||
|
||||
```bash
|
||||
lsof -nP -iTCP:8888 -sTCP:LISTEN
|
||||
lsof -nP -iTCP:8000 -sTCP:LISTEN
|
||||
lsof -nP -iTCP:5432 -sTCP:LISTEN
|
||||
```
|
||||
|
||||
如果命令有输出,先停止占用这些端口的服务,或调整 `docker-compose.yaml` 中的端口映射。
|
||||
|
||||
### 5. 拉取代码
|
||||
|
||||
首次安装:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/chengchengzhou7/CTMS.git
|
||||
cd CTMS
|
||||
```
|
||||
|
||||
已有仓库:
|
||||
|
||||
```bash
|
||||
cd /opt/ctms/CTMS
|
||||
git fetch --prune origin
|
||||
```
|
||||
|
||||
### 6. 确认本地配置不会提交
|
||||
|
||||
```bash
|
||||
grep -n "^\\.env$" .gitignore
|
||||
grep -n "^\\.env\\.\\*$" .gitignore
|
||||
```
|
||||
|
||||
预期能看到 `.env` 和 `.env.*` 已被忽略。
|
||||
|
||||
## dev 分支安装
|
||||
|
||||
### 1. 切换分支
|
||||
|
||||
@@ -51,68 +98,93 @@ git checkout dev
|
||||
git pull --rebase origin dev
|
||||
```
|
||||
|
||||
### 2. 配置 `.env`
|
||||
### 2. 写入环境配置
|
||||
|
||||
根目录 `.env` 不提交到仓库。开发环境推荐:
|
||||
在仓库根目录创建或覆盖 `.env`:
|
||||
|
||||
```env
|
||||
```bash
|
||||
cat > .env <<'EOF'
|
||||
COMPOSE_PROJECT_NAME=ctms_dev
|
||||
ENV=development
|
||||
JWT_SECRET_KEY=dev-secret
|
||||
LOGIN_RSA_KEY_ID=default
|
||||
LOGIN_RSA_PRIVATE_KEY=
|
||||
EOF
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `ENV=development` 会启用开发行为。
|
||||
- 未配置 `LOGIN_RSA_PRIVATE_KEY` 时,后端启动后会生成临时 RSA 私钥。
|
||||
- 后端重启后临时公钥会变化,已有登录页应刷新后重新登录。
|
||||
- `JWT_SECRET_KEY=dev-secret` 只允许本地开发使用。
|
||||
|
||||
### 3. 启动
|
||||
|
||||
```bash
|
||||
docker compose up -d --build backend nginx
|
||||
```
|
||||
|
||||
如果需要首次启动完整栈:
|
||||
### 3. 构建镜像并启动
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### 4. 开发模式行为
|
||||
### 4. 执行数据库迁移
|
||||
|
||||
`development` 模式下:
|
||||
已有数据库升级到新代码时,启动后执行一次迁移:
|
||||
|
||||
- FastAPI `debug=True`
|
||||
- 应用启动时会执行 `Base.metadata.create_all`
|
||||
- 应用启动时会确保默认管理员存在
|
||||
- 未配置 RSA 私钥时允许临时生成
|
||||
```bash
|
||||
docker compose run --rm backend python -m alembic upgrade head
|
||||
```
|
||||
|
||||
这些行为只适合开发,不适合生产。
|
||||
首次空库安装也可以执行该命令;如果已是最新版本,Alembic 不会重复应用迁移。
|
||||
|
||||
### 5. 验证
|
||||
### 5. 检查容器状态
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose exec backend python -c "from app.core.config import settings; print(settings.ENV)"
|
||||
```
|
||||
|
||||
确认 `ctms_db`、`ctms_backend`、`ctms_nginx` 都是 `Up`,且 `ctms_db` 为 `healthy`。
|
||||
|
||||
### 6. 检查后端环境
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -c "from app.core.config import settings; print('ENV=' + settings.ENV); print('JWT_SECRET_IS_DEV=' + str(settings.JWT_SECRET_KEY == 'dev-secret')); print('LOGIN_RSA_PRIVATE_KEY_SET=' + str(bool(settings.LOGIN_RSA_PRIVATE_KEY)))"
|
||||
```
|
||||
|
||||
预期输出:
|
||||
|
||||
```text
|
||||
ENV=development
|
||||
JWT_SECRET_IS_DEV=True
|
||||
LOGIN_RSA_PRIVATE_KEY_SET=False
|
||||
```
|
||||
|
||||
### 7. 检查接口
|
||||
|
||||
```bash
|
||||
curl -i http://127.0.0.1:8888/health
|
||||
curl -i http://127.0.0.1:8888/api/v1/auth/login-key
|
||||
```
|
||||
|
||||
预期:
|
||||
两个接口都应返回 `HTTP/1.1 200 OK`。
|
||||
|
||||
### 8. 打开系统
|
||||
|
||||
```text
|
||||
ENV=development
|
||||
GET /health -> 200
|
||||
GET /api/v1/auth/login-key -> 200, key_id=default
|
||||
http://localhost:8888
|
||||
```
|
||||
|
||||
## main 分支:预发布 / 验收环境
|
||||
### 9. 运行验证
|
||||
|
||||
`main` 是下一正式版本候选分支,应按生产模式运行,但不直接承载正式生产流量。
|
||||
后端:
|
||||
|
||||
```bash
|
||||
docker compose run --rm -v "$PWD/backend/tests:/code/tests:ro" backend python -m pytest
|
||||
```
|
||||
|
||||
前端:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run test:unit
|
||||
npm run type-check
|
||||
npm run build
|
||||
cd ..
|
||||
```
|
||||
|
||||
## main 分支安装
|
||||
|
||||
### 1. 切换分支
|
||||
|
||||
@@ -121,81 +193,153 @@ git checkout main
|
||||
git pull --rebase origin main
|
||||
```
|
||||
|
||||
### 2. 配置 `.env`
|
||||
### 2. 生成密钥
|
||||
|
||||
预发布环境应使用 `ENV=production`,并配置独立于生产的密钥:
|
||||
|
||||
```env
|
||||
COMPOSE_PROJECT_NAME=ctms_staging
|
||||
ENV=production
|
||||
JWT_SECRET_KEY=<staging-strong-random-secret>
|
||||
LOGIN_RSA_KEY_ID=staging-YYYYMMDD
|
||||
LOGIN_RSA_PRIVATE_KEY=<staging-rsa-private-key-pem-with-\n-escaped-newlines>
|
||||
```
|
||||
|
||||
生成密钥示例:
|
||||
生成 JWT 密钥:
|
||||
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048
|
||||
```
|
||||
|
||||
要求:
|
||||
生成 RSA 私钥文件:
|
||||
|
||||
- `JWT_SECRET_KEY` 不得使用 `dev-secret`。
|
||||
- `LOGIN_RSA_PRIVATE_KEY` 必须固定保存,不能每次部署重新生成。
|
||||
- staging 私钥不得复用 production 私钥。
|
||||
```bash
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out login_rsa_main.pem
|
||||
```
|
||||
|
||||
### 3. 初始化数据库
|
||||
生成可写入 `.env` 的 RSA 私钥单行文本:
|
||||
|
||||
生产模式不会自动建表或自动补管理员。首次部署或迁移前执行:
|
||||
```bash
|
||||
awk '{printf "%s\\n", $0}' login_rsa_main.pem
|
||||
```
|
||||
|
||||
### 3. 写入环境配置
|
||||
|
||||
在仓库根目录创建或覆盖 `.env`,将占位符替换为上一步生成的值:
|
||||
|
||||
```bash
|
||||
cat > .env <<'EOF'
|
||||
COMPOSE_PROJECT_NAME=ctms_main
|
||||
ENV=production
|
||||
JWT_SECRET_KEY=<替换为 JWT 密钥>
|
||||
LOGIN_RSA_KEY_ID=main-YYYYMMDD
|
||||
LOGIN_RSA_PRIVATE_KEY=<替换为 RSA 私钥单行文本>
|
||||
EOF
|
||||
```
|
||||
|
||||
### 4. 检查 Compose 配置
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
```
|
||||
|
||||
确认输出中包含:
|
||||
|
||||
```text
|
||||
ENV: production
|
||||
LOGIN_RSA_KEY_ID: main-YYYYMMDD
|
||||
LOGIN_RSA_PRIVATE_KEY: '-----BEGIN PRIVATE KEY-----...'
|
||||
```
|
||||
|
||||
### 5. 初始化数据库
|
||||
|
||||
```bash
|
||||
docker compose run --rm backend-init
|
||||
```
|
||||
|
||||
该步骤应运行 Alembic migration,并确保固定管理员账号存在。
|
||||
|
||||
### 4. 启动
|
||||
### 6. 构建镜像并启动
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### 5. 验证
|
||||
### 7. 执行数据库迁移
|
||||
|
||||
已有数据库升级到新代码时,启动后执行一次迁移:
|
||||
|
||||
```bash
|
||||
docker compose run --rm backend python -m alembic upgrade head
|
||||
```
|
||||
|
||||
`backend-init` 会在初始化时处理空库和已有库迁移;这里单独执行迁移用于确认部署代码已落到最新数据库版本。
|
||||
|
||||
### 8. 检查容器状态
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
docker compose ps
|
||||
docker compose exec backend python -c "from app.core.config import settings; print(settings.ENV); print(settings.JWT_SECRET_KEY == 'dev-secret'); print(bool(settings.LOGIN_RSA_PRIVATE_KEY))"
|
||||
```
|
||||
|
||||
确认 `ctms_db`、`ctms_backend`、`ctms_nginx` 都是 `Up`,且 `ctms_db` 为 `healthy`。
|
||||
|
||||
### 9. 检查后端环境
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -c "from app.core.config import settings; print('ENV=' + settings.ENV); print('JWT_SECRET_IS_DEV=' + str(settings.JWT_SECRET_KEY == 'dev-secret')); print('LOGIN_RSA_PRIVATE_KEY_SET=' + str(bool(settings.LOGIN_RSA_PRIVATE_KEY))); print('LOGIN_RSA_KEY_ID=' + settings.LOGIN_RSA_KEY_ID)"
|
||||
```
|
||||
|
||||
预期输出:
|
||||
|
||||
```text
|
||||
ENV=production
|
||||
JWT_SECRET_IS_DEV=False
|
||||
LOGIN_RSA_PRIVATE_KEY_SET=True
|
||||
LOGIN_RSA_KEY_ID=main-YYYYMMDD
|
||||
```
|
||||
|
||||
### 10. 检查接口
|
||||
|
||||
本机:
|
||||
|
||||
```bash
|
||||
curl -i http://127.0.0.1:8888/health
|
||||
curl -i http://127.0.0.1:8888/api/v1/auth/login-key
|
||||
```
|
||||
|
||||
预期:
|
||||
远程域名:
|
||||
|
||||
```text
|
||||
ENV=production
|
||||
JWT_SECRET_KEY == dev-secret -> False
|
||||
LOGIN_RSA_PRIVATE_KEY_SET -> True
|
||||
GET /health -> 200
|
||||
GET /api/v1/auth/login-key -> 200
|
||||
```bash
|
||||
curl -i https://<main-domain>/health
|
||||
curl -i https://<main-domain>/api/v1/auth/login-key
|
||||
```
|
||||
|
||||
### 6. 验收门禁
|
||||
接口应返回 `HTTP/1.1 200 OK`。
|
||||
|
||||
在把 `main` 推进到 `release` 前,至少执行:
|
||||
### 11. 打开系统
|
||||
|
||||
本机:
|
||||
|
||||
```text
|
||||
http://localhost:8888
|
||||
```
|
||||
|
||||
远程访问:
|
||||
|
||||
```text
|
||||
https://<main-domain>
|
||||
```
|
||||
|
||||
远程访问必须使用 HTTPS。
|
||||
|
||||
### 12. 运行验证
|
||||
|
||||
后端:
|
||||
|
||||
```bash
|
||||
docker compose run --rm -v "$PWD/backend/tests:/code/tests:ro" backend python -m pytest
|
||||
cd frontend && npm run test:unit
|
||||
cd frontend && npm run type-check
|
||||
cd frontend && npm run build
|
||||
```
|
||||
|
||||
## release 分支:生产环境
|
||||
前端:
|
||||
|
||||
`release` 是正式生产稳定分支。只有正式发布和生产 hotfix 应进入该分支。
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run test:unit
|
||||
npm run type-check
|
||||
npm run build
|
||||
cd ..
|
||||
```
|
||||
|
||||
## release 分支安装
|
||||
|
||||
### 1. 切换分支
|
||||
|
||||
@@ -204,125 +348,248 @@ git checkout release
|
||||
git pull --rebase origin release
|
||||
```
|
||||
|
||||
### 2. 配置 `.env`
|
||||
### 2. 准备 HTTPS 域名
|
||||
|
||||
生产环境必须使用生产专用配置:
|
||||
正式访问地址必须是:
|
||||
|
||||
```env
|
||||
COMPOSE_PROJECT_NAME=ctms_prod
|
||||
ENV=production
|
||||
JWT_SECRET_KEY=<production-strong-random-secret>
|
||||
LOGIN_RSA_KEY_ID=prod-YYYYMMDD
|
||||
LOGIN_RSA_PRIVATE_KEY=<production-rsa-private-key-pem-with-\n-escaped-newlines>
|
||||
```text
|
||||
https://<production-domain>
|
||||
```
|
||||
|
||||
要求:
|
||||
如果服务器前面有反向代理,确认代理规则:
|
||||
|
||||
- `.env` 必须只保存在部署机器或密钥管理系统中。
|
||||
- 不得提交 `.env`、私钥、JWT 密钥。
|
||||
- `JWT_SECRET_KEY` 轮换会使既有 token 失效,应安排维护窗口。
|
||||
- `LOGIN_RSA_PRIVATE_KEY` 轮换会影响新登录密钥获取,应同步更新 `LOGIN_RSA_KEY_ID`。
|
||||
```text
|
||||
/ -> CTMS nginx 8888
|
||||
/api/* -> CTMS nginx 8888
|
||||
/health -> CTMS nginx 8888
|
||||
```
|
||||
|
||||
### 3. HTTPS 要求
|
||||
### 3. 生成密钥
|
||||
|
||||
登录加密依赖浏览器 WebCrypto。生产访问必须使用 HTTPS:
|
||||
生成 JWT 密钥:
|
||||
|
||||
- `https://正式域名`
|
||||
- 本地 `localhost` 是浏览器安全上下文例外,但不能代表生产可用性
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
如果生产仍通过 `http://服务器IP:8888` 访问,前端会拒绝执行登录加密。
|
||||
生成 RSA 私钥文件:
|
||||
|
||||
### 4. 初始化与迁移
|
||||
```bash
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out login_rsa_release.pem
|
||||
```
|
||||
|
||||
首次部署或每次包含 migration 的发布:
|
||||
生成可写入 `.env` 的 RSA 私钥单行文本:
|
||||
|
||||
```bash
|
||||
awk '{printf "%s\\n", $0}' login_rsa_release.pem
|
||||
```
|
||||
|
||||
将 `login_rsa_release.pem` 保存到服务器安全目录或密钥管理系统。
|
||||
|
||||
### 4. 写入环境配置
|
||||
|
||||
在仓库根目录创建或覆盖 `.env`,将占位符替换为生产值:
|
||||
|
||||
```bash
|
||||
cat > .env <<'EOF'
|
||||
COMPOSE_PROJECT_NAME=ctms_release
|
||||
ENV=production
|
||||
JWT_SECRET_KEY=<替换为生产 JWT 密钥>
|
||||
LOGIN_RSA_KEY_ID=release-YYYYMMDD
|
||||
LOGIN_RSA_PRIVATE_KEY=<替换为生产 RSA 私钥单行文本>
|
||||
EOF
|
||||
```
|
||||
|
||||
确认 `.env` 没有进入 Git 暂存区:
|
||||
|
||||
```bash
|
||||
git status --short .env
|
||||
```
|
||||
|
||||
预期无输出。
|
||||
|
||||
### 5. 检查 Compose 配置
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
```
|
||||
|
||||
确认输出中包含:
|
||||
|
||||
```text
|
||||
ENV: production
|
||||
JWT_SECRET_KEY: <不是 dev-secret>
|
||||
LOGIN_RSA_KEY_ID: release-YYYYMMDD
|
||||
LOGIN_RSA_PRIVATE_KEY: '-----BEGIN PRIVATE KEY-----...'
|
||||
```
|
||||
|
||||
### 6. 初始化数据库
|
||||
|
||||
```bash
|
||||
docker compose run --rm backend-init
|
||||
```
|
||||
|
||||
确认 migration 成功后再启动或滚动重启服务。
|
||||
确认命令成功后再启动服务。
|
||||
|
||||
### 5. 启动
|
||||
### 7. 构建镜像并启动
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### 6. 生产验证
|
||||
### 8. 执行数据库迁移
|
||||
|
||||
已有数据库升级到新代码时,启动后执行一次迁移:
|
||||
|
||||
```bash
|
||||
docker compose run --rm backend python -m alembic upgrade head
|
||||
```
|
||||
|
||||
`backend-init` 会在初始化时处理空库和已有库迁移;这里单独执行迁移用于确认部署代码已落到最新数据库版本。
|
||||
|
||||
### 9. 检查容器状态
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose exec backend python -c "from app.core.config import settings; print(settings.ENV); print(settings.JWT_SECRET_KEY == 'dev-secret'); print(bool(settings.LOGIN_RSA_PRIVATE_KEY)); print(settings.LOGIN_RSA_KEY_ID)"
|
||||
```
|
||||
|
||||
确认 `ctms_db`、`ctms_backend`、`ctms_nginx` 都是 `Up`,且 `ctms_db` 为 `healthy`。
|
||||
|
||||
### 10. 检查后端环境
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -c "from app.core.config import settings; print('ENV=' + settings.ENV); print('JWT_SECRET_IS_DEV=' + str(settings.JWT_SECRET_KEY == 'dev-secret')); print('LOGIN_RSA_PRIVATE_KEY_SET=' + str(bool(settings.LOGIN_RSA_PRIVATE_KEY))); print('LOGIN_RSA_KEY_ID=' + settings.LOGIN_RSA_KEY_ID)"
|
||||
```
|
||||
|
||||
预期输出:
|
||||
|
||||
```text
|
||||
ENV=production
|
||||
JWT_SECRET_IS_DEV=False
|
||||
LOGIN_RSA_PRIVATE_KEY_SET=True
|
||||
LOGIN_RSA_KEY_ID=release-YYYYMMDD
|
||||
```
|
||||
|
||||
### 11. 检查生产接口
|
||||
|
||||
```bash
|
||||
curl -i https://<production-domain>/health
|
||||
curl -i https://<production-domain>/api/v1/auth/login-key
|
||||
```
|
||||
|
||||
预期:
|
||||
两个接口都应返回 `HTTP/1.1 200 OK`。
|
||||
|
||||
### 12. 打开系统并登录
|
||||
|
||||
```text
|
||||
https://<production-domain>
|
||||
```
|
||||
|
||||
初始化管理员:
|
||||
|
||||
```text
|
||||
admin@huapont.cn / admin123
|
||||
```
|
||||
|
||||
首次登录后立即修改初始密码。
|
||||
|
||||
### 13. 发布后检查
|
||||
|
||||
查看容器:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
查看后端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs --tail=200 backend
|
||||
```
|
||||
|
||||
查看 nginx 日志:
|
||||
|
||||
```bash
|
||||
docker compose logs --tail=200 nginx
|
||||
```
|
||||
|
||||
执行 smoke:
|
||||
|
||||
```bash
|
||||
BASE_URL=https://<production-domain> EMAIL=<admin-email> PASSWORD=<admin-password> bash docs/setup-config-curl-smoke.sh
|
||||
```
|
||||
|
||||
## 常见安装问题
|
||||
|
||||
### 端口被占用
|
||||
|
||||
检查:
|
||||
|
||||
```bash
|
||||
lsof -nP -iTCP:8888 -sTCP:LISTEN
|
||||
lsof -nP -iTCP:8000 -sTCP:LISTEN
|
||||
lsof -nP -iTCP:5432 -sTCP:LISTEN
|
||||
```
|
||||
|
||||
处理:停止占用进程,或调整 `docker-compose.yaml` 端口映射。
|
||||
|
||||
### 容器名冲突
|
||||
|
||||
检查:
|
||||
|
||||
```bash
|
||||
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||||
```
|
||||
|
||||
处理:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
如果同一台机器要同时运行多套 CTMS,需为每套环境调整 `docker-compose.yaml` 中的 `container_name` 和端口。
|
||||
|
||||
### production 启动失败
|
||||
|
||||
检查:
|
||||
|
||||
```bash
|
||||
grep -n "ENV\\|JWT_SECRET_KEY\\|LOGIN_RSA" .env
|
||||
```
|
||||
|
||||
确认:
|
||||
|
||||
```text
|
||||
ENV=production
|
||||
JWT_SECRET_KEY == dev-secret -> False
|
||||
LOGIN_RSA_PRIVATE_KEY_SET -> True
|
||||
GET /health -> 200
|
||||
GET /api/v1/auth/login-key -> 200
|
||||
JWT_SECRET_KEY 不是 dev-secret
|
||||
LOGIN_RSA_PRIVATE_KEY 不是空值
|
||||
LOGIN_RSA_PRIVATE_KEY 包含 -----BEGIN PRIVATE KEY-----
|
||||
```
|
||||
|
||||
### 7. 多实例约束
|
||||
### 远程访问无法登录
|
||||
|
||||
当前登录 challenge 默认保存在后端进程内:
|
||||
检查当前浏览器地址。如果不是 `https://`,改用 HTTPS 域名访问:
|
||||
|
||||
- 单实例、单 worker:可直接使用
|
||||
- 多实例或多 worker:必须满足以下至少一项
|
||||
- 使用共享缓存保存 challenge,例如 Redis
|
||||
- 启用粘性会话,确保 `/login-key` 与 `/login` 命中同一后端进程
|
||||
- 将后端限制为单 worker 单副本
|
||||
|
||||
如果不满足,上线后可能出现偶发登录失败。
|
||||
|
||||
## 环境变量说明
|
||||
|
||||
| 变量 | dev | main/staging | release/production | 说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `COMPOSE_PROJECT_NAME` | `ctms_dev` | `ctms_staging` | `ctms_prod` | 防止不同环境容器名、网络名冲突 |
|
||||
| `ENV` | `development` | `production` | `production` | 后端运行模式 |
|
||||
| `JWT_SECRET_KEY` | `dev-secret` | 强随机 | 强随机 | JWT 签名密钥 |
|
||||
| `LOGIN_RSA_KEY_ID` | `default` | `staging-YYYYMMDD` | `prod-YYYYMMDD` | 登录 RSA 密钥版本 |
|
||||
| `LOGIN_RSA_PRIVATE_KEY` | 空 | staging 私钥 | production 私钥 | RSA 私钥,生产模式必填 |
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 登录页提示当前浏览器环境不支持安全登录加密
|
||||
|
||||
原因:非 HTTPS、非 localhost 的访问环境不满足 WebCrypto 安全上下文要求。
|
||||
|
||||
处理:
|
||||
|
||||
- 本地使用 `http://localhost:8888`
|
||||
- staging/production 使用 HTTPS 域名
|
||||
|
||||
### production 模式启动失败,提示必须配置 LOGIN_RSA_PRIVATE_KEY
|
||||
|
||||
原因:`ENV=production` 时必须提供固定 RSA 私钥。
|
||||
|
||||
处理:
|
||||
|
||||
```bash
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048
|
||||
```text
|
||||
https://<domain>
|
||||
```
|
||||
|
||||
将输出 PEM 写入 `.env` 的 `LOGIN_RSA_PRIVATE_KEY`,换行使用 `\n` 转义。
|
||||
本机 `dev` 可使用:
|
||||
|
||||
### 切换分支后环境不符合预期
|
||||
|
||||
分支不会自动修改 `.env`。切换分支后应重新确认:
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
docker compose exec backend python -c "from app.core.config import settings; print(settings.ENV)"
|
||||
```text
|
||||
http://localhost:8888
|
||||
```
|
||||
|
||||
必要时修改 `.env` 并重启:
|
||||
### 切换分支后环境不正确
|
||||
|
||||
重新执行对应分支的 `.env` 配置,然后重建:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build backend nginx
|
||||
```
|
||||
|
||||
再检查:
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -c "from app.core.config import settings; print(settings.ENV)"
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user