feat: 添加完整的部署支持
- 后端多环境配置(dev, prod) - Docker 部署支持(Dockerfile, docker-compose.yml) - Java 部署脚本(deploy.sh) - 前端构建脚本(build.sh,支持自定义后端地址) - 健康检查接口(/api/health) - 完整的部署文档(docs/DEPLOYMENT.md) - 前端环境变量支持(VITE_API_URL, VITE_WS_URL)
This commit is contained in:
@@ -80,9 +80,9 @@ polymarket-bot/
|
||||
- JDK 17+
|
||||
- Node.js 18+
|
||||
- MySQL 8.0+
|
||||
- Gradle 7.5+
|
||||
- Gradle 7.5+(或使用 Gradle Wrapper)
|
||||
|
||||
### 安装步骤
|
||||
### 开发环境
|
||||
|
||||
1. **克隆仓库**
|
||||
|
||||
@@ -99,33 +99,16 @@ cd PolyHermes
|
||||
CREATE DATABASE polymarket_bot CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
3. **配置后端**
|
||||
|
||||
编辑 `backend/src/main/resources/application.properties`:
|
||||
|
||||
```properties
|
||||
# 数据库配置
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8mb4
|
||||
spring.datasource.username=${DB_USERNAME:root}
|
||||
spring.datasource.password=${DB_PASSWORD:your_password}
|
||||
|
||||
# 服务器端口
|
||||
server.port=${SERVER_PORT:8000}
|
||||
|
||||
# Polygon RPC(用于查询链上余额)
|
||||
polygon.rpc.url=${POLYGON_RPC_URL:https://polygon-rpc.com}
|
||||
```
|
||||
|
||||
4. **启动后端**
|
||||
3. **启动后端**
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
./gradlew bootRun
|
||||
```
|
||||
|
||||
后端服务将在 `http://localhost:8000` 启动。
|
||||
后端服务将在 `http://localhost:8000` 启动(开发环境)。
|
||||
|
||||
5. **启动前端**
|
||||
4. **启动前端**
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
@@ -135,6 +118,34 @@ npm run dev
|
||||
|
||||
前端应用将在 `http://localhost:3000` 启动。
|
||||
|
||||
### 生产部署
|
||||
|
||||
详细的部署文档请参考:[部署文档](docs/DEPLOYMENT.md)
|
||||
|
||||
#### 快速部署
|
||||
|
||||
**后端(Java 方式)**:
|
||||
```bash
|
||||
cd backend
|
||||
./deploy.sh java
|
||||
```
|
||||
|
||||
**后端(Docker 方式)**:
|
||||
```bash
|
||||
cd backend
|
||||
./deploy.sh docker
|
||||
```
|
||||
|
||||
**前端**:
|
||||
```bash
|
||||
cd frontend
|
||||
# 使用默认后端地址
|
||||
./build.sh
|
||||
|
||||
# 或指定自定义后端地址
|
||||
./build.sh --api-url http://your-backend-server.com:8000
|
||||
```
|
||||
|
||||
## 📖 使用指南
|
||||
|
||||
### 账户管理
|
||||
@@ -180,11 +191,11 @@ npm run dev
|
||||
3. 启用代理并测试连接
|
||||
4. 配置实时生效,无需重启服务
|
||||
|
||||
## 📚 API 文档
|
||||
## 📚 文档
|
||||
|
||||
详细的 API 文档请参考:
|
||||
- [跟单系统需求文档](docs/copy-trading-requirements.md)
|
||||
- [前端需求文档](docs/copy-trading-frontend-requirements.md)
|
||||
- [部署文档](docs/DEPLOYMENT.md) - 详细的部署指南(Java/Docker)
|
||||
- [跟单系统需求文档](docs/copy-trading-requirements.md) - 后端 API 接口文档
|
||||
- [前端需求文档](docs/copy-trading-frontend-requirements.md) - 前端功能文档
|
||||
|
||||
## 🤝 贡献
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Gradle
|
||||
.gradle/
|
||||
build/
|
||||
out/
|
||||
bin/
|
||||
*.log
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
*.ipr
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.DS_Store
|
||||
|
||||
# 部署相关
|
||||
deploy/
|
||||
*.jar
|
||||
!build/libs/*.jar
|
||||
|
||||
# 环境配置
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# 其他
|
||||
*.bak
|
||||
*.backup
|
||||
*.old
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# 多阶段构建 Dockerfile
|
||||
# 阶段1:构建应用
|
||||
FROM gradle:8.5-jdk17 AS build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 复制 Gradle 配置文件
|
||||
COPY build.gradle.kts settings.gradle.kts ./
|
||||
COPY gradle ./gradle
|
||||
|
||||
# 下载依赖(利用 Docker 缓存)
|
||||
RUN gradle dependencies --no-daemon || true
|
||||
|
||||
# 复制源代码
|
||||
COPY src ./src
|
||||
|
||||
# 构建应用
|
||||
RUN gradle bootJar --no-daemon
|
||||
|
||||
# 阶段2:运行应用
|
||||
FROM openjdk:17-jre-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 安装必要的工具
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 从构建阶段复制 JAR 文件
|
||||
COPY --from=build /app/build/libs/*.jar app.jar
|
||||
|
||||
# 创建非 root 用户
|
||||
RUN useradd -m -u 1000 appuser && \
|
||||
chown -R appuser:appuser /app
|
||||
|
||||
USER appuser
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 8000
|
||||
|
||||
# 健康检查
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||
CMD curl -f http://localhost:8000/api/health || exit 1
|
||||
|
||||
# 启动应用
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
|
||||
Executable
+203
@@ -0,0 +1,203 @@
|
||||
#!/bin/bash
|
||||
|
||||
# PolyHermes 后端部署脚本
|
||||
# 支持 Java 直接部署和 Docker 部署
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 配置
|
||||
APP_NAME="polymarket-bot-backend"
|
||||
JAR_NAME="polymarket-bot-backend-1.0.0.jar"
|
||||
DEPLOY_DIR="./deploy"
|
||||
PROFILE="${SPRING_PROFILES_ACTIVE:-prod}"
|
||||
|
||||
# 打印信息
|
||||
info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查 Java 环境
|
||||
check_java() {
|
||||
if ! command -v java &> /dev/null; then
|
||||
error "Java 未安装,请先安装 Java 17+"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | cut -d'.' -f1)
|
||||
if [ "$JAVA_VERSION" -lt 17 ]; then
|
||||
error "Java 版本过低,需要 Java 17+,当前版本: $JAVA_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
info "Java 环境检查通过: $(java -version 2>&1 | head -n 1)"
|
||||
}
|
||||
|
||||
# 构建应用
|
||||
build_app() {
|
||||
info "开始构建应用..."
|
||||
|
||||
if ! command -v gradle &> /dev/null; then
|
||||
error "Gradle 未安装,请先安装 Gradle 或使用 Gradle Wrapper"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./gradlew clean bootJar
|
||||
|
||||
if [ ! -f "build/libs/$JAR_NAME" ]; then
|
||||
error "构建失败,JAR 文件不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
info "构建完成: build/libs/$JAR_NAME"
|
||||
}
|
||||
|
||||
# Java 部署
|
||||
deploy_java() {
|
||||
info "使用 Java 方式部署..."
|
||||
|
||||
# 创建部署目录
|
||||
mkdir -p "$DEPLOY_DIR"
|
||||
|
||||
# 复制 JAR 文件
|
||||
cp "build/libs/$JAR_NAME" "$DEPLOY_DIR/"
|
||||
|
||||
# 创建启动脚本
|
||||
cat > "$DEPLOY_DIR/start.sh" <<EOF
|
||||
#!/bin/bash
|
||||
cd \$(dirname \$0)
|
||||
|
||||
# 设置 JVM 参数
|
||||
JVM_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
|
||||
|
||||
# 启动应用
|
||||
java \$JVM_OPTS -jar $JAR_NAME --spring.profiles.active=$PROFILE
|
||||
EOF
|
||||
|
||||
chmod +x "$DEPLOY_DIR/start.sh"
|
||||
|
||||
# 创建 systemd 服务文件(可选)
|
||||
cat > "$DEPLOY_DIR/${APP_NAME}.service" <<EOF
|
||||
[Unit]
|
||||
Description=PolyHermes Backend Service
|
||||
After=network.target mysql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=\${USER}
|
||||
WorkingDirectory=$DEPLOY_DIR
|
||||
ExecStart=/usr/bin/java -Xms512m -Xmx1024m -XX:+UseG1GC -jar $JAR_NAME --spring.profiles.active=$PROFILE
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
info "Java 部署文件已创建在: $DEPLOY_DIR"
|
||||
info "启动方式: cd $DEPLOY_DIR && ./start.sh"
|
||||
info "或使用 systemd: sudo cp ${APP_NAME}.service /etc/systemd/system/ && sudo systemctl start ${APP_NAME}"
|
||||
}
|
||||
|
||||
# Docker 部署
|
||||
deploy_docker() {
|
||||
info "使用 Docker 方式部署..."
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
error "Docker 未安装,请先安装 Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
error "Docker Compose 未安装,请先安装 Docker Compose"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建 .env 文件(如果不存在)
|
||||
if [ ! -f ".env" ]; then
|
||||
warn ".env 文件不存在,创建示例文件..."
|
||||
cat > .env <<EOF
|
||||
# 数据库配置
|
||||
DB_URL=jdbc:mysql://mysql:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8mb4
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=your_password_here
|
||||
|
||||
# Spring Profile
|
||||
SPRING_PROFILES_ACTIVE=prod
|
||||
|
||||
# 服务器端口
|
||||
SERVER_PORT=8000
|
||||
|
||||
# Polygon RPC
|
||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
||||
|
||||
# JWT 密钥(生产环境必须修改)
|
||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||
|
||||
# 管理员密码重置密钥(生产环境必须修改)
|
||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||
EOF
|
||||
warn "请编辑 .env 文件配置相关参数"
|
||||
fi
|
||||
|
||||
# 构建并启动
|
||||
info "构建 Docker 镜像..."
|
||||
docker-compose build
|
||||
|
||||
info "启动服务..."
|
||||
docker-compose up -d
|
||||
|
||||
info "Docker 部署完成"
|
||||
info "查看日志: docker-compose logs -f"
|
||||
info "停止服务: docker-compose down"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo "=========================================="
|
||||
echo " PolyHermes 后端部署脚本"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 解析参数
|
||||
DEPLOY_MODE="${1:-java}"
|
||||
|
||||
case "$DEPLOY_MODE" in
|
||||
java)
|
||||
check_java
|
||||
build_app
|
||||
deploy_java
|
||||
;;
|
||||
docker)
|
||||
deploy_docker
|
||||
;;
|
||||
build)
|
||||
check_java
|
||||
build_app
|
||||
;;
|
||||
*)
|
||||
echo "用法: $0 [java|docker|build]"
|
||||
echo ""
|
||||
echo " java - Java 直接部署(默认)"
|
||||
echo " docker - Docker 部署"
|
||||
echo " build - 仅构建应用"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: polymarket-bot-backend
|
||||
ports:
|
||||
- "${SERVER_PORT:-8000}:8000"
|
||||
environment:
|
||||
- SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-prod}
|
||||
- DB_URL=${DB_URL:-jdbc:mysql://mysql:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8mb4}
|
||||
- DB_USERNAME=${DB_USERNAME:-root}
|
||||
- DB_PASSWORD=${DB_PASSWORD:-}
|
||||
- SERVER_PORT=8000
|
||||
- POLYGON_RPC_URL=${POLYGON_RPC_URL:-https://polygon-rpc.com}
|
||||
- JWT_SECRET=${JWT_SECRET:-change-me-in-production}
|
||||
- ADMIN_RESET_PASSWORD_KEY=${ADMIN_RESET_PASSWORD_KEY:-change-me-in-production}
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- polymarket-network
|
||||
|
||||
mysql:
|
||||
image: mysql:8.2
|
||||
container_name: polymarket-bot-mysql
|
||||
ports:
|
||||
- "${MYSQL_PORT:-3306}:3306"
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD:-rootpassword}
|
||||
- MYSQL_DATABASE=polymarket_bot
|
||||
- MYSQL_CHARACTER_SET_SERVER=utf8mb4
|
||||
- MYSQL_COLLATION_SERVER=utf8mb4_unicode_ci
|
||||
volumes:
|
||||
- mysql-data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DB_PASSWORD:-rootpassword}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- polymarket-network
|
||||
|
||||
volumes:
|
||||
mysql-data:
|
||||
|
||||
networks:
|
||||
polymarket-network:
|
||||
driver: bridge
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.wrbug.polymarketbot.controller
|
||||
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 健康检查控制器
|
||||
* 用于 Docker 健康检查和监控
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/health")
|
||||
class HealthController {
|
||||
|
||||
@GetMapping
|
||||
fun health(): ResponseEntity<Map<String, Any>> {
|
||||
return ResponseEntity.ok(mapOf(
|
||||
"status" to "UP",
|
||||
"timestamp" to System.currentTimeMillis(),
|
||||
"service" to "polymarket-bot-backend"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 应用配置
|
||||
spring.application.name=polymarket-bot-backend
|
||||
|
||||
# 数据源配置
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8&allowPublicKeyRetrieval=true
|
||||
# 数据源配置(默认配置,可通过环境变量覆盖)
|
||||
spring.datasource.url=${DB_URL:jdbc:mysql://localhost:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8&allowPublicKeyRetrieval=true}
|
||||
spring.datasource.username=${DB_USERNAME:root}
|
||||
spring.datasource.password=${DB_PASSWORD:11111111}
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
@@ -25,6 +25,10 @@ spring.flyway.baseline-on-migrate=true
|
||||
# 服务器配置
|
||||
server.port=${SERVER_PORT:8000}
|
||||
|
||||
# Spring Profile 配置
|
||||
# 默认使用 dev 环境,可通过 --spring.profiles.active=prod 切换
|
||||
spring.profiles.active=${SPRING_PROFILES_ACTIVE:dev}
|
||||
|
||||
# 日志配置
|
||||
logging.level.root=INFO
|
||||
logging.level.com.wrbug.polymarketbot=DEBUG
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
# PolyHermes 部署文档
|
||||
|
||||
本文档介绍如何部署 PolyHermes 项目,包括后端和前端的不同部署方式。
|
||||
|
||||
## 目录
|
||||
|
||||
- [后端部署](#后端部署)
|
||||
- [Java 直接部署](#java-直接部署)
|
||||
- [Docker 部署](#docker-部署)
|
||||
- [前端部署](#前端部署)
|
||||
- [环境配置](#环境配置)
|
||||
- [常见问题](#常见问题)
|
||||
|
||||
## 后端部署
|
||||
|
||||
### Java 直接部署
|
||||
|
||||
#### 前置要求
|
||||
|
||||
- JDK 17+
|
||||
- MySQL 8.0+
|
||||
- Gradle 7.5+(或使用 Gradle Wrapper)
|
||||
|
||||
#### 部署步骤
|
||||
|
||||
1. **构建应用**
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
./gradlew clean bootJar
|
||||
```
|
||||
|
||||
构建产物位于 `build/libs/polymarket-bot-backend-1.0.0.jar`
|
||||
|
||||
2. **使用部署脚本(推荐)**
|
||||
|
||||
```bash
|
||||
# 构建并创建部署文件
|
||||
./deploy.sh java
|
||||
|
||||
# 或仅构建
|
||||
./deploy.sh build
|
||||
```
|
||||
|
||||
脚本会自动:
|
||||
- 检查 Java 环境
|
||||
- 构建应用
|
||||
- 创建部署目录和启动脚本
|
||||
- 生成 systemd 服务文件(可选)
|
||||
|
||||
3. **手动启动**
|
||||
|
||||
```bash
|
||||
# 开发环境
|
||||
java -jar build/libs/polymarket-bot-backend-1.0.0.jar --spring.profiles.active=dev
|
||||
|
||||
# 生产环境
|
||||
java -jar build/libs/polymarket-bot-backend-1.0.0.jar --spring.profiles.active=prod
|
||||
```
|
||||
|
||||
4. **使用 systemd 管理(Linux)**
|
||||
|
||||
```bash
|
||||
# 复制服务文件
|
||||
sudo cp deploy/polymarket-bot-backend.service /etc/systemd/system/
|
||||
|
||||
# 编辑服务文件,修改路径和用户
|
||||
sudo nano /etc/systemd/system/polymarket-bot-backend.service
|
||||
|
||||
# 启动服务
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable polymarket-bot-backend
|
||||
sudo systemctl start polymarket-bot-backend
|
||||
|
||||
# 查看日志
|
||||
sudo journalctl -u polymarket-bot-backend -f
|
||||
```
|
||||
|
||||
### Docker 部署
|
||||
|
||||
#### 前置要求
|
||||
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+
|
||||
|
||||
#### 部署步骤
|
||||
|
||||
1. **使用部署脚本(推荐)**
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
./deploy.sh docker
|
||||
```
|
||||
|
||||
脚本会自动:
|
||||
- 检查 Docker 环境
|
||||
- 创建 `.env` 配置文件(如果不存在)
|
||||
- 构建 Docker 镜像
|
||||
- 启动服务
|
||||
|
||||
2. **手动部署**
|
||||
|
||||
```bash
|
||||
# 创建 .env 文件
|
||||
cat > .env <<EOF
|
||||
DB_URL=jdbc:mysql://mysql:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8mb4
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=your_password_here
|
||||
SPRING_PROFILES_ACTIVE=prod
|
||||
SERVER_PORT=8000
|
||||
POLYGON_RPC_URL=https://polygon-rpc.com
|
||||
JWT_SECRET=your-jwt-secret-key-change-in-production
|
||||
ADMIN_RESET_PASSWORD_KEY=your-admin-reset-key-change-in-production
|
||||
EOF
|
||||
|
||||
# 构建并启动
|
||||
docker-compose up -d
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs -f
|
||||
|
||||
# 停止服务
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
3. **仅构建镜像**
|
||||
|
||||
```bash
|
||||
docker build -t polymarket-bot-backend:latest .
|
||||
```
|
||||
|
||||
4. **运行容器**
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name polymarket-bot-backend \
|
||||
-p 8000:8000 \
|
||||
-e SPRING_PROFILES_ACTIVE=prod \
|
||||
-e DB_URL=jdbc:mysql://host.docker.internal:3306/polymarket_bot?useSSL=false \
|
||||
-e DB_USERNAME=root \
|
||||
-e DB_PASSWORD=your_password \
|
||||
-e JWT_SECRET=your-jwt-secret \
|
||||
polymarket-bot-backend:latest
|
||||
```
|
||||
|
||||
## 前端部署
|
||||
|
||||
### 构建步骤
|
||||
|
||||
1. **使用构建脚本(推荐)**
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
|
||||
# 使用默认后端地址(http://127.0.0.1:8000)
|
||||
./build.sh
|
||||
|
||||
# 或指定自定义后端地址
|
||||
./build.sh --api-url http://your-backend-server.com:8000
|
||||
|
||||
# 或使用环境变量
|
||||
VITE_API_URL=http://your-backend-server.com:8000 ./build.sh
|
||||
```
|
||||
|
||||
2. **手动构建**
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
|
||||
# 创建环境配置文件
|
||||
cat > .env.production <<EOF
|
||||
VITE_API_URL=http://your-backend-server.com:8000
|
||||
VITE_WS_URL=ws://your-backend-server.com:8000
|
||||
EOF
|
||||
|
||||
# 安装依赖(首次)
|
||||
npm install
|
||||
|
||||
# 构建
|
||||
npm run build
|
||||
```
|
||||
|
||||
构建产物位于 `dist/` 目录。
|
||||
|
||||
### 部署方式
|
||||
|
||||
#### 方式1:Nginx 部署
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
root /path/to/frontend/dist;
|
||||
index index.html;
|
||||
|
||||
# API 代理
|
||||
location /api {
|
||||
proxy_pass http://localhost:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
# WebSocket 代理
|
||||
location /ws {
|
||||
proxy_pass http://localhost:8000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
# 前端路由(SPA)
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 方式2:Apache 部署
|
||||
|
||||
```apache
|
||||
<VirtualHost *:80>
|
||||
ServerName your-domain.com
|
||||
DocumentRoot /path/to/frontend/dist
|
||||
|
||||
# API 代理
|
||||
ProxyPass /api http://localhost:8000/api
|
||||
ProxyPassReverse /api http://localhost:8000/api
|
||||
|
||||
# WebSocket 代理
|
||||
ProxyPass /ws ws://localhost:8000/ws
|
||||
ProxyPassReverse /ws ws://localhost:8000/ws
|
||||
|
||||
# 前端路由(SPA)
|
||||
<Directory /path/to/frontend/dist>
|
||||
Options Indexes FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
RewriteRule ^index\.html$ - [L]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . /index.html [L]
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
#### 方式3:使用 serve(开发/测试)
|
||||
|
||||
```bash
|
||||
# 安装 serve
|
||||
npm install -g serve
|
||||
|
||||
# 启动服务
|
||||
serve -s dist -l 3000
|
||||
```
|
||||
|
||||
## 环境配置
|
||||
|
||||
### 后端环境变量
|
||||
|
||||
| 变量名 | 说明 | 默认值 | 必需 |
|
||||
|--------|------|--------|------|
|
||||
| `SPRING_PROFILES_ACTIVE` | Spring Profile | `dev` | 否 |
|
||||
| `DB_URL` | 数据库连接 URL | - | 是(生产) |
|
||||
| `DB_USERNAME` | 数据库用户名 | `root` | 是(生产) |
|
||||
| `DB_PASSWORD` | 数据库密码 | - | 是(生产) |
|
||||
| `SERVER_PORT` | 服务器端口 | `8000` | 否 |
|
||||
| `POLYGON_RPC_URL` | Polygon RPC 地址 | `https://polygon-rpc.com` | 否 |
|
||||
| `JWT_SECRET` | JWT 密钥 | - | 是(生产) |
|
||||
| `ADMIN_RESET_PASSWORD_KEY` | 管理员密码重置密钥 | - | 是(生产) |
|
||||
|
||||
### 前端环境变量
|
||||
|
||||
| 变量名 | 说明 | 默认值 |
|
||||
|--------|------|--------|
|
||||
| `VITE_API_URL` | 后端 API 地址 | `http://127.0.0.1:8000` |
|
||||
| `VITE_WS_URL` | WebSocket 地址 | `ws://127.0.0.1:8000` |
|
||||
|
||||
### 配置文件说明
|
||||
|
||||
#### 后端配置文件
|
||||
|
||||
- `application.properties` - 基础配置(所有环境共享)
|
||||
- `application-dev.properties` - 开发环境配置
|
||||
- `application-prod.properties` - 生产环境配置
|
||||
|
||||
通过 `--spring.profiles.active=prod` 或环境变量 `SPRING_PROFILES_ACTIVE=prod` 切换环境。
|
||||
|
||||
#### 前端环境变量
|
||||
|
||||
Vite 使用 `.env.production` 文件在构建时注入环境变量。构建脚本会自动创建此文件。
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 1. 数据库连接失败
|
||||
|
||||
**问题**: 后端无法连接数据库
|
||||
|
||||
**解决方案**:
|
||||
- 检查数据库服务是否运行
|
||||
- 检查数据库连接 URL、用户名、密码是否正确
|
||||
- 检查防火墙是否允许连接
|
||||
- 对于 Docker 部署,确保使用正确的数据库地址(`mysql` 而非 `localhost`)
|
||||
|
||||
### 2. 前端无法连接后端
|
||||
|
||||
**问题**: 前端请求后端 API 失败
|
||||
|
||||
**解决方案**:
|
||||
- 检查后端服务是否运行
|
||||
- 检查 `VITE_API_URL` 配置是否正确
|
||||
- 检查 CORS 配置(如果跨域)
|
||||
- 检查网络连接和防火墙
|
||||
|
||||
### 3. WebSocket 连接失败
|
||||
|
||||
**问题**: WebSocket 无法建立连接
|
||||
|
||||
**解决方案**:
|
||||
- 检查 `VITE_WS_URL` 配置是否正确
|
||||
- 检查 WebSocket 代理配置(Nginx/Apache)
|
||||
- 检查防火墙是否允许 WebSocket 连接
|
||||
- 检查后端 WebSocket 服务是否正常
|
||||
|
||||
### 4. Docker 容器无法访问数据库
|
||||
|
||||
**问题**: Docker 容器中的后端无法连接宿主机数据库
|
||||
|
||||
**解决方案**:
|
||||
- 使用 `host.docker.internal` 作为数据库地址(Mac/Windows)
|
||||
- 使用 Docker 网络连接(推荐使用 docker-compose)
|
||||
- 检查数据库是否允许远程连接
|
||||
|
||||
### 5. 构建失败
|
||||
|
||||
**问题**: 前端或后端构建失败
|
||||
|
||||
**解决方案**:
|
||||
- 检查 Node.js 版本(需要 18+)
|
||||
- 检查 Java 版本(需要 17+)
|
||||
- 清理缓存后重新构建:
|
||||
```bash
|
||||
# 前端
|
||||
rm -rf node_modules dist
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
# 后端
|
||||
./gradlew clean build
|
||||
```
|
||||
|
||||
## 生产环境检查清单
|
||||
|
||||
- [ ] 修改所有默认密码和密钥(JWT_SECRET、ADMIN_RESET_PASSWORD_KEY、数据库密码)
|
||||
- [ ] 配置正确的数据库连接(使用 SSL)
|
||||
- [ ] 设置正确的 Spring Profile(`prod`)
|
||||
- [ ] 配置正确的后端 API 地址(前端)
|
||||
- [ ] 配置反向代理(Nginx/Apache)
|
||||
- [ ] 配置 HTTPS(生产环境推荐)
|
||||
- [ ] 配置防火墙规则
|
||||
- [ ] 设置日志轮转
|
||||
- [ ] 配置监控和告警
|
||||
- [ ] 定期备份数据库
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 后端
|
||||
|
||||
- 调整 JVM 参数(堆内存、GC 策略)
|
||||
- 配置数据库连接池大小
|
||||
- 启用 HTTP 压缩
|
||||
- 配置缓存策略
|
||||
|
||||
### 前端
|
||||
|
||||
- 启用 Gzip 压缩(Nginx)
|
||||
- 配置静态资源缓存
|
||||
- 使用 CDN 加速
|
||||
- 启用 HTTP/2
|
||||
|
||||
## 安全建议
|
||||
|
||||
- 使用 HTTPS(生产环境必须)
|
||||
- 配置 CORS 白名单
|
||||
- 定期更新依赖包
|
||||
- 使用强密码和密钥
|
||||
- 限制数据库访问权限
|
||||
- 配置防火墙规则
|
||||
- 定期备份数据
|
||||
- 监控异常访问
|
||||
|
||||
## 技术支持
|
||||
|
||||
如有问题,请提交 Issue 到 [GitHub](https://github.com/WrBug/PolyHermes) 或联系 [Twitter](https://x.com/quant_tr)。
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# 依赖
|
||||
node_modules/
|
||||
.pnpm-store/
|
||||
|
||||
# 构建产物
|
||||
dist/
|
||||
build/
|
||||
out/
|
||||
|
||||
# 环境配置
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.DS_Store
|
||||
|
||||
# 日志
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# 其他
|
||||
*.bak
|
||||
*.backup
|
||||
*.old
|
||||
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
#!/bin/bash
|
||||
|
||||
# PolyHermes 前端构建脚本
|
||||
# 支持自定义后端 API 地址
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 默认配置
|
||||
DEFAULT_API_URL="http://127.0.0.1:8000"
|
||||
API_URL="${VITE_API_URL:-$DEFAULT_API_URL}"
|
||||
|
||||
# 打印信息
|
||||
info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查 Node.js 环境
|
||||
check_node() {
|
||||
if ! command -v node &> /dev/null; then
|
||||
error "Node.js 未安装,请先安装 Node.js 18+"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
|
||||
if [ "$NODE_VERSION" -lt 18 ]; then
|
||||
error "Node.js 版本过低,需要 Node.js 18+,当前版本: $(node -v)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
info "Node.js 环境检查通过: $(node -v)"
|
||||
}
|
||||
|
||||
# 创建环境配置文件
|
||||
create_env_file() {
|
||||
info "创建环境配置文件..."
|
||||
|
||||
# 解析 API URL,提取协议、主机和端口
|
||||
if [[ $API_URL == http* ]]; then
|
||||
# 提取协议和主机
|
||||
PROTOCOL=$(echo $API_URL | sed -E 's|^([^:]+)://.*|\1|')
|
||||
HOST_PORT=$(echo $API_URL | sed -E 's|^[^:]+://([^/]+).*|\1|')
|
||||
HOST=$(echo $HOST_PORT | cut -d':' -f1)
|
||||
PORT=$(echo $HOST_PORT | cut -d':' -f2)
|
||||
|
||||
# 构建 WebSocket URL
|
||||
if [ "$PROTOCOL" = "https" ]; then
|
||||
WS_PROTOCOL="wss"
|
||||
else
|
||||
WS_PROTOCOL="ws"
|
||||
fi
|
||||
WS_URL="${WS_PROTOCOL}://${HOST}:${PORT}"
|
||||
else
|
||||
error "API URL 格式错误,应为 http://host:port 或 https://host:port"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建 .env.production 文件
|
||||
cat > .env.production <<EOF
|
||||
# 后端 API 地址
|
||||
VITE_API_URL=$API_URL
|
||||
VITE_WS_URL=$WS_URL
|
||||
EOF
|
||||
|
||||
info "环境配置已创建: .env.production"
|
||||
info " API URL: $API_URL"
|
||||
info " WebSocket URL: $WS_URL"
|
||||
}
|
||||
|
||||
# 构建应用
|
||||
build_app() {
|
||||
info "开始构建前端应用..."
|
||||
|
||||
# 检查依赖
|
||||
if [ ! -d "node_modules" ]; then
|
||||
info "安装依赖..."
|
||||
npm install
|
||||
fi
|
||||
|
||||
# 构建
|
||||
info "执行构建..."
|
||||
npm run build
|
||||
|
||||
if [ ! -d "dist" ]; then
|
||||
error "构建失败,dist 目录不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
info "构建完成: dist/"
|
||||
info "构建产物大小: $(du -sh dist | cut -f1)"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo "=========================================="
|
||||
echo " PolyHermes 前端构建脚本"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
check_node
|
||||
|
||||
# 解析参数
|
||||
if [ "$1" = "--api-url" ] && [ -n "$2" ]; then
|
||||
API_URL="$2"
|
||||
info "使用自定义 API 地址: $API_URL"
|
||||
elif [ -n "$VITE_API_URL" ]; then
|
||||
info "使用环境变量 API 地址: $API_URL"
|
||||
else
|
||||
info "使用默认 API 地址: $API_URL"
|
||||
warn "提示: 可通过环境变量 VITE_API_URL 或参数 --api-url 自定义后端地址"
|
||||
fi
|
||||
|
||||
create_env_file
|
||||
build_app
|
||||
|
||||
echo ""
|
||||
info "构建完成!"
|
||||
info "部署方式:"
|
||||
info " 1. 静态文件服务器:将 dist/ 目录部署到 Nginx、Apache 等"
|
||||
info " 2. 使用 serve 预览:npx serve -s dist -l 3000"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -5,9 +5,22 @@ import { wsManager } from './websocket'
|
||||
|
||||
/**
|
||||
* API 基础配置
|
||||
* 支持通过环境变量 VITE_API_URL 配置后端地址
|
||||
* 默认使用相对路径 /api(适用于同域部署)
|
||||
* 如果设置了 VITE_API_URL,则使用完整 URL
|
||||
*/
|
||||
const getBaseURL = (): string => {
|
||||
const envApiUrl = import.meta.env.VITE_API_URL
|
||||
if (envApiUrl) {
|
||||
// 如果设置了环境变量,使用完整 URL
|
||||
return `${envApiUrl}/api`
|
||||
}
|
||||
// 否则使用相对路径(适用于开发环境代理或同域部署)
|
||||
return '/api'
|
||||
}
|
||||
|
||||
const apiClient: AxiosInstance = axios.create({
|
||||
baseURL: '/api',
|
||||
baseURL: getBaseURL(),
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
|
||||
@@ -325,16 +325,28 @@ class WebSocketManager {
|
||||
|
||||
/**
|
||||
* 获取 WebSocket URL(带token认证)
|
||||
* 支持通过环境变量 VITE_WS_URL 配置 WebSocket 地址
|
||||
*/
|
||||
private getWebSocketUrl(): string {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
const host = window.location.host
|
||||
const envWsUrl = import.meta.env.VITE_WS_URL
|
||||
let wsBaseUrl: string
|
||||
|
||||
if (envWsUrl) {
|
||||
// 如果设置了环境变量,使用完整 URL
|
||||
wsBaseUrl = envWsUrl
|
||||
} else {
|
||||
// 否则使用相对路径(适用于开发环境代理或同域部署)
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
const host = window.location.host
|
||||
wsBaseUrl = `${protocol}//${host}`
|
||||
}
|
||||
|
||||
const token = this.getToken()
|
||||
if (token) {
|
||||
// 通过查询参数传递token
|
||||
return `${protocol}//${host}/ws?token=${encodeURIComponent(token)}`
|
||||
return `${wsBaseUrl}/ws?token=${encodeURIComponent(token)}`
|
||||
}
|
||||
return `${protocol}//${host}/ws`
|
||||
return `${wsBaseUrl}/ws`
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_API_URL?: string
|
||||
readonly VITE_WS_URL?: string
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
}
|
||||
|
||||
+29
-14
@@ -1,21 +1,36 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8000',
|
||||
changeOrigin: true
|
||||
},
|
||||
'/ws': {
|
||||
target: 'ws://localhost:8000',
|
||||
ws: true,
|
||||
changeOrigin: true
|
||||
export default defineConfig(({ mode }) => {
|
||||
// 加载环境变量
|
||||
const env = loadEnv(mode, process.cwd(), '')
|
||||
|
||||
// 从环境变量获取 API 地址,默认使用 localhost:8000
|
||||
const API_URL = env.VITE_API_URL || 'http://localhost:8000'
|
||||
const WS_URL = env.VITE_WS_URL || 'ws://localhost:8000'
|
||||
|
||||
return {
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: API_URL,
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, '/api')
|
||||
},
|
||||
'/ws': {
|
||||
target: WS_URL,
|
||||
ws: true,
|
||||
changeOrigin: true
|
||||
}
|
||||
}
|
||||
},
|
||||
// 定义环境变量,在构建时注入
|
||||
define: {
|
||||
'import.meta.env.VITE_API_URL': JSON.stringify(API_URL),
|
||||
'import.meta.env.VITE_WS_URL': JSON.stringify(WS_URL)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user