Files
labweb/README.md
2025-12-05 20:27:09 +08:00

756 lines
19 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.
# Traefik 反向代理 + 多服务部署平台
基于 Traefik 的统一网关架构,支持多个 Web 应用和后端服务的集中管理和部署。
**域名**: `amiap.hzau.edu.cn`
**核心架构**: Traefik + Supabase + MinIO (内网) + Vue.js + WebSocket 服务
---
## 📊 系统架构总览
### 整体架构图
```
┌─────────────────────────────────────────────────────────┐
│ Internet (HTTPS) │
│ https://amiap.hzau.edu.cn │
└────────────────────┬────────────────────────────────────┘
┌──────────▼──────────┐
│ Traefik Gateway │ ← Let's Encrypt 自动证书
│ (反向代理+路由) │
└──────────┬──────────┘
┌────────────┼────────────┐
│ │ │
┌────▼───┐ ┌────▼────┐ ┌───▼────┐
│Supabase│ │Web Apps │ │Derper │
│ Stack │ │ (多项目)│ │ │
└────┬───┘ └─────────┘ └────────┘
┌────▼────┐
│ MinIO │ ← 内网存储
│ (内网) │
└─────────┘
```
### 核心设计原则
**MinIO 内网化**: 对象存储不暴露公网,仅通过 Tailscale VPN 访问
**统一网关**: 所有公网服务通过 Traefik 统一入口
**安全隔离**: 管理界面仅内网可访问
**自动证书**: Let's Encrypt 自动申请和续期 HTTPS 证书
---
## 🌐 URL 路由规划
### 公网访问 (HTTPS)
| 服务 | URL | 说明 | 状态 |
|------|-----|------|------|
| **主站** | `https://amiap.hzau.edu.cn/` | 自动跳转到 /group/ (302) | ✅ |
| **课题组网站** | `https://amiap.hzau.edu.cn/group/` | Vue.js 前端 | ✅ |
| **Supabase Storage** | `https://amiap.hzau.edu.cn/supa/storage/v1/` | 文件上传下载 API | ✅ |
| **Supabase API** | `https://amiap.hzau.edu.cn/supa/` | Auth/REST/Realtime | ✅ |
| **ABM 数据库** | `https://amiap.hzau.edu.cn/ABM/` | WebSocket 项目 | ✅ |
| **Derper** | `https://amiap.hzau.edu.cn/derp` | Tailscale DERP | ✅ |
### 内网访问 (Tailscale VPN)
| 服务 | URL | 说明 | 状态 |
|------|-----|------|------|
| **MinIO S3 API** | `http://100.64.0.2:9000` | 对象存储 API | ✅ |
| **MinIO Console** | `http://100.64.0.2:9001` | Web 管理界面 | ✅ |
| **Supabase Dashboard** | `http://100.64.0.2:18000` | 数据库管理 | ✅ |
### Supabase API 端点
```
https://amiap.hzau.edu.cn/supa/
├── auth/v1/ # 用户认证
├── rest/v1/ # 数据库 REST API
├── storage/v1/ # 文件存储
└── realtime/v1/ # 实时订阅
```
## 🚀 快速开始
### 1. 启动 Traefik 网关
```bash
cd /vol1/1000/docker_server/traefik
docker compose up -d
# 快速启动方式
cd supabase-stack
docker compose -f docker-compose.yml -f docker-compose.s3.yml up
```
### 2. 启动 Supabase 后端
```bash
cd supabase-stack
# 🔥 推荐:同时启动核心服务 + MinIO S3 对象存储
docker compose -f docker-compose.yml -f docker-compose.s3.yml up -d
# 查看所有服务状态
docker compose ps
# 测试 Storage API
python3 examples/test_https_storage.py
```
**详细文档**
- [supabase-stack/README_CN.md](supabase-stack/README_CN.md) - 中文完整指南
- [supabase-stack/README_STORAGE.md](supabase-stack/README_STORAGE.md) - Storage 使用指南
- [supabase-stack/docs/QUICK_START.md](supabase-stack/docs/QUICK_START.md) - 快速入门
### 3. 部署课题组网站
```bash
cd web/group-site
# 复制你的 Vue 构建文件到 dist/
cp -r /path/to/your-vue-project/dist ./
# 启动
docker compose up -d
```
**Vue 项目集成 Supabase**:详见 [VUE_API_INTEGRATION.md](supabase-stack/docs/VUE_API_INTEGRATION.md)
### 4. 部署 ABM 数据库
```bash
cd web/ws
# 启动服务Go 后端 + PostgreSQL
docker compose up -d
# 查看日志
docker compose logs -f
```
访问:`https://amiap.hzau.edu.cn/ABM`
---
## 📊 存储架构说明
### MinIO 内网化存储流程
**公网访问流程**:
```
用户(公网)
https://amiap.hzau.edu.cn/supa/storage/v1/
↓ Traefik → Kong
Supabase Storage Service
↓ 内部网络(不暴露公网)
MinIO (http://minio:9000)
物理存储: /vol1/1000/s3
```
**内网访问流程** (需要 Tailscale VPN):
```
管理员(通过 Tailscale VPN
http://100.64.0.2:9000 (MinIO S3 API)
http://100.64.0.2:9001 (MinIO Console)
物理存储: /vol1/1000/s3
```
### 关键特性
**安全隔离**: MinIO 不暴露到公网,仅通过内部网络访问
**统一入口**: 所有公网文件访问通过 Supabase Storage API
**权限控制**: 通过 Supabase RLS 实现细粒度权限管理
**内网管理**: 管理界面仅 Tailscale VPN 可访问
**根路径重定向**: 自动跳转到课题组网站
## 🔐 MinIO 访问
### 内网访问(需要 Tailscale VPN
**MinIO Console**:
- URL: `http://100.64.0.2:9001`
- 用户名: `bsxzZAJ3fvDquup`
- 密码: (见 `supabase-stack/.env`)
**MinIO S3 API**:
- URL: `http://100.64.0.2:9000`
- Access Key: 同上
- Secret Key: 同上
### 公网访问(通过 Supabase Storage API
```python
import requests
BASE_URL = 'https://amiap.hzau.edu.cn/supa'
API_KEY = 'your_anon_key' # 见 supabase-stack/.env
headers = {
'apikey': API_KEY,
'Authorization': f'Bearer {API_KEY}'
}
# 上传文件
with open('file.txt', 'rb') as f:
response = requests.post(
f'{BASE_URL}/storage/v1/object/bucket-name/file.txt',
headers={**headers, 'Content-Type': 'text/plain'},
data=f
)
# 下载文件
response = requests.get(
f'{BASE_URL}/storage/v1/object/bucket-name/file.txt',
headers=headers
)
```
---
## 📁 目录结构
```text
/vol1/1000/docker_server/traefik/
├── 📁 核心配置
│ ├── docker-compose.yml # Traefik 网关 + Derper
│ ├── .gitignore # Git 忽略规则
│ ├── README.md # 本文档(完整指南)
│ └── ARCHITECTURE_SUMMARY.md # 架构总览(已整合)
├── 📁 docs/ # 部署策略文档
│ ├── strategy-1-path-prefix.md # 路径前缀方案(当前使用)
│ ├── strategy-2-subdomain.md # 子域名方案
│ ├── strategy-3-hybrid.md # 混合方案
│ └── strategy-comparison-report.md # 策略对比分析
├── 📁 supabase-stack/ # 🔥 Supabase 后端服务
│ ├── docker-compose.yml # 核心服务PostgreSQL, Auth, REST, etc.)
│ ├── docker-compose.s3.yml # MinIO 对象存储(内网)
│ ├── .env # 环境变量和凭证
│ ├── README_CN.md # 中文使用指南
│ ├── README_STORAGE.md # Storage 对象存储指南
│ ├── MINIO_GUIDE.md # MinIO S3 完整使用指南
│ ├── docs/ # 详细文档
│ │ ├── QUICK_START.md # 快速入门
│ │ ├── OPERATIONS_GUIDE.md # 运维指南
│ │ ├── VUE_API_INTEGRATION.md # Vue 集成教程
│ │ └── FINAL_ARCHITECTURE_MINIO_INTERNAL.md # MinIO 内网化详细说明
│ └── examples/ # 示例代码
│ ├── storage_client.py # Python 客户端
│ ├── storage_client.js # JavaScript 客户端
│ └── test_https_storage.py # 测试脚本
└── 📁 web/ # Web 应用项目
├── redirect-root/ # 根路径重定向(到 /group/
├── group-site/ # 课题组网站Vue.js
├── ws/ # ABM 数据库项目
│ ├── docker-compose.yml # 项目配置
│ ├── backend/ # Go 后端
│ └── postgres_data/ # PostgreSQL 数据
├── gzy/ # GZY 项目(待部署)
└── zz/ # ZZ 项目(待部署)
```
---
## 🛠️ 常用命令
### 查看服务状态
```bash
# 查看所有相关容器
docker ps | grep -E "traefik|supabase|minio"
# Traefik + Derper
cd /vol1/1000/docker_server/traefik
docker compose ps
# Supabase 服务
cd supabase-stack
docker compose ps
# Web 应用
cd web/ws
docker compose ps
```
### 重启服务
```bash
# 重启 Traefik
cd /vol1/1000/docker_server/traefik
docker compose restart traefik
# 重启 Supabase 特定服务
cd supabase-stack
docker compose restart kong
docker compose restart storage
# 重启 Supabase + MinIO 全部服务
docker compose -f docker-compose.yml -f docker-compose.s3.yml restart
# 重启 Web 应用
cd web/ws
docker compose restart
```
### 停止服务
```bash
# 停止所有服务
docker compose down
# 停止并删除数据卷(慎用!)
docker compose down -v
```
### 更新服务
```bash
# 拉取最新镜像
docker compose pull
# 重新构建和启动
docker compose up -d --build
```
### 查看日志
```bash
# Traefik 日志
docker compose logs -f traefik
# Supabase 日志
cd supabase-stack
docker compose logs -f kong
docker compose logs -f storage
docker logs supabase-minio-1 --tail 50
# Web 应用日志
cd web/ws
docker compose logs -f
# 查看所有容器日志
docker compose logs -f --tail=100
```
### 测试 API
```bash
# 测试根路径重定向
curl -I https://amiap.hzau.edu.cn
# 测试 Supabase Storage
curl https://amiap.hzau.edu.cn/supa/storage/v1/bucket
# 测试 Supabase Auth
curl https://amiap.hzau.edu.cn/supa/auth/v1/health
# 测试 ABM 服务
curl https://amiap.hzau.edu.cn/ABM
# 测试 MinIO 内网访问(需要 Tailscale VPN
curl -I http://100.64.0.2:9001
# 运行 MinIO 完整功能测试
cd supabase-stack
python3 examples/test_https_storage.py
```
---
## 📚 详细文档
### Traefik 部署策略
| 文档 | 说明 |
|------|------|
| [strategy-1-path-prefix.md](docs/strategy-1-path-prefix.md) | 路径前缀方案(当前使用)|
| [strategy-2-subdomain.md](docs/strategy-2-subdomain.md) | 子域名方案 |
| [strategy-3-hybrid.md](docs/strategy-3-hybrid.md) | 混合方案 |
| [strategy-comparison-report.md](docs/strategy-comparison-report.md) | 策略对比分析 |
### Supabase 文档
| 文档 | 说明 |
|------|------|
| [supabase-stack/README_CN.md](supabase-stack/README_CN.md) | 🔥 完整使用指南(中文)|
| [supabase-stack/README_STORAGE.md](supabase-stack/README_STORAGE.md) | Storage 对象存储指南 |
| [supabase-stack/MINIO_GUIDE.md](supabase-stack/MINIO_GUIDE.md) | MinIO S3 完整使用指南 |
| [supabase-stack/docs/QUICK_START.md](supabase-stack/docs/QUICK_START.md) | 快速入门 |
| [supabase-stack/docs/OPERATIONS_GUIDE.md](supabase-stack/docs/OPERATIONS_GUIDE.md) | 运维指南 |
| [supabase-stack/docs/VUE_API_INTEGRATION.md](supabase-stack/docs/VUE_API_INTEGRATION.md) | Vue 集成教程 |
| [supabase-stack/docs/FINAL_ARCHITECTURE_MINIO_INTERNAL.md](supabase-stack/docs/FINAL_ARCHITECTURE_MINIO_INTERNAL.md) | MinIO 内网化详细说明 |
### 示例代码
| 文件 | 说明 |
|------|------|
| [supabase-stack/examples/storage_client.py](supabase-stack/examples/storage_client.py) | Python 完整客户端 |
| [supabase-stack/examples/storage_client.js](supabase-stack/examples/storage_client.js) | JavaScript 完整客户端 |
| [supabase-stack/examples/test_https_storage.py](supabase-stack/examples/test_https_storage.py) | 测试脚本 |
---
## 🔍 故障排查
### Traefik 无法启动
```bash
# 检查端口占用
sudo netstat -tlnp | grep ':80\|:443\|:8080'
# 查看 Traefik 日志
cd /vol1/1000/docker_server/traefik
docker compose logs traefik
# 查看证书状态
docker compose logs traefik | grep -i "certificate"
```
### Supabase 服务问题
```bash
cd supabase-stack
# 查看所有服务状态
docker compose ps
# 查看特定服务日志
docker compose logs -f kong
docker compose logs -f storage
docker compose logs -f db
# 重启服务
docker compose restart
```
**常见问题**
1. **supabase-pooler 一直重启** - 可以忽略,不影响功能(详见 [README_CN.md](supabase-stack/README_CN.md)
2. **Storage API 403 错误** - 检查 RLS 策略和 API 密钥
3. **数据库连接失败** - 检查 PostgreSQL 是否正常运行
### Supabase Storage API 404
```bash
# 检查 Kong 状态
docker ps | grep kong
docker logs supabase-kong --tail 50
# 确认 Kong 健康
docker inspect supabase-kong --format='{{.State.Health.Status}}'
# 检查 Storage 服务
docker compose logs -f storage
```
### MinIO 内网无法访问
```bash
# 确认 Tailscale 连接
tailscale status
ping 100.64.0.2
# 检查 MinIO 容器状态
docker ps | grep minio
docker logs supabase-minio-1 --tail 50
# 检查 MinIO 端口
docker port supabase-minio-1
```
### 根路径不跳转
```bash
# 检查 redirect-root 容器
docker ps | grep redirect-root
docker logs redirect-root --tail 20
# 测试重定向
curl -I https://amiap.hzau.edu.cn
```
### Web 应用问题
```bash
cd web/ws
# 查看容器状态
docker compose ps
# 查看日志
docker compose logs -f
# 进入容器调试
docker compose exec webws /bin/sh
```
### SSL 证书问题
```bash
# 查看证书状态
cd /vol1/1000/docker_server/traefik
docker compose logs traefik | grep -i "certificate"
# 删除旧证书重新申请(慎用!)
docker volume rm traefik_acme-data
docker compose up -d
```
---
## ⚙️ 配置说明
### Traefik 配置
**docker-compose.yml** 关键配置:
```yaml
services:
traefik:
image: traefik:v3.0
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.email=lyzeng@hzau.edu.cn"
ports:
- "80:80"
- "443:443"
- "8080:8080" # Dashboard
```
**访问 Traefik Dashboard**`http://服务器IP:8080`
### Supabase 配置
主要配置文件:
- `.env` - 环境变量(密钥、数据库配置等)
- `docker-compose.yml` - 核心服务
- `docker-compose.s3.yml` - MinIO 对象存储
**关键环境变量**
```bash
# API 密钥
ANON_KEY=eyJhbGc... # 前端使用
SERVICE_ROLE_KEY=eyJ... # 后端使用
# 数据库
POSTGRES_PASSWORD=your-password
# MinIO 对象存储
MINIO_ROOT_USER=bsxzZAJ3fvDquup
MINIO_ROOT_PASSWORD=your-minio-password
# 内网访问
MinIO S3 API: http://100.64.0.2:9000
MinIO Console: http://100.64.0.2:9001
```
### Web 应用配置
每个项目独立配置示例web/ws
```yaml
services:
webws:
labels:
- "traefik.enable=true"
- "traefik.http.routers.webws.rule=Host(`amiap.hzau.edu.cn`) && PathPrefix(`/ABM`)"
- "traefik.http.routers.webws.entrypoints=websecure"
- "traefik.http.routers.webws.tls.certresolver=myresolver"
```
---
## 📝 开发指南
### 添加新的 Web 应用
1.`web/` 下创建项目目录
2. 创建 `docker-compose.yml`
3. 配置 Traefik 标签
示例:
```yaml
services:
myapp:
image: myapp:latest
networks:
- frontend
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`amiap.hzau.edu.cn`) && PathPrefix(`/myapp`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls.certresolver=myresolver"
- "traefik.http.middlewares.myapp-stripprefix.stripprefix.prefixes=/myapp"
- "traefik.http.routers.myapp.middlewares=myapp-stripprefix"
networks:
frontend:
external: true
```
### 前端开发集成 Supabase
**Vue 项目集成**
```javascript
// src/lib/supabaseClient.js
import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
'https://amiap.hzau.edu.cn/supa',
'your-anon-key'
)
```
详细教程:[VUE_API_INTEGRATION.md](supabase-stack/docs/VUE_API_INTEGRATION.md)
### Storage API 使用
**Python**:
```python
from examples.storage_client import SupabaseStorageClient
client = SupabaseStorageClient(
'https://amiap.hzau.edu.cn/supa',
'your-service-role-key'
)
# 上传文件
client.upload_file('bucket', 'photo.jpg', 'uploads/photo.jpg')
# 生成临时下载链接
url = client.create_signed_url('bucket', 'uploads/photo.jpg', 3600)
```
**JavaScript**:
```javascript
const client = new SupabaseStorageClient(
'https://amiap.hzau.edu.cn/supa',
'your-service-role-key'
);
// 上传文件
await client.uploadFile('bucket', fileObject, 'uploads/photo.jpg');
// 生成临时下载链接
const url = await client.createSignedUrl('bucket', 'uploads/photo.jpg', 3600);
```
---
## 🎯 最佳实践
### 部署流程
1. **开发环境** → 本地测试
2. **测试环境** → 内网测试
3. **生产环境** → 公网部署
### 备份策略
```bash
# 备份 Supabase 数据库
cd supabase-stack
docker exec supabase-db pg_dump -U postgres postgres > backup_$(date +%Y%m%d).sql
# 备份 MinIO 数据
tar -czf minio_backup_$(date +%Y%m%d).tar.gz /vol1/1000/s3/
# 备份配置文件
tar -czf config_backup_$(date +%Y%m%d).tar.gz .env docker-compose*.yml
```
### 监控和日志
```bash
# 实时监控资源使用
docker stats
# 查看所有容器日志
docker compose logs -f --tail=100
# 日志持久化(可选)
mkdir -p /var/log/docker
docker compose logs > /var/log/docker/traefik_$(date +%Y%m%d).log
```
### 性能优化
1. **数据库连接池** - Supabase pooler可选
2. **CDN 加速** - 静态资源使用 CDN
3. **缓存策略** - Traefik 支持缓存中间件
4. **负载均衡** - 多实例部署
---
## 🔒 安全配置
### SSL/TLS 证书
- 使用 Let's Encrypt 自动申请和续期
- 证书存储在 `acme-data` Docker volume 中
- 自动 HTTP 到 HTTPS 重定向
### 访问控制
- ✅ MinIO 不暴露到公网,仅内网访问
- ✅ Supabase Dashboard 仅内网访问(`http://100.64.0.2:18000`
- ✅ Traefik Dashboard 端口 8080建议配置认证
- ✅ 生产环境建议配置防火墙规则
### API 密钥管理
- `ANON_KEY` - 前端使用,权限受 RLS 限制
- `SERVICE_ROLE_KEY` - 后端使用,完全权限,需严格保密
- 所有公网服务使用 HTTPS + Let's Encrypt 证书
- 公网文件访问通过 Supabase API支持权限控制
---
## 📞 技术支持
### 相关链接
- [Traefik 官方文档](https://doc.traefik.io/traefik/)
- [Supabase 官方文档](https://supabase.com/docs)
- [Docker Compose 文档](https://docs.docker.com/compose/)
- [MinIO 文档](https://min.io/docs/)
### 项目信息
- **域名**: amiap.hzau.edu.cn
- **服务器**: HZAU Lab Server
- **部署日期**: 2025-11-22
- **维护团队**: Lab Admin
---
**快速导航**
- [Supabase 中文指南](supabase-stack/README_CN.md)
- [Storage 使用指南](supabase-stack/README_STORAGE.md)
- [MinIO S3 指南](supabase-stack/MINIO_GUIDE.md)
- [部署策略文档](docs/)
---
**版本**: v3.0 (MinIO 内网化)
**更新日期**: 2025-11-23
**状态**: ✅ 生产就绪
🎉 **开始使用 Traefik + Supabase 部署平台!**