CHECKOK
This commit is contained in:
397
DEPLOYMENT.md
397
DEPLOYMENT.md
@@ -1,141 +1,98 @@
|
|||||||
# PANJIT 文件翻譯系統 - 部署手冊
|
# PANJIT 文件翻譯系統 - 部署指南
|
||||||
|
|
||||||
## 部署概述
|
本指南說明如何在公司內部以 Docker 方式部署系統至生產環境,並提供日常維運要點。
|
||||||
|
|
||||||
本系統已完成生產環境準備,包含完整的 Docker 配置和環境設定。系統使用 12010 端口,符合公司端口規範 (12010-12019)。
|
## 生產最佳化更新(重要)
|
||||||
|
- 後端以 Gunicorn + eventlet 啟動(WSGI 入口:`wsgi:app`),提升併發與穩定性。
|
||||||
|
- Socket.IO 啟用 Redis message queue(`REDIS_URL`),支援多進程/多副本一致廣播。
|
||||||
|
- Celery worker 預設併發提高至 8,可依 CPU 與佇列長度再水平擴展。
|
||||||
|
- Redis 僅供容器內部使用,Compose 預設不再對外暴露 6379。
|
||||||
|
- 新增套件內根路由提供 SPA 與 `/api`、`/api/health`(`/api/v1/health` 仍由健康檢查藍圖提供)。
|
||||||
|
|
||||||
## 系統架構
|
## 系統架構
|
||||||
|
|
||||||
```
|
- 前端:Vue(Vite 打包後為靜態檔,容器內由後端服務)
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
- 後端:Flask + Flask-SocketIO(eventlet)+ SQLAlchemy + JWT
|
||||||
│ Frontend │ │ Backend │ │ Celery │
|
- 佇列:Celery(Redis broker/result)
|
||||||
│ (Vue.js) │ │ (Flask) │ │ (Worker) │
|
- 資料庫:MySQL(透過 SQLAlchemy 連線池)
|
||||||
│ Port: 12010 │────│ Port: 12010 │────│ 獨立容器 │
|
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
│ │ │
|
|
||||||
└───────────────────────┼───────────────────────┘
|
|
||||||
│
|
|
||||||
┌─────────────────┐
|
|
||||||
│ Redis │
|
|
||||||
│ (Queue/Cache) │
|
|
||||||
│ Port: 6379 │
|
|
||||||
└─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
**架構優化說明:**
|
## 需求與準備
|
||||||
- Flask 應用專注於 Web 服務,不再內建 Celery Worker
|
|
||||||
- Celery Worker 運行在獨立容器中,提供更好的資源管理
|
- Docker 20.10+、Docker Compose 1.28+
|
||||||
- 消除了重複的 worker 實例,避免任務重複執行風險
|
- 4GB 以上可用記憶體、20GB 以上可用磁碟空間
|
||||||
- 心跳同步更加穩定,減少集群管理開銷
|
- 內部網路可存取 MySQL、LDAP、SMTP、Dify API
|
||||||
|
|
||||||
## 快速部署
|
## 快速部署
|
||||||
|
|
||||||
### 前置需求
|
|
||||||
- Docker 20.10+
|
|
||||||
- Docker Compose 1.28+
|
|
||||||
- 至少 4GB 可用記憶體
|
|
||||||
- 至少 20GB 可用磁碟空間
|
|
||||||
|
|
||||||
### 一鍵部署
|
|
||||||
```bash
|
```bash
|
||||||
# 1. 進入專案目錄
|
# 1) 進入專案目錄
|
||||||
cd Document_translator_V2
|
cd Document_translator_V2
|
||||||
|
|
||||||
# 2. 建置並啟動所有服務
|
# 2) 建置並啟動(首次執行會自動 build)
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
# 3. 檢查服務狀態
|
# 3) 檢查服務狀態
|
||||||
docker-compose ps
|
docker-compose ps
|
||||||
|
|
||||||
# 4. 查看日誌
|
# 4) 追蹤應用日誌
|
||||||
docker-compose logs -f app
|
docker-compose logs -f app
|
||||||
```
|
```
|
||||||
|
|
||||||
### 驗證部署
|
驗證健康與前端:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 檢查主應用健康狀態
|
|
||||||
curl http://localhost:12010/api/v1/health
|
curl http://localhost:12010/api/v1/health
|
||||||
|
|
||||||
# 檢查前端訪問
|
|
||||||
curl http://localhost:12010/
|
curl http://localhost:12010/
|
||||||
|
```
|
||||||
|
|
||||||
# 檢查 Celery Worker 狀態
|
檢查 Celery worker:
|
||||||
|
|
||||||
|
```bash
|
||||||
docker-compose exec celery-worker celery -A celery_app inspect active
|
docker-compose exec celery-worker celery -A celery_app inspect active
|
||||||
```
|
```
|
||||||
|
|
||||||
## 詳細部署步驟
|
## 詳細部署步驟
|
||||||
|
|
||||||
### 1. 環境準備
|
### 1) 主機檢查
|
||||||
|
|
||||||
**檢查系統資源**
|
|
||||||
```bash
|
```bash
|
||||||
# 檢查記憶體
|
# 記憶體 / 磁碟 / 埠使用
|
||||||
free -h
|
free -h
|
||||||
|
|
||||||
# 檢查磁碟空間
|
|
||||||
df -h
|
df -h
|
||||||
|
netstat -tulpn | grep 12010 || ss -lntp | grep 12010
|
||||||
|
|
||||||
# 檢查端口占用
|
# Docker 狀態
|
||||||
netstat -tulpn | grep 12010
|
|
||||||
```
|
|
||||||
|
|
||||||
**檢查 Docker 環境**
|
|
||||||
```bash
|
|
||||||
docker --version
|
docker --version
|
||||||
docker-compose --version
|
docker-compose --version
|
||||||
docker system info
|
docker system info
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. 配置文件檢查
|
### 2) 建置映像
|
||||||
|
|
||||||
系統已包含完整的生產環境配置:
|
|
||||||
|
|
||||||
**資料庫配置**
|
|
||||||
- MySQL 主機:mysql.theaken.com:33306
|
|
||||||
- 資料庫:db_A060
|
|
||||||
- 連接已內建在 Docker 映像中
|
|
||||||
|
|
||||||
**郵件配置**
|
|
||||||
- SMTP 服務器:mail.panjit.com.tw
|
|
||||||
- 端口:25 (無認證)
|
|
||||||
|
|
||||||
**LDAP 配置**
|
|
||||||
- 服務器:panjit.com.tw
|
|
||||||
- 認證已配置完成
|
|
||||||
|
|
||||||
### 3. 建置映像
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 建置主應用映像
|
|
||||||
docker build -t panjit-translator:latest .
|
docker build -t panjit-translator:latest .
|
||||||
|
|
||||||
# 檢查映像大小
|
|
||||||
docker images panjit-translator
|
docker images panjit-translator
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. 啟動服務
|
### 3) 使用 Docker Compose 啟動(推薦)
|
||||||
|
|
||||||
**使用 Docker Compose (推薦)**
|
|
||||||
```bash
|
```bash
|
||||||
# 啟動所有服務
|
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
# 分別檢查各服務
|
|
||||||
docker-compose ps
|
docker-compose ps
|
||||||
docker-compose logs app
|
docker-compose logs app
|
||||||
docker-compose logs celery-worker
|
docker-compose logs celery-worker
|
||||||
docker-compose logs redis
|
docker-compose logs redis
|
||||||
```
|
```
|
||||||
|
|
||||||
**手動 Docker 部署**
|
### 4) 純 Docker 佈署(可選)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 啟動 Redis
|
# 啟動 Redis(內部使用,無需對外開放)
|
||||||
docker run -d --name panjit-redis \
|
docker run -d --name panjit-redis \
|
||||||
-p 6379:6379 \
|
|
||||||
-v redis_data:/data \
|
-v redis_data:/data \
|
||||||
redis:7-alpine
|
redis:7-alpine
|
||||||
|
|
||||||
# 啟動主應用
|
# 啟動主應用(Gunicorn + eventlet, 12010)
|
||||||
docker run -d --name panjit-translator \
|
docker run -d --name panjit-translator \
|
||||||
-p 12010:12010 \
|
-p 12010:12010 \
|
||||||
-v $(pwd)/uploads:/app/uploads \
|
-v $(pwd)/uploads:/app/uploads \
|
||||||
@@ -145,203 +102,52 @@ docker run -d --name panjit-translator \
|
|||||||
-e REDIS_URL=redis://redis:6379/0 \
|
-e REDIS_URL=redis://redis:6379/0 \
|
||||||
panjit-translator:latest
|
panjit-translator:latest
|
||||||
|
|
||||||
# 啟動 Celery Worker
|
# 啟動 Celery Worker(可調整並行度)
|
||||||
docker run -d --name panjit-worker \
|
docker run -d --name panjit-worker \
|
||||||
-v $(pwd)/uploads:/app/uploads \
|
-v $(pwd)/uploads:/app/uploads \
|
||||||
-v $(pwd)/cache:/app/cache \
|
-v $(pwd)/cache:/app/cache \
|
||||||
--link panjit-redis:redis \
|
--link panjit-redis:redis \
|
||||||
-e REDIS_URL=redis://redis:6379/0 \
|
-e REDIS_URL=redis://redis:6379/0 \
|
||||||
panjit-translator:latest \
|
panjit-translator:latest \
|
||||||
celery -A celery_app worker --loglevel=info
|
celery -A celery_app worker --loglevel=info --concurrency=8
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. 服務驗證
|
## 驗證與健康檢查
|
||||||
|
|
||||||
**健康檢查**
|
|
||||||
```bash
|
```bash
|
||||||
# API 健康檢查
|
# 健康檢查(API 藍圖)
|
||||||
curl -f http://localhost:12010/api/v1/health
|
curl http://localhost:12010/api/v1/health
|
||||||
|
|
||||||
# 預期回應:
|
# 前端/靜態頁
|
||||||
{
|
curl http://localhost:12010/
|
||||||
"status": "healthy",
|
|
||||||
"timestamp": "2025-09-04T12:00:00Z",
|
# WebSocket(瀏覽器端透過前端頁面測試)
|
||||||
"service": "PANJIT Document Translator API",
|
|
||||||
"version": "2.0.0"
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**功能測試**
|
## 擴展與監控
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 測試 LDAP 連接 (需要有效帳號)
|
# 觀察資源
|
||||||
curl -X POST http://localhost:12010/api/v1/auth/login \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"username": "test@panjit.com.tw", "password": "password"}'
|
|
||||||
|
|
||||||
# 測試檔案上傳端點
|
|
||||||
curl -f http://localhost:12010/api/v1/files/supported-formats
|
|
||||||
```
|
|
||||||
|
|
||||||
**Celery 檢查**
|
|
||||||
```bash
|
|
||||||
# 檢查 Worker 狀態
|
|
||||||
docker-compose exec celery-worker celery -A celery_app inspect active
|
|
||||||
|
|
||||||
# 檢查佇列狀態
|
|
||||||
docker-compose exec celery-worker celery -A celery_app inspect reserved
|
|
||||||
```
|
|
||||||
|
|
||||||
## 監控和維護
|
|
||||||
|
|
||||||
### 日誌管理
|
|
||||||
```bash
|
|
||||||
# 查看實時日誌
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# 查看特定服務日誌
|
|
||||||
docker-compose logs -f app
|
|
||||||
docker-compose logs -f celery-worker
|
|
||||||
|
|
||||||
# 查看錯誤日誌
|
|
||||||
docker-compose logs app | grep ERROR
|
|
||||||
```
|
|
||||||
|
|
||||||
### 性能監控
|
|
||||||
```bash
|
|
||||||
# 檢查容器資源使用
|
|
||||||
docker stats
|
docker stats
|
||||||
|
|
||||||
# 檢查服務狀態
|
# 觀察容器狀態
|
||||||
docker-compose ps
|
docker-compose ps
|
||||||
|
|
||||||
# 檢查健康狀況
|
# 擴展 Celery Worker 副本(例如 3 副本)
|
||||||
docker inspect panjit-translator-app --format='{{json .State.Health}}'
|
docker-compose up -d --scale celery-worker=3
|
||||||
```
|
```
|
||||||
|
|
||||||
### 備份和恢復
|
## 安全與網路
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 備份上傳檔案
|
# 僅開放必要端口(應用 12010)
|
||||||
tar -czf uploads_backup_$(date +%Y%m%d).tar.gz uploads/
|
|
||||||
|
|
||||||
# 備份快取
|
|
||||||
tar -czf cache_backup_$(date +%Y%m%d).tar.gz cache/
|
|
||||||
|
|
||||||
# 備份日誌
|
|
||||||
tar -czf logs_backup_$(date +%Y%m%d).tar.gz logs/
|
|
||||||
```
|
|
||||||
|
|
||||||
## 更新和升級
|
|
||||||
|
|
||||||
### 更新應用
|
|
||||||
```bash
|
|
||||||
# 1. 備份重要數據
|
|
||||||
docker-compose exec app tar -czf /app/backup_$(date +%Y%m%d).tar.gz uploads/ cache/
|
|
||||||
|
|
||||||
# 2. 停止服務
|
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# 3. 更新代碼和重新建置
|
|
||||||
git pull origin main
|
|
||||||
docker-compose build
|
|
||||||
|
|
||||||
# 4. 啟動服務
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 5. 驗證更新
|
|
||||||
curl http://localhost:12010/api/v1/health
|
|
||||||
```
|
|
||||||
|
|
||||||
### 滾動更新(零停機時間)
|
|
||||||
```bash
|
|
||||||
# 1. 建置新映像
|
|
||||||
docker build -t panjit-translator:v2.1.0 .
|
|
||||||
|
|
||||||
# 2. 更新 docker-compose.yml 中的映像版本
|
|
||||||
# 3. 逐一重啟服務
|
|
||||||
docker-compose up -d --no-deps app
|
|
||||||
docker-compose up -d --no-deps celery-worker
|
|
||||||
```
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 常見問題
|
|
||||||
|
|
||||||
**1. 容器無法啟動**
|
|
||||||
```bash
|
|
||||||
# 檢查端口占用
|
|
||||||
sudo netstat -tulpn | grep 12010
|
|
||||||
|
|
||||||
# 檢查映像是否存在
|
|
||||||
docker images panjit-translator
|
|
||||||
|
|
||||||
# 檢查容器日誌
|
|
||||||
docker-compose logs app
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. 資料庫連接失敗**
|
|
||||||
```bash
|
|
||||||
# 測試資料庫連接
|
|
||||||
docker-compose exec app python -c "
|
|
||||||
import pymysql
|
|
||||||
try:
|
|
||||||
conn = pymysql.connect(
|
|
||||||
host='mysql.theaken.com',
|
|
||||||
port=33306,
|
|
||||||
user='A060',
|
|
||||||
password='WLeSCi0yhtc7',
|
|
||||||
database='db_A060'
|
|
||||||
)
|
|
||||||
print('資料庫連接成功')
|
|
||||||
conn.close()
|
|
||||||
except Exception as e:
|
|
||||||
print(f'資料庫連接失敗: {e}')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. Celery Worker 無法啟動**
|
|
||||||
```bash
|
|
||||||
# 檢查 Redis 連接
|
|
||||||
docker-compose exec app python -c "
|
|
||||||
import redis
|
|
||||||
try:
|
|
||||||
r = redis.Redis.from_url('redis://redis:6379/0')
|
|
||||||
r.ping()
|
|
||||||
print('Redis 連接成功')
|
|
||||||
except Exception as e:
|
|
||||||
print(f'Redis 連接失敗: {e}')
|
|
||||||
"
|
|
||||||
|
|
||||||
# 重啟 Worker
|
|
||||||
docker-compose restart celery-worker
|
|
||||||
```
|
|
||||||
|
|
||||||
### 緊急恢復
|
|
||||||
```bash
|
|
||||||
# 完全重置並重啟
|
|
||||||
docker-compose down -v
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 清理未使用的映像和容器
|
|
||||||
docker system prune -f
|
|
||||||
|
|
||||||
# 重新建置
|
|
||||||
docker-compose build --no-cache
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## 安全配置
|
|
||||||
|
|
||||||
### 防火牆設定
|
|
||||||
```bash
|
|
||||||
# 開放必要端口
|
|
||||||
sudo ufw allow 12010/tcp
|
sudo ufw allow 12010/tcp
|
||||||
|
|
||||||
# 限制 Redis 端口(僅本機)
|
# Redis 預設不對外開放;如需遠端維運才開放 6379 並限管理網段
|
||||||
sudo ufw deny 6379/tcp
|
# sudo ufw allow from <管理網段> to any port 6379 proto tcp
|
||||||
```
|
```
|
||||||
|
|
||||||
### SSL/TLS 配置
|
如需 HTTPS,建議於前端加 Nginx/Traefik 反向代理:
|
||||||
如需 HTTPS,建議在前端配置 Nginx 反向代理:
|
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
server {
|
server {
|
||||||
@@ -361,24 +167,81 @@ server {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 疑難排解(內部)
|
||||||
|
|
||||||
|
資料庫連線測試(內部憑證):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose exec app python -c "
|
||||||
|
import pymysql
|
||||||
|
try:
|
||||||
|
conn = pymysql.connect(
|
||||||
|
host='mysql.theaken.com',
|
||||||
|
port=33306,
|
||||||
|
user='A060',
|
||||||
|
password='WLeSCi0yhtc7',
|
||||||
|
database='db_A060'
|
||||||
|
)
|
||||||
|
print('資料庫連線成功')
|
||||||
|
conn.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(f'資料庫連線失敗: {e}')
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
Redis 連線測試:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose exec app python -c "
|
||||||
|
import redis
|
||||||
|
try:
|
||||||
|
r = redis.Redis.from_url('redis://redis:6379/0')
|
||||||
|
r.ping()
|
||||||
|
print('Redis 連線成功')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Redis 連線失敗: {e}')
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
重建與清理:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose down -v
|
||||||
|
docker system prune -f
|
||||||
|
docker-compose build --no-cache
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## 維運與更新
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 備份重要資料(uploads/cache/logs)
|
||||||
|
docker-compose exec app tar -czf /app/backup_$(date +%Y%m%d).tar.gz uploads/ cache/
|
||||||
|
|
||||||
|
# 更新程式碼與重建
|
||||||
|
docker-compose down
|
||||||
|
git pull origin main
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 驗證
|
||||||
|
curl http://localhost:12010/api/v1/health
|
||||||
|
```
|
||||||
|
|
||||||
|
零停機滾動更新(僅針對單一服務重新拉起):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d --no-deps app
|
||||||
|
docker-compose up -d --no-deps celery-worker
|
||||||
|
```
|
||||||
|
|
||||||
## 聯繫支援
|
## 聯繫支援
|
||||||
|
|
||||||
如遇到部署問題,請聯繫:
|
PANJIT IT Team(內部)
|
||||||
|
|
||||||
**PANJIT IT Team**
|
|
||||||
- Email: it-support@panjit.com.tw
|
- Email: it-support@panjit.com.tw
|
||||||
- 內線電話: 2481
|
- 分機: 2481
|
||||||
- 緊急支援: 24/7 待命
|
- 緊急支援: 24/7 待命
|
||||||
|
|
||||||
**系統資訊**
|
|
||||||
- 版本:v2.1.0 (優化版)
|
|
||||||
- 部署日期:2025-09-11
|
|
||||||
- 維護人員:System Administrator
|
|
||||||
- 更新內容:
|
|
||||||
- 優化 Celery 架構,移除重複 worker
|
|
||||||
- 修正 Excel 翻譯輸出格式
|
|
||||||
- 清理開發階段檔案
|
|
||||||
- 簡化 Docker 映像構建
|
|
||||||
|
|
||||||
---
|
---
|
||||||
*本部署手冊適用於 PANJIT 文件翻譯系統 v2.1.0*
|
本文件適用於 PANJIT 文件翻譯系統 v2.1.0
|
||||||
|
|
||||||
|
@@ -62,9 +62,9 @@ COPY --from=frontend-builder /app/frontend/dist ./static
|
|||||||
# Create required directories
|
# Create required directories
|
||||||
RUN mkdir -p uploads logs scripts
|
RUN mkdir -p uploads logs scripts
|
||||||
|
|
||||||
# Create startup script (removed redundant celery worker)
|
# Create startup script using Gunicorn + eventlet for production
|
||||||
RUN echo '#!/bin/bash' > /app/start.sh && \
|
RUN echo '#!/bin/bash' > /app/start.sh && \
|
||||||
echo 'python app.py' >> /app/start.sh && \
|
echo 'exec gunicorn -k eventlet -w 1 -b 0.0.0.0:12010 wsgi:app' >> /app/start.sh && \
|
||||||
chmod +x /app/start.sh
|
chmod +x /app/start.sh
|
||||||
|
|
||||||
# Set permissions
|
# Set permissions
|
||||||
|
@@ -139,6 +139,13 @@ def create_app(config_name=None):
|
|||||||
from app.websocket import init_websocket
|
from app.websocket import init_websocket
|
||||||
app.socketio = init_websocket(app)
|
app.socketio = init_websocket(app)
|
||||||
|
|
||||||
|
# 註冊 Root 路由(提供 SPA 與基本 API 資訊)
|
||||||
|
try:
|
||||||
|
from app.root import root_bp
|
||||||
|
app.register_blueprint(root_bp)
|
||||||
|
except Exception as e:
|
||||||
|
app.logger.warning(f"Root routes not registered: {e}")
|
||||||
|
|
||||||
app.logger.info("Flask application created successfully")
|
app.logger.info("Flask application created successfully")
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
64
app/root.py
Normal file
64
app/root.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Root routes and static file serving for SPA in production.
|
||||||
|
|
||||||
|
These were originally defined in the top-level app.py. Moving them into the
|
||||||
|
package allows a clean WSGI entry (wsgi:app) without importing app.py.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from flask import Blueprint, current_app, send_from_directory
|
||||||
|
|
||||||
|
root_bp = Blueprint('root', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@root_bp.route('/')
|
||||||
|
def index():
|
||||||
|
try:
|
||||||
|
return send_from_directory('/app/static', 'index.html')
|
||||||
|
except Exception:
|
||||||
|
# Fallback API info when frontend is not present
|
||||||
|
return {
|
||||||
|
'application': 'PANJIT Document Translator',
|
||||||
|
'version': '1.0.0',
|
||||||
|
'status': 'running',
|
||||||
|
'api_base_url': '/api/v1',
|
||||||
|
'note': 'Frontend files not found, serving API info'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@root_bp.route('/<path:path>')
|
||||||
|
def serve_static(path):
|
||||||
|
try:
|
||||||
|
return send_from_directory('/app/static', path)
|
||||||
|
except Exception:
|
||||||
|
# SPA fallback
|
||||||
|
return send_from_directory('/app/static', 'index.html')
|
||||||
|
|
||||||
|
|
||||||
|
@root_bp.route('/api')
|
||||||
|
def api_info():
|
||||||
|
return {
|
||||||
|
'api_version': 'v1',
|
||||||
|
'base_url': '/api/v1',
|
||||||
|
'endpoints': {
|
||||||
|
'auth': '/api/v1/auth',
|
||||||
|
'files': '/api/v1/files',
|
||||||
|
'jobs': '/api/v1/jobs',
|
||||||
|
'admin': '/api/v1/admin',
|
||||||
|
'health': '/api/v1/health'
|
||||||
|
},
|
||||||
|
'documentation': 'Available endpoints provide RESTful API for document translation'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@root_bp.route('/api/health')
|
||||||
|
def health_check():
|
||||||
|
# Keep a simple health endpoint here for compatibility
|
||||||
|
return {
|
||||||
|
'status': 'healthy',
|
||||||
|
'timestamp': datetime.utcnow().isoformat(),
|
||||||
|
'service': 'PANJIT Document Translator API',
|
||||||
|
'version': '1.0.0'
|
||||||
|
}, 200
|
@@ -8,6 +8,7 @@ Created: 2024-01-28
|
|||||||
Modified: 2024-01-28
|
Modified: 2024-01-28
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from flask_socketio import SocketIO, emit, join_room, leave_room, disconnect
|
from flask_socketio import SocketIO, emit, join_room, leave_room, disconnect
|
||||||
from flask_jwt_extended import decode_token, get_jwt
|
from flask_jwt_extended import decode_token, get_jwt
|
||||||
from flask import request
|
from flask import request
|
||||||
@@ -17,7 +18,9 @@ import logging
|
|||||||
# 初始化 SocketIO
|
# 初始化 SocketIO
|
||||||
socketio = SocketIO(
|
socketio = SocketIO(
|
||||||
cors_allowed_origins="*",
|
cors_allowed_origins="*",
|
||||||
async_mode='threading',
|
# Use eventlet for production and enable Redis message queue for multi-process/replica support
|
||||||
|
async_mode='eventlet',
|
||||||
|
message_queue=os.getenv('REDIS_URL'),
|
||||||
logger=True,
|
logger=True,
|
||||||
engineio_logger=False
|
engineio_logger=False
|
||||||
)
|
)
|
||||||
|
@@ -3,8 +3,7 @@ services:
|
|||||||
redis:
|
redis:
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
container_name: panjit-translator-redis
|
container_name: panjit-translator-redis
|
||||||
ports:
|
# Redis only for internal network use; no public port exposure
|
||||||
- "6379:6379"
|
|
||||||
volumes:
|
volumes:
|
||||||
- redis_data:/data
|
- redis_data:/data
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -50,7 +49,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- REDIS_URL=redis://redis:6379/0
|
- REDIS_URL=redis://redis:6379/0
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: celery -A celery_app worker --loglevel=info --concurrency=4
|
command: celery -A celery_app worker --loglevel=info --concurrency=8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "celery", "-A", "celery_app", "inspect", "ping"]
|
test: ["CMD", "celery", "-A", "celery_app", "inspect", "ping"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
|
15
wsgi.py
Normal file
15
wsgi.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
WSGI entrypoint for production (Gunicorn)
|
||||||
|
|
||||||
|
This creates the Flask application via the application factory in app/__init__.py,
|
||||||
|
so we avoid importing the top-level app.py to prevent name clashes with the
|
||||||
|
package module name "app".
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app import create_app
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
|
Reference in New Issue
Block a user