558 lines
12 KiB
Markdown
558 lines
12 KiB
Markdown
# 低預算部署指南
|
||
|
||
## 概述
|
||
為Drama Ling應用設計的超低預算部署方案,滿足開發階段NT$2,000/月、生產階段NT$5,000/月的預算限制。
|
||
|
||
## 部署策略總覽
|
||
|
||
### 成本控制原則
|
||
- **開發階段**: 完全本地化開發,最小化雲端服務使用
|
||
- **生產階段**: VPS單機部署,優化AI服務用量
|
||
- **擴展準備**: 架構設計考慮未來遷移至雲端服務的可能性
|
||
|
||
## 開發階段部署 (NT$ 2,000/月預算)
|
||
|
||
### 本地開發環境設置
|
||
|
||
#### Docker Compose配置
|
||
```yaml
|
||
# docker-compose.dev.yml
|
||
version: '3.8'
|
||
|
||
services:
|
||
# 後端API服務
|
||
api:
|
||
build:
|
||
context: ./backend
|
||
dockerfile: Dockerfile.dev
|
||
ports:
|
||
- "3001:3001"
|
||
environment:
|
||
- NODE_ENV=development
|
||
- DATABASE_URL=postgresql://dev:dev123@postgres:5432/dramaling_dev
|
||
- REDIS_URL=redis://redis:6379
|
||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||
volumes:
|
||
- ./backend:/app
|
||
- /app/node_modules
|
||
depends_on:
|
||
- postgres
|
||
- redis
|
||
|
||
# PostgreSQL資料庫
|
||
postgres:
|
||
image: postgres:15-alpine
|
||
environment:
|
||
POSTGRES_DB: dramaling_dev
|
||
POSTGRES_USER: dev
|
||
POSTGRES_PASSWORD: dev123
|
||
ports:
|
||
- "5432:5432"
|
||
volumes:
|
||
- postgres_data:/var/lib/postgresql/data
|
||
- ./database/init:/docker-entrypoint-initdb.d
|
||
|
||
# Redis快取
|
||
redis:
|
||
image: redis:7-alpine
|
||
ports:
|
||
- "6379:6379"
|
||
command: redis-server --appendonly yes
|
||
volumes:
|
||
- redis_data:/data
|
||
|
||
# 前端開發服務器
|
||
web:
|
||
build:
|
||
context: ./frontend
|
||
dockerfile: Dockerfile.dev
|
||
ports:
|
||
- "3000:3000"
|
||
volumes:
|
||
- ./frontend:/app
|
||
- /app/node_modules
|
||
environment:
|
||
- REACT_APP_API_URL=http://localhost:3001
|
||
|
||
volumes:
|
||
postgres_data:
|
||
redis_data:
|
||
```
|
||
|
||
#### 開發成本明細
|
||
```yaml
|
||
development_costs:
|
||
infrastructure:
|
||
local_docker: "免費"
|
||
domain_testing: "免費 (ngrok或localhost)"
|
||
|
||
services:
|
||
openai_api: "NT$ 300-600/月"
|
||
# 基於低用量GPT-4o-mini,約1000-2000次API呼叫
|
||
database: "免費 (本地PostgreSQL)"
|
||
storage: "免費 (本地檔案系統)"
|
||
|
||
tools:
|
||
monitoring: "免費 (Docker logs)"
|
||
version_control: "免費 (GitHub)"
|
||
|
||
total: "NT$ 300-600/月"
|
||
remaining_budget: "NT$ 1,400-1,700/月"
|
||
```
|
||
|
||
### 開發工作流程
|
||
|
||
#### 1. 環境啟動
|
||
```bash
|
||
# 啟動開發環境
|
||
docker-compose -f docker-compose.dev.yml up -d
|
||
|
||
# 檢查服務狀態
|
||
docker-compose -f docker-compose.dev.yml ps
|
||
|
||
# 查看日誌
|
||
docker-compose -f docker-compose.dev.yml logs -f api
|
||
```
|
||
|
||
#### 2. 資料庫遷移
|
||
```bash
|
||
# 執行資料庫遷移
|
||
docker-compose -f docker-compose.dev.yml exec api npm run migrate
|
||
|
||
# 填充測試資料
|
||
docker-compose -f docker-compose.dev.yml exec api npm run seed
|
||
```
|
||
|
||
#### 3. AI服務成本控制
|
||
```javascript
|
||
// AI服務配置
|
||
const aiConfig = {
|
||
provider: 'openai',
|
||
model: 'gpt-4o-mini', // 比GPT-4便宜10倍
|
||
maxTokens: 500, // 限制回應長度
|
||
cache: {
|
||
enabled: true,
|
||
ttl: 3600, // 1小時快取
|
||
hitRateTarget: 0.9 // 目標90%命中率
|
||
},
|
||
rateLimiting: {
|
||
requestsPerMinute: 10,
|
||
tokensPerMinute: 5000
|
||
}
|
||
}
|
||
```
|
||
|
||
## 生產階段部署 (NT$ 5,000/月預算)
|
||
|
||
### VPS服務商選擇
|
||
|
||
#### 推薦VPS配置
|
||
```yaml
|
||
recommended_vps:
|
||
provider_options:
|
||
- name: "DigitalOcean"
|
||
specs: "4GB RAM, 2 vCPU, 80GB SSD"
|
||
monthly_cost: "NT$ 320 ($10 USD)"
|
||
location: "Singapore"
|
||
|
||
- name: "Vultr"
|
||
specs: "4GB RAM, 2 vCPU, 80GB SSD"
|
||
monthly_cost: "NT$ 384 ($12 USD)"
|
||
location: "Tokyo"
|
||
|
||
- name: "Linode"
|
||
specs: "4GB RAM, 2 vCPU, 80GB SSD"
|
||
monthly_cost: "NT$ 320 ($10 USD)"
|
||
location: "Tokyo"
|
||
|
||
selection_criteria:
|
||
- 亞洲機房降低延遲
|
||
- 穩定的網路連線
|
||
- 良好的技術支援
|
||
- 彈性的計費方式
|
||
```
|
||
|
||
### 生產環境配置
|
||
|
||
#### Docker Compose生產配置
|
||
```yaml
|
||
# docker-compose.prod.yml
|
||
version: '3.8'
|
||
|
||
services:
|
||
# Nginx反向代理
|
||
nginx:
|
||
image: nginx:alpine
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
volumes:
|
||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
||
- ./nginx/ssl:/etc/nginx/ssl
|
||
- ./frontend/build:/usr/share/nginx/html
|
||
depends_on:
|
||
- api
|
||
restart: unless-stopped
|
||
|
||
# 後端API服務
|
||
api:
|
||
build:
|
||
context: ./backend
|
||
dockerfile: Dockerfile.prod
|
||
environment:
|
||
- NODE_ENV=production
|
||
- DATABASE_URL=${DATABASE_URL}
|
||
- REDIS_URL=${REDIS_URL}
|
||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||
- JWT_SECRET=${JWT_SECRET}
|
||
depends_on:
|
||
- postgres
|
||
- redis
|
||
restart: unless-stopped
|
||
|
||
# PostgreSQL資料庫
|
||
postgres:
|
||
image: postgres:15-alpine
|
||
environment:
|
||
POSTGRES_DB: ${POSTGRES_DB}
|
||
POSTGRES_USER: ${POSTGRES_USER}
|
||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||
volumes:
|
||
- postgres_data:/var/lib/postgresql/data
|
||
- ./database/init:/docker-entrypoint-initdb.d
|
||
restart: unless-stopped
|
||
|
||
# Redis快取
|
||
redis:
|
||
image: redis:7-alpine
|
||
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
|
||
volumes:
|
||
- redis_data:/data
|
||
restart: unless-stopped
|
||
|
||
# 監控服務
|
||
prometheus:
|
||
image: prom/prometheus:latest
|
||
ports:
|
||
- "9090:9090"
|
||
volumes:
|
||
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
|
||
restart: unless-stopped
|
||
|
||
grafana:
|
||
image: grafana/grafana:latest
|
||
ports:
|
||
- "3001:3000"
|
||
environment:
|
||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
|
||
volumes:
|
||
- grafana_data:/var/lib/grafana
|
||
restart: unless-stopped
|
||
|
||
volumes:
|
||
postgres_data:
|
||
redis_data:
|
||
grafana_data:
|
||
```
|
||
|
||
#### Nginx配置
|
||
```nginx
|
||
# nginx/nginx.conf
|
||
events {
|
||
worker_connections 1024;
|
||
}
|
||
|
||
http {
|
||
upstream api {
|
||
server api:3001;
|
||
}
|
||
|
||
# 啟用gzip壓縮
|
||
gzip on;
|
||
gzip_vary on;
|
||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
|
||
|
||
# SSL配置
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name your-domain.com;
|
||
|
||
ssl_certificate /etc/nginx/ssl/cert.pem;
|
||
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
||
|
||
# 前端靜態檔案
|
||
location / {
|
||
root /usr/share/nginx/html;
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
# API代理
|
||
location /api/ {
|
||
proxy_pass http://api;
|
||
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;
|
||
}
|
||
}
|
||
|
||
# HTTP重定向至HTTPS
|
||
server {
|
||
listen 80;
|
||
server_name your-domain.com;
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 生產成本明細
|
||
|
||
```yaml
|
||
production_costs:
|
||
infrastructure:
|
||
vps_server: "NT$ 320-480/月" # 4GB VPS
|
||
domain_ssl: "NT$ 400-600/月" # 域名 + Cloudflare Pro
|
||
backup_storage: "NT$ 160-240/月" # 備份儲存
|
||
|
||
services:
|
||
openai_api: "NT$ 1,500-3,000/月" # 優化使用GPT-4o-mini
|
||
payment_stripe: "3% 交易手續費"
|
||
monitoring: "NT$ 0-480/月" # 基本免費或便宜方案
|
||
|
||
total_fixed: "NT$ 2,380-4,800/月"
|
||
remaining_budget: "NT$ 200-2,620/月"
|
||
```
|
||
|
||
### AI服務成本優化策略
|
||
|
||
#### 1. 快取策略
|
||
```javascript
|
||
// 多層快取系統
|
||
const cacheStrategy = {
|
||
// L1: 記憶體快取 (最快)
|
||
memory: {
|
||
provider: 'node-cache',
|
||
ttl: 300, // 5分鐘
|
||
checkperiod: 60
|
||
},
|
||
|
||
// L2: Redis快取 (跨實例)
|
||
redis: {
|
||
provider: 'redis',
|
||
ttl: 3600, // 1小時
|
||
keyPrefix: 'ai_cache:'
|
||
},
|
||
|
||
// L3: 資料庫快取 (持久化)
|
||
database: {
|
||
table: 'ai_responses',
|
||
ttl: 86400 * 7 // 7天
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. 批次處理
|
||
```javascript
|
||
// 批次AI請求降低成本
|
||
const batchProcessor = {
|
||
queueSize: 10, // 累積10個請求
|
||
timeout: 5000, // 或等待5秒
|
||
|
||
async processBatch(requests) {
|
||
// 合併類似請求
|
||
const grouped = groupSimilarRequests(requests);
|
||
|
||
// 批次發送
|
||
const results = await Promise.all(
|
||
grouped.map(group => this.sendBatchRequest(group))
|
||
);
|
||
|
||
return results.flat();
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3. 智慧降級
|
||
```javascript
|
||
// 根據複雜度選擇模型
|
||
const modelSelector = {
|
||
simple: 'gpt-4o-mini', // 簡單任務
|
||
complex: 'gpt-4o', // 複雜任務(限量)
|
||
|
||
selectModel(task) {
|
||
const complexity = this.analyzeComplexity(task);
|
||
return complexity < 0.5 ? this.simple : this.complex;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 部署自動化
|
||
|
||
### 部署腳本
|
||
```bash
|
||
#!/bin/bash
|
||
# deploy.sh
|
||
|
||
set -e
|
||
|
||
echo "🚀 開始部署 Drama Ling 生產環境..."
|
||
|
||
# 1. 拉取最新代碼
|
||
git pull origin main
|
||
|
||
# 2. 構建前端
|
||
echo "📦 構建前端應用..."
|
||
cd frontend
|
||
npm run build
|
||
cd ..
|
||
|
||
# 3. 停止現有服務
|
||
echo "⏹️ 停止現有服務..."
|
||
docker-compose -f docker-compose.prod.yml down
|
||
|
||
# 4. 備份資料庫
|
||
echo "💾 備份資料庫..."
|
||
./scripts/backup-database.sh
|
||
|
||
# 5. 啟動新服務
|
||
echo "▶️ 啟動新服務..."
|
||
docker-compose -f docker-compose.prod.yml up -d
|
||
|
||
# 6. 健康檢查
|
||
echo "🏥 執行健康檢查..."
|
||
./scripts/health-check.sh
|
||
|
||
# 7. 清理舊映像
|
||
echo "🧹 清理舊Docker映像..."
|
||
docker image prune -f
|
||
|
||
echo "✅ 部署完成!"
|
||
```
|
||
|
||
### 健康檢查腳本
|
||
```bash
|
||
#!/bin/bash
|
||
# scripts/health-check.sh
|
||
|
||
echo "檢查服務健康狀態..."
|
||
|
||
# 檢查API服務
|
||
if curl -f http://localhost/api/health; then
|
||
echo "✅ API服務正常"
|
||
else
|
||
echo "❌ API服務異常"
|
||
exit 1
|
||
fi
|
||
|
||
# 檢查資料庫連線
|
||
if docker-compose -f docker-compose.prod.yml exec -T postgres pg_isready; then
|
||
echo "✅ 資料庫連線正常"
|
||
else
|
||
echo "❌ 資料庫連線異常"
|
||
exit 1
|
||
fi
|
||
|
||
# 檢查Redis服務
|
||
if docker-compose -f docker-compose.prod.yml exec -T redis redis-cli ping; then
|
||
echo "✅ Redis服務正常"
|
||
else
|
||
echo "❌ Redis服務異常"
|
||
exit 1
|
||
fi
|
||
|
||
echo "🎉 所有服務健康檢查通過!"
|
||
```
|
||
|
||
## 監控與維護
|
||
|
||
### 免費監控方案
|
||
```yaml
|
||
monitoring_stack:
|
||
uptime_monitoring:
|
||
provider: "UptimeRobot"
|
||
cost: "免費"
|
||
features:
|
||
- 5分鐘間隔檢查
|
||
- 50個監控點
|
||
- email/SMS通知
|
||
|
||
error_tracking:
|
||
provider: "Sentry"
|
||
cost: "免費 (5000 errors/月)"
|
||
features:
|
||
- 錯誤追蹤
|
||
- 性能監控
|
||
- 釋出追蹤
|
||
|
||
log_analysis:
|
||
provider: "Docker logs + Grafana"
|
||
cost: "免費"
|
||
features:
|
||
- 集中化日誌
|
||
- 基本儀表板
|
||
- 警報通知
|
||
```
|
||
|
||
### 備份策略
|
||
```bash
|
||
#!/bin/bash
|
||
# scripts/backup-database.sh
|
||
|
||
BACKUP_DIR="/var/backups/dramaling"
|
||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||
BACKUP_FILE="dramaling_backup_${TIMESTAMP}.sql"
|
||
|
||
# 創建備份目錄
|
||
mkdir -p $BACKUP_DIR
|
||
|
||
# 執行資料庫備份
|
||
docker-compose -f docker-compose.prod.yml exec -T postgres \
|
||
pg_dump -U $POSTGRES_USER $POSTGRES_DB > "$BACKUP_DIR/$BACKUP_FILE"
|
||
|
||
# 壓縮備份檔案
|
||
gzip "$BACKUP_DIR/$BACKUP_FILE"
|
||
|
||
# 保留最近7天的備份
|
||
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
|
||
|
||
# 上傳至雲端存儲(可選)
|
||
# aws s3 cp "$BACKUP_DIR/${BACKUP_FILE}.gz" s3://your-backup-bucket/
|
||
|
||
echo "✅ 資料庫備份完成: ${BACKUP_FILE}.gz"
|
||
```
|
||
|
||
## 擴展計劃
|
||
|
||
### 當預算增加時的升級路徑
|
||
|
||
#### 第一階段:服務優化 (NT$ 10,000/月)
|
||
- 升級至更大規格VPS
|
||
- 啟用專業版監控工具
|
||
- 增加AI API使用量
|
||
|
||
#### 第二階段:高可用性 (NT$ 20,000/月)
|
||
- 多VPS負載均衡
|
||
- 資料庫主從複製
|
||
- CDN服務啟用
|
||
|
||
#### 第三階段:雲端遷移 (NT$ 50,000/月)
|
||
- 遷移至AWS/GCP
|
||
- 容器編排 (Kubernetes)
|
||
- 微服務架構改造
|
||
|
||
## 總結
|
||
|
||
這個低預算部署方案能夠:
|
||
|
||
✅ **滿足預算限制**: 開發階段NT$300-600/月,生產階段NT$2,380-4,800/月
|
||
✅ **保持功能完整**: 支援所有核心功能,包括AI服務
|
||
✅ **確保可擴展性**: 架構設計考慮未來升級需求
|
||
✅ **維護便利性**: 自動化部署和監控
|
||
✅ **風險可控**: 多層備份和健康檢查
|
||
|
||
---
|
||
|
||
**文件版本**: v1.0
|
||
**最後更新**: 2024年9月7日
|
||
**適用場景**: 預算受限的初期部署階段
|
||
**下次檢討**: 生產環境運行3個月後評估升級需求 |