7.5 KiB
7.5 KiB
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 |
标准部署流程
部署到测试环境
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"
部署到生产环境
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(备选方案)
本地网络慢时,在新加坡服务器构建:
# 后端
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 → 生产自动部署
服务管理
# 查看容器状态
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 .
测试环境管理
# 查看状态
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
volumes:
postgres_prod_data:
external: true
name: ai-project_postgres_prod_data
redis_prod_data:
external: true
name: ai-project_redis_prod_data
数据库操作
# 运行迁移
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 解释,必须使用文件传输方式:
# 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 | 租户用户 |
重置密码
# 生成新哈希并更新
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_URLREACT_APP_API_BASE_URL
否则会使用 .env.production 中的生产 URL。
验证镜像中的 URL:
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'