Files
ai-proj-helper/plugins/ops-tools-plugin/ai-proj-deploy.md

247 lines
7.5 KiB
Markdown
Raw 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.
# AI-Proj 部署指南
**创建时间**: 2026-01-29 11:50:00 CST
**父技能**: ops-tools
## 环境概览
| 环境 | 服务器 | 域名 | 镜像标签 |
|------|--------|------|----------|
| 生产 | tools_ai_proj (152.136.104.251) | https://ai.pipexerp.com | `latest` |
| 测试 | singapore (43.134.28.147) | http://staging.ai.pipexerp.com | `test` |
## 镜像信息
| 服务 | 镜像 |
|------|------|
| 后端 | `saltthing123/ai-proj-backend` |
| 前端 | `saltthing123/ai-proj-frontend` |
## 标准部署流程
### 部署到测试环境
```bash
cd /path/to/new-ai-proj
# 构建后端 test 镜像
docker buildx build --platform linux/amd64 -f backend/Dockerfile --target production \
-t saltthing123/ai-proj-backend:test --push backend/
# 构建前端 test 镜像
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 \
--build-arg REACT_APP_ENV=staging \
-t saltthing123/ai-proj-frontend:test --push frontend/
# 部署到测试服务器
ssh singapore "cd /opt/ai-project-staging && sudo docker-compose pull && sudo docker-compose up -d"
```
### 部署到生产环境
```bash
cd /path/to/new-ai-proj
# 构建后端 latest 镜像
docker buildx build --platform linux/amd64 -f backend/Dockerfile --target production \
-t saltthing123/ai-proj-backend:latest --push backend/
# 构建前端 latest 镜像
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 \
--build-arg REACT_APP_ENV=production \
-t saltthing123/ai-proj-frontend:latest --push frontend/
# 部署到生产服务器
ssh tools_ai_proj "cd /opt/ai-project && \
docker compose -f deploy/tencent-cloud/docker-compose.dockerhub.yml pull && \
docker compose -f deploy/tencent-cloud/docker-compose.dockerhub.yml up -d"
```
## 新加坡服务器 Build备选方案
本地网络慢时,在新加坡服务器构建:
```bash
# 后端
ssh singapore "cd ~/projects/new-ai-proj && git pull && \
docker build --platform linux/amd64 -f backend/Dockerfile --target production \
-t saltthing123/ai-proj-backend:latest ./backend && \
docker push saltthing123/ai-proj-backend:latest"
# 前端(生产)
ssh singapore "cd ~/projects/new-ai-proj && \
docker 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 \
--build-arg REACT_APP_ENV=production \
-t saltthing123/ai-proj-frontend:latest ./frontend && \
docker push saltthing123/ai-proj-frontend:latest"
```
## 自动部署Webhook
**状态**: 已启用 (2026-01-16)
```
git push main → Gitea webhook → Jenkins ai-proj → 生产自动部署
```
## 服务管理
```bash
# 查看容器状态
ssh tools_ai_proj "docker ps --format 'table {{.Names}}\t{{.Status}}'"
# 查看日志
ssh tools_ai_proj "docker logs -f ai_backend_prod --tail 100"
# 重启服务
ssh tools_ai_proj "docker restart ai_backend_prod"
# 健康检查
curl -s https://ai.pipexerp.com/api/v1/health | jq .
```
## 测试环境管理
```bash
# 查看状态
ssh singapore "sudo docker-compose -f /opt/ai-project-staging/docker-compose.yml ps"
# 查看日志
ssh singapore "sudo docker logs -f ai_backend_staging --tail 100"
# 健康检查
ssh singapore "curl -s -H 'Host: staging.ai.pipexerp.com' http://127.0.0.1/api/v1/health"
```
## Docker Volumes 配置
**重要**: 数据卷必须标记为 `external: true`
```yaml
volumes:
postgres_prod_data:
external: true
name: ai-project_postgres_prod_data
redis_prod_data:
external: true
name: ai-project_redis_prod_data
```
## 数据库操作
```bash
# 运行迁移
ssh tools_ai_proj "cd /opt/ai-project/backend/migrations && \
for file in \$(ls *.sql | grep -v _down.sql | sort); do \
docker exec -i ai_postgres_prod psql -U ai_prod_user -d ai_project_prod < \"\$file\"; \
done"
# 备份
ssh tools_ai_proj "docker exec ai_postgres_prod pg_dump -U ai_prod_user ai_project_prod > /tmp/backup.sql"
```
## 用户管理
> **重要**: 密码哈希必须使用 bcrypt **cost 12**,这是后端 `utils/password.go` 中的 `DefaultCost` 值。
### 创建用户完整流程
由于 bcrypt 哈希包含 `$` 字符会被 shell 解释,必须使用文件传输方式:
```bash
# 1. 生成密码哈希(在有 Go 环境的机器上执行)
cd /path/to/new-ai-proj/backend
cat > /tmp/genhash.go << 'EOF'
package main
import ("fmt"; "golang.org/x/crypto/bcrypt")
func main() {
hash, _ := bcrypt.GenerateFromPassword([]byte("用户密码"), 12)
fmt.Println(string(hash))
}
EOF
HASH=$(go run /tmp/genhash.go)
echo "Generated hash: $HASH"
# 2. 创建 SQL 文件
cat > /tmp/create_user.sql << EOF
INSERT INTO users (username, email, password_hash, user_type, role, status, created_at, updated_at)
VALUES ('newuser', 'newuser@example.com', '$HASH', 'system', 'admin', 'active', NOW(), NOW());
EOF
# 3. 传输并执行
scp /tmp/create_user.sql tools_ai_proj:/tmp/
ssh tools_ai_proj "docker cp /tmp/create_user.sql ai_postgres_prod:/tmp/ && \
docker exec ai_postgres_prod psql -U ai_prod_user -d ai_project_prod -f /tmp/create_user.sql"
# 4. 验证
curl -s -X POST "https://ai.pipexerp.com/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"newuser","password":"用户密码"}' | jq '.success'
```
### 用户角色
| user_type | role | 权限 |
|-----------|------|------|
| system | admin | 系统管理员 |
| system | user | 系统用户 |
| tenant | admin | 租户管理员 |
| tenant | user | 租户用户 |
### 重置密码
```bash
# 生成新哈希并更新
cd /path/to/new-ai-proj/backend
HASH=$(go run -e 'package main; import ("fmt";"golang.org/x/crypto/bcrypt"); func main() { h,_:=bcrypt.GenerateFromPassword([]byte("新密码"),12); fmt.Println(string(h)) }' 2>/dev/null || cat > /tmp/h.go << 'E'
package main
import ("fmt";"golang.org/x/crypto/bcrypt")
func main() { h,_:=bcrypt.GenerateFromPassword([]byte("新密码"),12); fmt.Println(string(h)) }
E
go run /tmp/h.go)
cat > /tmp/reset.sql << EOF
UPDATE users SET password_hash = '$HASH' WHERE username = 'targetuser';
EOF
scp /tmp/reset.sql tools_ai_proj:/tmp/
ssh tools_ai_proj "docker cp /tmp/reset.sql ai_postgres_prod:/tmp/ && \
docker exec ai_postgres_prod psql -U ai_prod_user -d ai_project_prod -f /tmp/reset.sql"
```
### 常见错误
| 问题 | 原因 | 解决 |
|------|------|------|
| 登录失败 | bcrypt cost 不是 12 | 用 Go 重新生成 cost 12 的哈希 |
| 哈希被截断 | shell 解释了 $ 符号 | 使用文件传输方式 |
### 已创建的系统用户
| 用户名 | 邮箱 | user_type | role | 创建时间 |
|--------|------|-----------|------|----------|
| qiudl | qiudl@zhiyuncai.com | system | admin | - |
| jiaxiang | jiaxiang@joylodging.com | system | admin | 2026-01 |
| haiqing | haiqing@joylodging.com | system | admin | 2026-02 |
> 注意:密码信息不在文档中记录,如需重置请使用上述重置密码流程
## 前端构建注意事项
必须同时设置两个 URL 变量:
- `REACT_APP_API_URL`
- `REACT_APP_API_BASE_URL`
否则会使用 `.env.production` 中的生产 URL。
验证镜像中的 URL
```bash
docker exec <container> sh -c 'grep -oE "https://[a-zA-Z0-9.-]*pipexerp[a-zA-Z0-9./-]*" /usr/share/nginx/html/static/js/main*.js | sort | uniq -c'
```