forked from quant-speed-AI/Scoring-System
chore: 优化 Docker 配置,添加生产环境部署脚本和文档
This commit is contained in:
73
.env.example
Normal file
73
.env.example
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# ==========================================
|
||||||
|
# 创赢未来报名评分系统 - 环境变量配置
|
||||||
|
# 复制此文件为 .env 并修改为您的实际配置
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# Django 基础配置
|
||||||
|
# ==========================================
|
||||||
|
# 生产环境请设置为 False
|
||||||
|
DEBUG=False
|
||||||
|
|
||||||
|
# 安全密钥,生产环境必须修改!
|
||||||
|
# 生成方法: python -c "import secrets; print(secrets.token_urlsafe(50))"
|
||||||
|
SECRET_KEY=your-secret-key-change-this-in-production
|
||||||
|
|
||||||
|
# 允许访问的域名,多个用逗号分隔
|
||||||
|
ALLOWED_HOSTS=localhost,127.0.0.1,your-domain.com
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 数据库配置 (PostgreSQL)
|
||||||
|
# ==========================================
|
||||||
|
DB_NAME=scoring_system
|
||||||
|
DB_USER=postgres
|
||||||
|
DB_PASSWORD=your-db-password
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_PORT=5432
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 微信支付配置
|
||||||
|
# ==========================================
|
||||||
|
WECHAT_APPID=wx-your-app-id
|
||||||
|
WECHAT_SECRET=your-wechat-secret
|
||||||
|
WECHAT_MCHID=your-merchant-id
|
||||||
|
WECHAT_API_KEY=your-api-key
|
||||||
|
WECHAT_API_V3_KEY=your-api-v3-key
|
||||||
|
WECHAT_CERT_PATH=/path/to/cert.pem
|
||||||
|
WECHAT_KEY_PATH=/path/to/key.pem
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 阿里云 OSS 配置 (文件存储)
|
||||||
|
# ==========================================
|
||||||
|
ALIYUN_ACCESS_KEY_ID=your-access-key-id
|
||||||
|
ALIYUN_ACCESS_KEY_SECRET=your-access-key-secret
|
||||||
|
ALIYUN_OSS_ENDPOINT=https://oss-cn-your-region.aliyuncs.com
|
||||||
|
ALIYUN_OSS_BUCKET_NAME=your-bucket-name
|
||||||
|
ALIYUN_OSS_INTERNAL_ENDPOINT=https://oss-cn-your-region-internal.aliyuncs.com
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 阿里云听悟配置 (语音转写)
|
||||||
|
# ==========================================
|
||||||
|
ALIYUN_TINGWU_APP_KEY=your-tingwu-app-key
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 阿里云百炼/通义千问配置 (AI 评估)
|
||||||
|
# ==========================================
|
||||||
|
DASHSCOPE_API_KEY=your-dashscope-api-key
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 前端 API 地址配置
|
||||||
|
# ==========================================
|
||||||
|
VITE_API_URL=/api
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 其他配置
|
||||||
|
# ==========================================
|
||||||
|
# 时区
|
||||||
|
TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
# 日志级别 (DEBUG, INFO, WARNING, ERROR)
|
||||||
|
LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# 文件上传大小限制 (MB)
|
||||||
|
MAX_UPLOAD_SIZE=100
|
||||||
249
DEPLOY.md
Normal file
249
DEPLOY.md
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
# 创赢未来报名评分系统 - 生产环境部署指南
|
||||||
|
|
||||||
|
## 📋 部署前准备
|
||||||
|
|
||||||
|
### 系统要求
|
||||||
|
- **操作系统**: Ubuntu 20.04+ / CentOS 7+ / Debian 10+
|
||||||
|
- **内存**: 至少 2GB RAM
|
||||||
|
- **磁盘**: 至少 20GB 可用空间
|
||||||
|
- **Docker**: 20.10+
|
||||||
|
- **Docker Compose**: 2.0+
|
||||||
|
|
||||||
|
### 安装 Docker
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
|
||||||
|
# 安装 Docker Compose
|
||||||
|
sudo apt-get install -y docker-compose-plugin
|
||||||
|
# 或
|
||||||
|
pip install docker-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 快速部署
|
||||||
|
|
||||||
|
### 1. 拉取代码
|
||||||
|
```bash
|
||||||
|
git clone https://gitea.tangledup-ai.com/quant-speed-AI/Scoring-System.git
|
||||||
|
cd Scoring-System
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置环境变量
|
||||||
|
```bash
|
||||||
|
# 复制环境变量模板
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# 编辑 .env 文件,填入您的实际配置
|
||||||
|
vim .env
|
||||||
|
```
|
||||||
|
|
||||||
|
**必须配置的项目:**
|
||||||
|
- `SECRET_KEY`: Django 安全密钥(必须修改!)
|
||||||
|
- `DB_PASSWORD`: 数据库密码
|
||||||
|
- `WECHAT_*`: 微信支付相关配置(如需支付功能)
|
||||||
|
- `ALIYUN_*`: 阿里云 OSS 和 AI 服务配置(如需语音转写和 AI 评估)
|
||||||
|
|
||||||
|
### 3. 执行部署脚本
|
||||||
|
```bash
|
||||||
|
# 给脚本添加执行权限
|
||||||
|
chmod +x deploy.sh
|
||||||
|
|
||||||
|
# 执行部署
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 手动部署(高级)
|
||||||
|
|
||||||
|
### 1. 构建镜像
|
||||||
|
```bash
|
||||||
|
docker-compose build --no-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 启动服务
|
||||||
|
```bash
|
||||||
|
# 后台启动
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
docker-compose logs -f
|
||||||
|
|
||||||
|
# 查看特定服务日志
|
||||||
|
docker-compose logs -f backend
|
||||||
|
docker-compose logs -f frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 执行数据库迁移
|
||||||
|
```bash
|
||||||
|
docker-compose exec backend python manage.py migrate
|
||||||
|
docker-compose exec backend python manage.py createsuperuser
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 收集静态文件
|
||||||
|
```bash
|
||||||
|
docker-compose exec backend python manage.py collectstatic --noinput
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌐 Nginx 反向代理配置(推荐)
|
||||||
|
|
||||||
|
如果需要使用域名和 HTTPS,在服务器上安装 Nginx:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# /etc/nginx/sites-available/scoring-system
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name your-domain.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:80;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
启用配置:
|
||||||
|
```bash
|
||||||
|
sudo ln -s /etc/nginx/sites-available/scoring-system /etc/nginx/sites-enabled/
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 HTTPS 配置(Let's Encrypt)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装 Certbot
|
||||||
|
sudo apt-get install -y certbot python3-certbot-nginx
|
||||||
|
|
||||||
|
# 申请证书
|
||||||
|
sudo certbot --nginx -d your-domain.com
|
||||||
|
|
||||||
|
# 自动续期
|
||||||
|
sudo certbot renew --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看运行状态
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# 停止服务
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# 重启服务
|
||||||
|
docker-compose restart
|
||||||
|
|
||||||
|
# 重启单个服务
|
||||||
|
docker-compose restart backend
|
||||||
|
|
||||||
|
# 进入容器
|
||||||
|
docker-compose exec backend bash
|
||||||
|
docker-compose exec frontend sh
|
||||||
|
|
||||||
|
# 查看容器日志
|
||||||
|
docker-compose logs -f --tail=100 backend
|
||||||
|
|
||||||
|
# 清理未使用的镜像
|
||||||
|
docker image prune -f
|
||||||
|
|
||||||
|
# 更新部署(拉取最新代码并重启)
|
||||||
|
git pull
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 故障排查
|
||||||
|
|
||||||
|
### 问题1: 端口被占用
|
||||||
|
```bash
|
||||||
|
# 检查端口占用
|
||||||
|
sudo netstat -tlnp | grep 8000
|
||||||
|
sudo netstat -tlnp | grep 80
|
||||||
|
|
||||||
|
# 修改 docker-compose.yml 中的端口映射
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题2: 数据库连接失败
|
||||||
|
```bash
|
||||||
|
# 检查数据库配置
|
||||||
|
docker-compose exec backend python manage.py dbshell
|
||||||
|
|
||||||
|
# 查看后端日志
|
||||||
|
docker-compose logs backend | grep -i error
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题3: 静态文件无法访问
|
||||||
|
```bash
|
||||||
|
# 重新收集静态文件
|
||||||
|
docker-compose exec backend python manage.py collectstatic --noinput
|
||||||
|
|
||||||
|
# 检查权限
|
||||||
|
ls -la backend/static/
|
||||||
|
ls -la backend/media/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题4: 容器无法启动
|
||||||
|
```bash
|
||||||
|
# 查看详细日志
|
||||||
|
docker-compose logs --no-color
|
||||||
|
|
||||||
|
# 检查配置
|
||||||
|
docker-compose config
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💾 数据备份
|
||||||
|
|
||||||
|
### 数据库备份
|
||||||
|
```bash
|
||||||
|
# 进入容器执行备份
|
||||||
|
docker-compose exec backend python manage.py dumpdata > backup_$(date +%Y%m%d).json
|
||||||
|
|
||||||
|
# 或使用 PostgreSQL 直接备份
|
||||||
|
docker exec scoring_system_db pg_dump -U postgres scoring_system > db_backup_$(date +%Y%m%d).sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 媒体文件备份
|
||||||
|
```bash
|
||||||
|
# 备份上传的文件
|
||||||
|
tar -czvf media_backup_$(date +%Y%m%d).tar.gz backend/media/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 自动部署(CI/CD)
|
||||||
|
|
||||||
|
使用 Gitea Actions 或 Jenkins 实现自动部署:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .gitea/workflows/deploy.yaml
|
||||||
|
name: Deploy to Production
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Deploy to Server
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.HOST }}
|
||||||
|
username: ${{ secrets.USERNAME }}
|
||||||
|
password: ${{ secrets.PASSWORD }}
|
||||||
|
script: |
|
||||||
|
cd ~/Scoring-System
|
||||||
|
git pull
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
- **项目仓库**: https://gitea.tangledup-ai.com/quant-speed-AI/Scoring-System
|
||||||
|
- **问题反馈**: 在仓库提交 Issue
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**部署完成后访问地址:**
|
||||||
|
- 🌐 前端页面: http://your-server-ip/
|
||||||
|
- 🔧 后台管理: http://your-server-ip:8000/admin/
|
||||||
|
- 📚 API 文档: http://your-server-ip:8000/api/docs/
|
||||||
@@ -1,26 +1,40 @@
|
|||||||
# Use an official Python runtime as a parent image
|
# 使用 Python 3.12 slim 镜像作为基础镜像
|
||||||
FROM python:3.13-slim
|
FROM python:3.12-slim
|
||||||
|
|
||||||
# Set environment variables
|
# 设置环境变量
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV PYTHONIOENCODING=utf-8
|
||||||
|
|
||||||
# Set work directory
|
# 设置工作目录
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install python dependencies
|
# 安装系统依赖
|
||||||
COPY requirements.txt /app/
|
RUN apt-get update && apt-get install -y \
|
||||||
RUN pip install --upgrade pip && pip install -r requirements.txt
|
gcc \
|
||||||
|
libpq-dev \
|
||||||
|
libffi-dev \
|
||||||
|
libjpeg-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Copy project
|
# 复制 requirements 文件并安装依赖
|
||||||
COPY . /app/
|
COPY requirements.txt .
|
||||||
COPY .env /app/
|
RUN pip install --no-cache-dir --upgrade pip && \
|
||||||
|
pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# Expose port
|
# 复制项目代码
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 创建媒体文件目录
|
||||||
|
RUN mkdir -p /app/media /app/static
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
# Volume for media files
|
# 健康检查
|
||||||
VOLUME ["/app/media"]
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
CMD python -c "import requests; requests.get('http://localhost:8000/api/health/')" || exit 1
|
||||||
|
|
||||||
# Run the application with gunicorn
|
# 启动命令
|
||||||
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "config.wsgi:application"]
|
CMD ["sh", "-c", "python manage.py collectstatic --noinput && python manage.py migrate && gunicorn --bind 0.0.0.0:8000 --workers 4 --threads 2 --worker-class gthread --access-logfile - --error-logfile - --capture-output --enable-stdio-inheritance config.wsgi:application"]
|
||||||
|
|||||||
@@ -2,11 +2,21 @@ from django.contrib import admin
|
|||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
|
from django.http import JsonResponse
|
||||||
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, SpectacularRedocView
|
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, SpectacularRedocView
|
||||||
from competition import judge_views
|
from competition import judge_views
|
||||||
|
|
||||||
|
# 健康检查视图
|
||||||
|
def health_check(request):
|
||||||
|
return JsonResponse({
|
||||||
|
'status': 'healthy',
|
||||||
|
'service': '创赢未来报名评分系统',
|
||||||
|
'version': '1.0.0'
|
||||||
|
})
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
path('api/health/', health_check, name='health_check'),
|
||||||
|
|
||||||
# Judge System Routes
|
# Judge System Routes
|
||||||
path('judge/', include('competition.judge_urls')),
|
path('judge/', include('competition.judge_urls')),
|
||||||
|
|||||||
95
deploy.sh
Normal file
95
deploy.sh
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 创赢未来报名评分系统 - 生产环境部署脚本
|
||||||
|
# 用法: ./deploy.sh [环境变量]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 打印带颜色的信息
|
||||||
|
print_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查环境
|
||||||
|
print_info "检查 Docker 环境..."
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
print_error "Docker 未安装,请先安装 Docker"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
|
||||||
|
print_error "Docker Compose 未安装,请先安装 Docker Compose"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 .env 文件
|
||||||
|
if [ ! -f .env ]; then
|
||||||
|
print_warning ".env 文件不存在,将使用默认配置"
|
||||||
|
print_warning "建议复制 .env.example 为 .env 并修改配置"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 显示部署信息
|
||||||
|
print_info "================================"
|
||||||
|
print_info "创赢未来报名评分系统 - 部署脚本"
|
||||||
|
print_info "================================"
|
||||||
|
|
||||||
|
# 拉取最新代码(如果是 git 仓库)
|
||||||
|
if [ -d .git ]; then
|
||||||
|
print_info "拉取最新代码..."
|
||||||
|
git pull || print_warning "Git pull 失败,使用本地代码继续"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 停止旧容器
|
||||||
|
print_info "停止旧容器..."
|
||||||
|
docker-compose down --remove-orphans
|
||||||
|
|
||||||
|
# 删除旧镜像(可选)
|
||||||
|
print_info "清理旧镜像..."
|
||||||
|
docker-compose rm -f
|
||||||
|
|
||||||
|
# 构建镜像
|
||||||
|
print_info "构建 Docker 镜像..."
|
||||||
|
docker-compose build --no-cache
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
print_info "启动服务..."
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 等待服务启动
|
||||||
|
print_info "等待服务启动..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# 检查服务状态
|
||||||
|
print_info "检查服务状态..."
|
||||||
|
if docker-compose ps | grep -q "Up"; then
|
||||||
|
print_success "服务启动成功!"
|
||||||
|
echo ""
|
||||||
|
print_info "访问地址:"
|
||||||
|
print_success " - 前端: http://localhost"
|
||||||
|
print_success " - 后端 API: http://localhost:8000/api/"
|
||||||
|
print_success " - 后台管理: http://localhost:8000/admin/"
|
||||||
|
echo ""
|
||||||
|
print_info "查看日志: docker-compose logs -f"
|
||||||
|
else
|
||||||
|
print_error "服务启动失败,请检查日志: docker-compose logs"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -1,31 +1,85 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
# 后端服务
|
||||||
backend:
|
backend:
|
||||||
build: ./backend
|
build:
|
||||||
# 使用 gunicorn 替代 runserver,提高稳定性,并捕获标准输出1
|
context: ./backend
|
||||||
command: sh -c "python manage.py collectstatic --noinput && python manage.py migrate && gunicorn --bind 0.0.0.0:8000 --access-logfile - --error-logfile - config.wsgi:application"
|
dockerfile: Dockerfile
|
||||||
|
container_name: scoring_backend
|
||||||
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./backend:/app
|
|
||||||
- ./backend/media:/app/media
|
- ./backend/media:/app/media
|
||||||
|
- ./backend/static:/app/static
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
environment:
|
environment:
|
||||||
- DB_NAME=market
|
- DEBUG=False
|
||||||
- DB_USER=market
|
- SECRET_KEY=${SECRET_KEY:-your-secret-key-change-this}
|
||||||
- DB_PASSWORD=123market
|
- DB_NAME=${DB_NAME:-scoring_system}
|
||||||
- DB_HOST=6.6.6.66
|
- DB_USER=${DB_USER:-postgres}
|
||||||
- DB_PORT=5432
|
- DB_PASSWORD=${DB_PASSWORD:-password}
|
||||||
|
- DB_HOST=${DB_HOST:-localhost}
|
||||||
|
- DB_PORT=${DB_PORT:-5432}
|
||||||
|
- WECHAT_APPID=${WECHAT_APPID}
|
||||||
|
- WECHAT_SECRET=${WECHAT_SECRET}
|
||||||
|
- WECHAT_MCHID=${WECHAT_MCHID}
|
||||||
|
- WECHAT_API_KEY=${WECHAT_API_KEY}
|
||||||
|
- ALIYUN_ACCESS_KEY_ID=${ALIYUN_ACCESS_KEY_ID}
|
||||||
|
- ALIYUN_ACCESS_KEY_SECRET=${ALIYUN_ACCESS_KEY_SECRET}
|
||||||
|
- ALIYUN_OSS_ENDPOINT=${ALIYUN_OSS_ENDPOINT}
|
||||||
|
- ALIYUN_OSS_BUCKET_NAME=${ALIYUN_OSS_BUCKET_NAME}
|
||||||
|
- ALIYUN_TINGWU_APP_KEY=${ALIYUN_TINGWU_APP_KEY}
|
||||||
|
- DASHSCOPE_API_KEY=${DASHSCOPE_API_KEY}
|
||||||
|
networks:
|
||||||
|
- scoring_network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "python", "-c", "import requests; requests.get('http://localhost:8000/api/health/')"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
# 前端服务 (Nginx)
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: ./frontend
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
- VITE_API_URL=/api
|
- VITE_API_URL=/api
|
||||||
# volumes:
|
container_name: scoring_frontend
|
||||||
# - ./frontend:/app
|
restart: always
|
||||||
# - /app/node_modules
|
|
||||||
ports:
|
ports:
|
||||||
- "15173:15173"
|
- "80:80"
|
||||||
environment:
|
|
||||||
- VITE_API_URL=http://localhost:8000/api
|
|
||||||
depends_on:
|
depends_on:
|
||||||
|
backend:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- scoring_network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
# Nginx 反向代理 (可选,用于负载均衡和 SSL)
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: scoring_nginx
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./nginx/ssl:/etc/nginx/ssl:ro
|
||||||
|
depends_on:
|
||||||
|
- frontend
|
||||||
- backend
|
- backend
|
||||||
|
networks:
|
||||||
|
- scoring_network
|
||||||
|
profiles:
|
||||||
|
- ssl # 只在需要 SSL 时启动
|
||||||
|
|
||||||
|
networks:
|
||||||
|
scoring_network:
|
||||||
|
driver: bridge
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
# Use an official Node runtime as a parent image
|
# 构建阶段
|
||||||
FROM node:22-alpine
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
# Set working directory
|
# 设置工作目录
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install build dependencies for native modules
|
# 安装依赖
|
||||||
RUN apk add --no-cache autoconf automake libtool make g++ zlib-dev nasm python3
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
COPY package.json package-lock.json* ./
|
COPY package.json package-lock.json* ./
|
||||||
RUN npm install --registry=https://registry.npmmirror.com
|
RUN npm install --registry=https://registry.npmmirror.com
|
||||||
|
|
||||||
@@ -16,14 +13,22 @@ COPY . .
|
|||||||
|
|
||||||
# 接收构建参数
|
# 接收构建参数
|
||||||
ARG VITE_API_URL=/api
|
ARG VITE_API_URL=/api
|
||||||
# 设置环境变量供构建时使用
|
ENV VITE_API_URL=${VITE_API_URL}
|
||||||
ENV VITE_API_URL=$VITE_API_URL
|
|
||||||
|
|
||||||
# 构建生产环境代码
|
# 构建生产环境代码
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# 暴露应用运行的端口
|
# 生产阶段 - 使用 Nginx
|
||||||
EXPOSE 15173
|
FROM nginx:alpine
|
||||||
|
|
||||||
# 启动应用 (Preview 模式)
|
# 复制 Nginx 配置
|
||||||
CMD ["npm", "run", "preview", "--", "--host", "0.0.0.0", "--port", "15173"]
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# 从构建阶段复制构建产物
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# 启动 Nginx
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|||||||
67
frontend/nginx.conf
Normal file
67
frontend/nginx.conf
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gzip 压缩
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
||||||
|
|
||||||
|
# 缓存静态资源
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|otf)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 前端路由支持 - 所有路由指向 index.html
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
add_header Cache-Control "no-cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
# API 代理 - 将 /api 请求转发到后端
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://backend:8000/api/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
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_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 媒体文件代理
|
||||||
|
location /media/ {
|
||||||
|
proxy_pass http://backend:8000/media/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态文件代理
|
||||||
|
location /static/ {
|
||||||
|
proxy_pass http://backend:8000/static/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 健康检查
|
||||||
|
location /health {
|
||||||
|
access_log off;
|
||||||
|
return 200 "healthy\n";
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 错误页面
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user