feat: 添加Nginx反代支持

This commit is contained in:
CaasianVale
2025-03-09 17:10:11 +08:00
parent 9ae1e60f7a
commit 3421e32ac1
5 changed files with 246 additions and 23 deletions

View File

@@ -76,6 +76,7 @@ jobs:
with:
sparse-checkout: |
docker-compose.prod.yml
nginx/nginx.conf
- name: Create .env file for deployment
run: |
@@ -110,13 +111,29 @@ jobs:
fi
fi
# 创建nginx目录和日志目录如果不存在
mkdir -p ${DEPLOY_PATH}/nginx
mkdir -p ${DEPLOY_PATH}/nginx/logs
mkdir -p ${DEPLOY_PATH}/nginx/ssl
# 如果SSL证书不存在创建自签名证书仅用于测试
if [ ! -f ${DEPLOY_PATH}/nginx/ssl/cert.pem ] || [ ! -f ${DEPLOY_PATH}/nginx/ssl/key.pem ]; then
echo "SSL证书不存在创建自签名证书..."
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ${DEPLOY_PATH}/nginx/ssl/key.pem \
-out ${DEPLOY_PATH}/nginx/ssl/cert.pem \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
echo "自签名证书创建完成"
fi
- name: Copy files to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "docker-compose.prod.yml,.env"
source: "docker-compose.prod.yml,.env,nginx/nginx.conf"
target: ${{ secrets.DEPLOY_PATH }}
overwrite: true
@@ -139,7 +156,7 @@ jobs:
sleep 10
# 验证服务是否正常运行
if ! curl -s http://localhost:8888/api/config > /dev/null; then
if ! curl -s -k https://localhost:443 > /dev/null && ! curl -s http://localhost:80 > /dev/null; then
echo "服务未正常运行!"
exit 1
fi

View File

@@ -1,33 +1,41 @@
# 股票分析系统 (Stock Analysis System)
## 简介
基于 https://github.com/DR-lin-eng/stock-scanner 二次修改,感谢原作者
## 功能变更
1. 增加html页面支持浏览器在线使用。
2. 增加港股、美股支持。
3. 完善Dockerfile、GitHub Actions 支持docker一键部署使用。
1. 增加html页面支持浏览器在线使用
2. 增加港股、美股支持
3. 完善Dockerfile、GitHub Actions 支持docker一键部署使用
4. 支持x86_64 和 ARM64架构镜像
5. 支持流式输出支持前端传入Key(仅作为本地用户使用,日志等内容不会输出) 感谢@Cassianvale
6. 重构为Vue3+Vite+TS+Naive UI支持响应式布局
7. 支持GitHub Actions 一键部署
8. 支持Nginx反向代理可通过80/443端口访问
## Docker镜像一键部署
## docker一键部署
```
# 拉取最新版本
docker pull cassianvale/stock-scanner:latest
# 启动容器
docker run -d \
--name stock-scanner \
--name stock-scanner-app \
-p 8888:8888 \
-e API_KEY=替换为你的key \
-e API_URL=替换为你的api地址 \
-e API_MODEL=替换为你的模型 \
-e API_TIMEOUT=60 \
-e LOGIN_PASSWORD=替换为你的密码 \
lanzhihong/stock-scanner:latest
-e API_KEY=你的API密钥 \
-e API_URL=你的API地址 \
-e API_MODEL=你的API模型 \
-e API_TIMEOUT=超时时间(默认60秒) \
-e LOGIN_PASSWORD=登录密码(可选) \
-e ANNOUNCEMENT_TEXT=公告文本 \
-v $(pwd)/logs:/app/logs \
--restart unless-stopped \
--network bridge \
cassianvale/stock-scanner:latest
API_TIMEOUT=60 202503040712版本开始 (AI分析发生错误查看日志是否有timed out类似错误需要增加你的API超时时间)
LOGIN_PASSWORD 为空时,表示不需要登录,否则需要经过登录接口验证
注意⚠️: 环境变量名变更,更新版本后需要调整!!!
针对API_URL处理兼容更多的api地址规则与Cherry Studio一致 /结尾忽略v1版本#结尾强制使用输入地址。
API_URL 处理逻辑说明:
@@ -46,7 +54,54 @@ API_URL 处理逻辑说明:
```
默认8888端口部署完成后访问 http://127.0.0.1:8888 即可使用。
默认8888端口部署完成后访问 http://你的域名或ip:8888 即可使用
## 使用Nginx反向代理
项目已集成Nginx服务可以通过80端口(HTTP)和443端口(HTTPS)访问应用
使用docker-compose启动
```
# 克隆仓库
git clone https://github.com/your-username/stock-scanner.git
cd stock-scanner
# 创建.env文件并填写必要的环境变量
cat > .env << EOL
API_KEY=你的API密钥
API_URL=你的API地址
API_MODEL=你的API模型
API_TIMEOUT=超时时间(默认60秒)
LOGIN_PASSWORD=登录密码(可选)
ANNOUNCEMENT_TEXT=公告文本
EOL
# 创建SSL证书目录
mkdir -p nginx/ssl
# 生成自签名SSL证书仅用于测试环境
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout nginx/ssl/key.pem \
-out nginx/ssl/cert.pem \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
# 启动服务
docker-compose up -d
```
启动后可通过以下方式访问应用:
- HTTP: http://你的域名或ip
- HTTPS: https://你的域名或ip
### 使用自己的SSL证书
如果您有自己的SSL证书可以替换自签名证书
1. 将您的证书文件放在 `nginx/ssl/` 目录下
2. 确保证书文件命名为 `cert.pem`,私钥文件命名为 `key.pem`
3. 重启服务: `docker-compose restart nginx`
## Github Actions 部署
@@ -65,6 +120,7 @@ API_URL 处理逻辑说明:
- 股票分析仅供参考,不构成投资建议
- 使用前请确保网络连接正常
- 建议在实盘前充分测试
- 使用HTTPS可以提高数据传输的安全性
## 贡献 (Contributing)
欢迎提交 issues 和 pull requests

View File

@@ -39,6 +39,41 @@ services:
networks:
- stock-scanner-network
nginx:
image: nginx:stable-alpine
container_name: stock-scanner-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/ssl:/etc/nginx/ssl
depends_on:
- app
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.1'
memory: 128M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
- stock-scanner-network
networks:
stock-scanner-network:
driver: bridge

View File

@@ -27,6 +27,28 @@ services:
networks:
- stock-scanner-network
nginx:
image: nginx:stable-alpine
container_name: stock-scanner-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/ssl:/etc/nginx/ssl
depends_on:
- app
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
networks:
- stock-scanner-network
networks:
stock-scanner-network:
driver: bridge

93
nginx/nginx.conf Normal file
View File

@@ -0,0 +1,93 @@
server {
listen 80;
listen 443 ssl;
server_name localhost;
# SSL证书配置
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 日志配置
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# 设置较大的客户端请求体大小限制,以支持上传文件
client_max_body_size 20M;
# 设置超时时间
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
# 启用gzip压缩
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/javascript
application/json
application/x-javascript
application/xml
application/xml+rss
image/svg+xml
text/css
text/javascript
text/plain
text/xml;
# 反向代理到应用服务
location / {
proxy_pass http://app:8888;
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;
# WebSocket支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 安全相关头信息
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options SAMEORIGIN;
add_header Referrer-Policy strict-origin-when-cross-origin;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
# API请求处理
location /api/ {
proxy_pass http://app:8888;
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;
# WebSocket支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 静态文件缓存设置
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
proxy_pass http://app:8888;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
add_header X-Content-Type-Options nosniff;
}
}