# 部署指南 ## 部署流程概览 ``` Staging 部署(手动) Production 部署(Jenkins) ↓ ↓ 本地构建 :test 镜像 本地构建 :latest 镜像 ↓ ↓ 推送到 DockerHub 推送到 DockerHub ↓ ↓ 显示部署命令 调用 Jenkins API ↓ ↓ 用户手动执行 自动触发部署 ↓ ↓ 验证 API 轮询构建状态 ↓ 验证 API ``` ## 环境说明 | 环境 | 触发方式 | 镜像标签 | 用途 | |------|----------|----------|------| | staging | 手动 SSH | `:test` | 预发布测试 | | production | Jenkins API | `:latest` | 正式生产 | ## 镜像构建规范 > ⚠️ **重要**: 必须理解 Dockerfile target 和镜像标签的区别 ### Dockerfile Target vs 镜像标签 | 概念 | 说明 | 示例 | |------|------|------| | **Dockerfile Target** | 构建阶段,决定镜像内容 | `--target production`, `--target test` | | **镜像标签** | 版本标识,决定部署环境 | `:test`, `:latest` | ### 正确的构建方式 | 用途 | Dockerfile Target | 镜像标签 | 镜像大小 | |------|-------------------|----------|----------| | **Staging 部署** | `--target production` | `:test` | ~50MB | | **Production 部署** | `--target production` | `:latest` | ~50MB | | **运行单元测试** | `--target test` | 无需推送 | ~900MB+ | ### 常见错误 ❌ **错误做法**:用 `--target test` 构建部署镜像 ```bash # 错误!这会生成 900MB+ 的镜像,包含测试框架和源代码 docker buildx build --target test -t xxx:test ... ``` ✅ **正确做法**:用 `--target production` 构建部署镜像 ```bash # 正确!生成 ~50MB 的精简镜像,只包含二进制文件 docker buildx build --target production -t xxx:test ... ``` ### Staging vs Production 镜像区别 两者都使用 `--target production` 构建,区别在于: | 区别点 | Staging (`:test`) | Production (`:latest`) | |--------|-------------------|------------------------| | 镜像标签 | `:test` | `:latest` | | 前端 API URL | `staging.ai.pipexerp.com` | `ai.pipexerp.com` | | 后端代码 | 完全相同 | 完全相同 | | 部署服务器 | singapore | tools_ai_proj | > **注意**: 不是把 staging 镜像部署到生产,而是测试通过后用生产 URL **重新构建** `:latest` 镜像 ## Staging 部署 ### 前置条件 > ⚠️ **必须完成本机测试才能部署 staging** | 检查项 | 说明 | |--------|------| | 代码评审 | `/req cr` 已完成 | | 后端单元测试 | `go test ./... -v` 全部通过 | | **前端截图验证** | 使用 chrome-dev MCP 截图确认 UI 正确显示 | 如果本机测试未通过,将拒绝部署并提示: ``` → ❌ 本机测试未完成,禁止部署到 staging → 请先执行: /req test REQ-XXX ``` ### 命令格式 ```bash /req deploy REQ-XXX --env staging [--service ] ``` ### 支持的服务 | 服务 | 说明 | |------|------| | `backend` | 后端 API 服务 | | `frontend` | 前端 Web 应用 | | `all` | 全部服务(默认) | ### 执行流程 1. **构建镜像**(本地执行) ```bash # 后端 docker buildx build --platform linux/amd64 \ -f backend/Dockerfile --target production \ -t saltthing123/ai-proj-backend:test --push backend/ # 前端(注意 API URL 配置) docker buildx build --platform linux/amd64 \ -f frontend/Dockerfile.prod --target production \ --build-arg REACT_APP_API_URL=https://staging.ai.pipexerp.com/api/v1 \ --build-arg REACT_APP_API_BASE_URL=https://staging.ai.pipexerp.com/api/v1 \ -t saltthing123/ai-proj-frontend:test --push frontend/ ``` 2. **部署命令**(用户手动执行) ```bash ssh singapore "cd /opt/ai-project-staging && \ sudo docker-compose pull && \ sudo docker-compose up -d" ``` 3. **验证** ```bash curl -s https://staging.ai.pipexerp.com/api/v1/health | jq . ``` ## Production 部署 ### 命令格式 ```bash /req deploy REQ-XXX --env production [--service ] ``` ### 支持的服务 | 服务 | 镜像名 | Jenkins 参数 | |------|--------|--------------| | `backend` | saltthing123/ai-proj-backend | SERVICE=backend | | `frontend` | saltthing123/ai-proj-frontend | SERVICE=frontend | | `ios` | - | SERVICE=ios | | `android` | - | SERVICE=android | | `all` | 全部 | SERVICE=all(默认) | ### 执行流程 1. **构建镜像**(本地执行) ```bash # 后端 docker buildx build --platform linux/amd64 \ -f backend/Dockerfile --target production \ -t saltthing123/ai-proj-backend:latest --push backend/ # 前端 docker buildx build --platform linux/amd64 \ -f frontend/Dockerfile.prod --target production \ --build-arg REACT_APP_API_URL=https://ai.pipexerp.com/api/v1 \ --build-arg REACT_APP_API_BASE_URL=https://ai.pipexerp.com/api/v1 \ -t saltthing123/ai-proj-frontend:latest --push frontend/ ``` 2. **触发 Jenkins 部署** ```bash source ~/.config/devops/credentials.env curl -X POST "$JENKINS_URL/job/ai-proj/buildWithParameters" \ -u "$JENKINS_USER:$JENKINS_TOKEN" \ --data "SERVICE=backend&IMAGE_TAG=latest" ``` 3. **查看构建状态** ```bash source ~/.config/devops/credentials.env curl -s "$JENKINS_URL/job/ai-proj/lastBuild/api/json" \ -u "$JENKINS_USER:$JENKINS_TOKEN" | jq '.result, .building' ``` 4. **验证** ```bash curl -s https://ai.pipexerp.com/api/v1/health | jq . ``` ## 安全约束 - **禁止自动 SSH 部署到生产服务器** - 生产环境部署必须通过 Jenkins API 触发 - Staging 部署命令只显示,由用户手动执行 - 构建失败时必须显示错误原因和解决方案 ## 项目配置 ### AI-Proj | 配置项 | 值 | |--------|-----| | Jenkins Job | ai-proj | | Staging 服务器 | singapore | | Production 服务器 | tools_ai_proj | | DockerHub 用户 | saltthing123 | ### Coolbuy-Paas | 配置项 | 值 | |--------|-----| | Jenkins Job | coolbuy-paas | | Staging 服务器 | fnos 测试环境 | | Production 服务器 | 39.106.88.83 | | DockerHub 用户 | saltthing123 | ## 常见问题 ### Docker 推送失败 **错误**: `push access denied` **解决**: ```bash docker login # 输入 Docker Hub 凭据 ``` ### Jenkins 构建失败 **查看日志**: ```bash source ~/.config/devops/credentials.env curl -s "$JENKINS_URL/job/ai-proj/lastBuild/consoleText" \ -u "$JENKINS_USER:$JENKINS_TOKEN" | tail -100 ``` ### 镜像架构不匹配 **错误**: `exec format error` **原因**: 在 ARM64 (M1/M2 Mac) 构建的镜像部署到 AMD64 服务器 **解决**: 构建时必须指定 `--platform linux/amd64` ### 镜像体积异常大(900MB+) **错误**: 构建的镜像超过 100MB **原因**: 使用了错误的 Dockerfile target **检查**: ```bash # 查看镜像层大小 docker history : --no-trunc --format "{{.Size}}\t{{.CreatedBy}}" | head -10 ``` **常见原因**: | 层内容 | 大小 | 说明 | |--------|------|------| | `go mod download` | 600MB+ | Go 依赖包(不应出现在生产镜像) | | `ginkgo/gomega` | 200MB+ | 测试框架(不应出现在生产镜像) | | `COPY . .` | 100MB+ | 源代码(不应出现在生产镜像) | **解决**: 确保使用 `--target production` 而不是 `--target test` ```bash # 错误 docker buildx build --target test ... # 正确 docker buildx build --target production ... ```