# MaaS 底座前端 Docker 生产部署文档

## 一、项目概述

本项目为 MaaS（Model as a Service）底座前端，基于 UmiJS + React + Ant Design 构建。采用 Docker 多阶段构建，最终产物通过 Nginx 提供静态资源服务，并代理部分请求至后端 GPUStack 服务。

### 技术栈

| 组件     | 版本                     |
| -------- | ------------------------ |
| Node.js  | 18 (Alpine)              |
| pnpm     | 9.3.0                    |
| Nginx    | Alpine (最新稳定版)      |
| 后端服务 | gpustack/gpustack:latest |

### 架构说明

```
用户请求 → Nginx (80端口)
              ├── 静态资源 → /usr/share/nginx/html (前端构建产物)
              └── API代理  → gpustack 后端 (:80)
                   代理路径: /v1, /v2, /auth, /version, /proxy, /update, /cli, /grafana
```

---

## 二、环境要求

- Docker >= 20.10
- Docker Compose >= 2.0
- 服务器内存 >= 4GB（构建阶段）
- 磁盘空间 >= 5GB（含镜像和构建缓存）

---

## 三、部署步骤

### 3.1 拉取代码

```bash
git clone <repository-url> maas-base-ui
cd maas-base-ui
```

### 3.2 配置环境变量

复制 `.env` 文件并根据实际情况修改：

```bash
cp .env .env.prod
```

| 变量名 | 说明 | 默认值 |
| --- | --- | --- |
| `APP_TITLE` | 前端应用标题 | `成都网讯MaaS底座` |
| `ENABLE_PLAYGROUND` | 是否显示试验场菜单 (`true`/`false`) | `false` |
| `UI_PORT` | Nginx 对外暴露端口 | `8080` |

### 3.3 构建并启动

```bash
docker compose --env-file .env.prod up -d --build
```

该命令会依次执行：

1. **builder 阶段**：在 `node:18-alpine` 中安装依赖并执行 `pnpm build`
2. **nginx 阶段**：将构建产物复制到 Nginx 容器，注入自定义配置
3. 启动 `maas-ui` 和 `backend` 两个服务

### 3.4 验证部署

```bash
# 查看容器状态
docker compose ps

# 查看前端服务日志
docker compose logs -f maas-ui

# 查看后端服务日志
docker compose logs -f backend

# 测试访问
curl -I http://localhost:8080
```

预期返回 `200 OK`。

---

## 四、生产环境配置建议

### 4.1 Nginx 生产配置

当前 `nginx.conf` 为基础配置，生产环境建议补充以下内容：

```nginx
server {
    listen 80;
    server_name your-domain.com;  # 替换为实际域名

    # 安全头
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_min_length 1000;

    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    # 后端代理
    location ~ ^/(v1|v2|auth|version|proxy|update|cli|grafana) {
        proxy_pass http://backend:80;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}
```

### 4.2 HTTPS 配置

推荐使用 Nginx Proxy Manager 或手动配置证书：

```bash
# 将证书文件放置到指定目录
mkdir -p certs
# 放入 your-domain.crt 和 your-domain.key

# 修改 nginx.conf 监听 443
```

或通过 `docker-compose.yml` 挂载 Traefik / Caddy 等反向代理处理 HTTPS。

### 4.3 数据持久化

后端 GPUStack 数据已通过 Docker Volume `gpustack-data` 持久化。生产环境建议：

```bash
# 查看数据卷位置
docker volume inspect maas-base-ui_gpustack-data

# 可选：将 volume 替换为宿主机目录挂载
# volumes:
#   - /data/gpustack:/var/lib/gpustack
```

---

## 五、常用运维操作

### 5.1 更新镜像

```bash
# 拉取最新代码
git pull

# 重新构建并启动
docker compose --env-file .env.prod up -d --build

# 清理无用镜像
docker image prune -f
```

### 5.2 扩缩容

修改 `.env.prod` 中的 `UI_PORT` 可更改对外端口：

```bash
UI_PORT=9090
docker compose --env-file .env.prod up -d
```

### 5.3 日志管理

```bash
# 实时日志
docker compose logs -f --tail=100 maas-ui

# 导出日志
docker compose logs --no-color maas-ui > maas-ui.log

# 限制 Docker 日志大小（建议配置 /etc/docker/daemon.json）
# {
#   "log-driver": "json-file",
#   "log-opts": {
#     "max-size": "50m",
#     "max-file": "3"
#   }
# }
```

### 5.4 停止与清理

```bash
# 停止服务
docker compose down

# 停止并删除数据卷（⚠️ 会清除后端数据）
docker compose down -v

# 完整清理
docker compose down -v --rmi all --remove-orphans
```

---

## 六、故障排查

### 6.1 构建失败

```bash
# 检查 pnpm-lock.yaml 是否存在
ls -la pnpm-lock.yaml

# 清理 Docker 构建缓存
docker builder prune -a

# 增加 Docker 内存限制（macOS/Windows Docker Desktop）
# 设置 -> Resources -> Memory >= 4GB
```

### 6.2 容器启动后无法访问

```bash
# 检查端口占用
netstat -tlnp | grep 8080

# 检查容器网络
docker compose exec maas-ui curl -I http://backend:80

# 检查防火墙
# Ubuntu/Debian
sudo ufw allow 8080/tcp
# CentOS/RHEL
sudo firewall-cmd --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
```

### 6.3 后端连接失败

确认 `nginx.conf` 中的 `proxy_pass http://backend:80` 与 `docker-compose.yml` 中 `backend` 服务名一致。Docker Compose 自动通过内部 DNS 解析服务名。

---

## 七、附录

### 7.1 文件清单

| 文件                 | 用途                                  |
| -------------------- | ------------------------------------- |
| `Dockerfile`         | 多阶段构建：Node.js 构建 + Nginx 运行 |
| `docker-compose.yml` | 编排前端 + 后端 GPUStack 服务         |
| `nginx.conf`         | Nginx 路由配置（静态资源 + API 代理） |
| `.env`               | 环境变量配置                          |

### 7.2 端口说明

| 端口                  | 服务    | 说明                  |
| --------------------- | ------- | --------------------- |
| `UI_PORT` (默认 8080) | maas-ui | 前端 Nginx 对外端口   |
| `80`                  | backend | GPUStack Web 服务     |
| `30080`               | backend | GPUStack 备用端口     |
| `10161`               | backend | GPUStack 内部通信端口 |
