# CTMS 安装步骤向导 按目标分支选择对应章节执行: - [dev 分支安装](#dev-分支安装) - [main 分支安装](#main-分支安装) - [release 分支安装](#release-分支安装) ## 安装前准备 三个分支都先完成本节。 ### 1. 准备安装目录 ```bash mkdir -p /opt/ctms cd /opt/ctms ``` ### 2. 安装 Docker Linux 可使用 Docker Engine 或 Docker Desktop。安装完成后确认 Docker Compose v2 可用: ```bash docker --version docker compose version ``` 如果当前用户不能执行 Docker 命令,将用户加入 `docker` 组后重新登录: ```bash sudo usermod -aG docker "$USER" ``` macOS 安装 Docker Desktop 后执行: ```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. 切换分支 ```bash git checkout dev git pull --rebase origin dev ``` ### 2. 写入环境配置 在仓库根目录创建或覆盖 `.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 ``` ### 3. 构建镜像并启动 ```bash docker compose up -d --build ``` ### 4. 执行数据库迁移 已有数据库升级到新代码时,启动后执行一次迁移: ```bash docker compose run --rm backend python -m alembic upgrade head ``` 首次空库安装也可以执行该命令;如果已是最新版本,Alembic 不会重复应用迁移。 ### 5. 检查容器状态 ```bash docker compose ps ``` 确认 `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 http://localhost:8888 ``` ### 9. 运行验证 后端: ```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. 切换分支 ```bash git checkout main git pull --rebase origin main ``` ### 2. 生成密钥 生成 JWT 密钥: ```bash openssl rand -hex 32 ``` 生成 RSA 私钥文件: ```bash openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out login_rsa_main.pem ``` 生成可写入 `.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 ``` ### 6. 构建镜像并启动 ```bash docker compose up -d --build ``` ### 7. 执行数据库迁移 已有数据库升级到新代码时,启动后执行一次迁移: ```bash docker compose run --rm backend python -m alembic upgrade head ``` `backend-init` 会在初始化时处理空库和已有库迁移;这里单独执行迁移用于确认部署代码已落到最新数据库版本。 ### 8. 检查容器状态 ```bash docker compose ps ``` 确认 `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 ``` 远程域名: ```bash curl -i https:///health curl -i https:///api/v1/auth/login-key ``` 接口应返回 `HTTP/1.1 200 OK`。 ### 11. 打开系统 本机: ```text http://localhost:8888 ``` 远程访问: ```text https:// ``` 远程访问必须使用 HTTPS。 ### 12. 运行验证 后端: ```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 .. ``` ## release 分支安装 ### 1. 切换分支 ```bash git checkout release git pull --rebase origin release ``` ### 2. 准备 HTTPS 域名 正式访问地址必须是: ```text https:// ``` 如果服务器前面有反向代理,确认代理规则: ```text / -> CTMS nginx 8888 /api/* -> CTMS nginx 8888 /health -> CTMS nginx 8888 ``` ### 3. 生成密钥 生成 JWT 密钥: ```bash openssl rand -hex 32 ``` 生成 RSA 私钥文件: ```bash openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out login_rsa_release.pem ``` 生成可写入 `.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 ``` 确认命令成功后再启动服务。 ### 7. 构建镜像并启动 ```bash docker compose up -d --build ``` ### 8. 执行数据库迁移 已有数据库升级到新代码时,启动后执行一次迁移: ```bash docker compose run --rm backend python -m alembic upgrade head ``` `backend-init` 会在初始化时处理空库和已有库迁移;这里单独执行迁移用于确认部署代码已落到最新数据库版本。 ### 9. 检查容器状态 ```bash docker compose ps ``` 确认 `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:///health curl -i https:///api/v1/auth/login-key ``` 两个接口都应返回 `HTTP/1.1 200 OK`。 ### 12. 打开系统并登录 ```text https:// ``` 初始化管理员: ```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:// EMAIL= 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 LOGIN_RSA_PRIVATE_KEY 不是空值 LOGIN_RSA_PRIVATE_KEY 包含 -----BEGIN PRIVATE KEY----- ``` ### 远程访问无法登录 检查当前浏览器地址。如果不是 `https://`,改用 HTTPS 域名访问: ```text https:// ``` 本机 `dev` 可使用: ```text http://localhost:8888 ``` ### 切换分支后环境不正确 重新执行对应分支的 `.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)" ```