7.0 KiB
AI Platform 打包部署指南
项目概况
| 项目 | 说明 |
|---|---|
| 项目名称 | ai-platform |
| 前端框架 | React 18 + TypeScript + Vite 8 |
| UI 库 | Ant Design 5 + Tailwind CSS 3 |
| 构建产物 | 静态文件(dist/),由 nginx 提供服务 |
| 容器化 | Docker 多阶段构建(builder → nginx:alpine) |
| 部署端口 | 8901 |
| 后端代理 | http://host.docker.internal:8000(可运行时覆盖) |
目录结构要点
ai-platform/
├── Dockerfile # 多阶段构建:node:20-alpine 构建 → nginx:alpine 运行
├── nginx.conf # nginx 配置模板(支持 ${BACKEND_URL} 环境变量替换)
├── .dockerignore # 排除 node_modules / dist / .git / *.md 等
├── package.json # build 脚本:tsc -b && vite build
├── vite.config.ts # 开发代理配置(/api/v1, /health, /bexapi, /iam-api)
├── index.html # 入口 HTML
├── src/ # 源码
├── public/ # 静态资源
└── docs/ # 文档(本文件所在目录)
Docker 镜像构建
Dockerfile 构建流程
-
Stage 1 — builder(node:20-alpine)
- 复制
package.json+package-lock.json,执行npm install - 复制全部源码,执行
npm run build(即tsc -b && vite build) - 产物输出到
/app/dist
- 复制
-
Stage 2 — 运行时(nginx:alpine)
- 将 builder 阶段的
/app/dist复制到/usr/share/nginx/html - 复制
nginx.conf到/etc/nginx/templates/default.conf.template(nginx 入口脚本会通过envsubst替换其中的${BACKEND_URL}) - 默认环境变量
BACKEND_URL=http://host.docker.internal:8000 - 暴露端口 8901
- 将 builder 阶段的
构建命令
sudo docker build -t ai-platform:1.0.0 .
构建过程利用了 Docker 缓存层:如果 package.json / package-lock.json 未变,npm install 层会命中缓存,仅重新执行源码复制和构建。
容器部署
启动命令
sudo docker run -d \
--name ai-platform \
-p 8901:8901 \
--add-host=host.docker.internal:host-gateway \
-e BACKEND_URL=http://host.docker.internal:8000 \
ai-platform:1.0.0
参数说明
| 参数 | 说明 |
|---|---|
-d |
后台运行 |
--name ai-platform |
容器名称 |
-p 8901:8901 |
宿主机 8901 端口映射到容器 8901 |
--add-host=host.docker.internal:host-gateway |
必须添加,否则 nginx 启动时无法解析 host.docker.internal,容器会立即退出(exit code 1) |
-e BACKEND_URL=... |
后端 API 地址,运行时可覆盖。默认 http://host.docker.internal:8000 |
踩坑记录:Docker 29.x 版本中,
host.docker.internal不会自动解析,必须通过--add-host=host.docker.internal:host-gateway显式添加。如果不加此参数,nginx 启动报错:host not found in upstream "host.docker.internal",容器退出码为 1。
重新部署(完整流程)
# 1. 构建新镜像
sudo docker build -t ai-platform:1.0.0 .
# 2. 停止并移除旧容器
sudo docker stop ai-platform
sudo docker rm ai-platform
# 3. 启动新容器
sudo docker run -d \
--name ai-platform \
-p 8901:8901 \
--add-host=host.docker.internal:host-gateway \
-e BACKEND_URL=http://host.docker.internal:8000 \
ai-platform:1.0.0
验证部署
# 检查容器运行状态
sudo docker ps --filter "name=ai-platform"
# 从容器内部验证 nginx 响应
sudo docker exec ai-platform curl -s -o /dev/null -w "HTTP %{http_code}" http://localhost:8901/
# 预期输出:HTTP 200
# 查看页面内容
sudo docker exec ai-platform curl -s http://localhost:8901/
# 查看 nginx 日志
sudo docker logs ai-platform
nginx 配置说明
nginx.conf 作为模板文件放在 /etc/nginx/templates/default.conf.template,nginx 容器入口脚本会自动用 envsubst 将 ${BACKEND_URL} 替换为环境变量值,输出到 /etc/nginx/conf.d/default.conf。
路由规则
| 路径 | 代理目标 | 说明 |
|---|---|---|
/api/v1/ |
${BACKEND_URL}/api/v1/ |
后端 API,支持 SSE 长连接(关闭 buffering,300s 超时) |
/health |
${BACKEND_URL}/health |
健康检查 |
/bexapi/ |
https://bexell-scheduling.dongsk.top/api/ |
Bexell 排程 API |
/iam-api/ |
https://iam.digiwincloud.com.cn/ |
鼎捷云 IAM 登录服务 |
/ |
try_files $uri $uri/ /index.html |
SPA 路由 fallback |
/assets/ |
本地静态文件 | 长缓存 1 年,Cache-Control: public, immutable |
*.svg/png/jpg/... |
本地静态文件 | 缓存 30 天 |
开发环境 vs 生产环境代理对照
开发时由 Vite dev server 代理(vite.config.ts),生产时由 nginx 代理(nginx.conf),两者路径需保持一致:
| 路径 | Vite target | nginx proxy_pass |
|---|---|---|
/api/v1 |
http://localhost:8000 |
${BACKEND_URL}/api/v1/ |
/health |
http://localhost:8000 |
${BACKEND_URL}/health |
/bexapi |
https://bexell-scheduling.dongsk.top(rewrite → /api) |
https://bexell-scheduling.dongsk.top/api/ |
/iam-api |
https://iam.digiwincloud.com.cn(rewrite → 去前缀) |
https://iam.digiwincloud.com.cn/ |
常见问题排查
容器启动后立即退出(exit code 1)
原因:nginx 无法解析 host.docker.internal。
解决:启动时添加 --add-host=host.docker.internal:host-gateway。
验证:sudo docker logs ai-platform 查看是否有 host not found in upstream 错误。
构建时 TypeScript 编译失败
npm run build 先执行 tsc -b 类型检查,类型错误会导致构建中断。需修复所有 TS 错误后重新构建。
构建产物体积过大
当前主 chunk 约 1.9MB(gzip 后 581KB),Vite 会输出警告。如需优化:
- 使用动态
import()对路由模块做懒加载(代码分割) - 在
vite.config.ts中配置build.rollupOptions.output.manualChunks手动分包 - 调整
build.chunkSizeWarningLimit提高警告阈值(仅消除警告,不减小体积)
端口被占用
# 查看占用 8901 端口的进程
sudo lsof -i :8901
# 停止旧容器后释放端口
sudo docker stop ai-platform
快速部署脚本
将以下内容保存为 deploy.sh 即可一键重新打包部署:
#!/bin/bash
set -e
IMAGE_NAME="ai-platform:1.0.0"
CONTAINER_NAME="ai-platform"
PORT=8901
BACKEND_URL="${BACKEND_URL:-http://host.docker.internal:8000}"
echo ">>> 构建镜像..."
sudo docker build -t "$IMAGE_NAME" .
echo ">>> 停止旧容器..."
sudo docker stop "$CONTAINER_NAME" 2>/dev/null || true
sudo docker rm "$CONTAINER_NAME" 2>/dev/null || true
echo ">>> 启动新容器..."
sudo docker run -d \
--name "$CONTAINER_NAME" \
-p "$PORT:8901" \
--add-host=host.docker.internal:host-gateway \
-e BACKEND_URL="$BACKEND_URL" \
"$IMAGE_NAME"
echo ">>> 验证..."
sleep 2
sudo docker exec "$CONTAINER_NAME" curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8901/
echo ">>> 部署完成: http://localhost:$PORT"