diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 0000000..74bfb80 --- /dev/null +++ b/docker/.dockerignore @@ -0,0 +1,64 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# 虚拟环境 +venv/ +env/ +ENV/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# 日志和缓存 +logs/ +*.log +.cache/ + +# 数据文件 +data/ +*.csv +*.xlsx + +# 临时文件 +.DS_Store +Thumbs.db + +# Git +.git/ +.gitignore + +# Docker +docker/ +Dockerfile +docker-compose*.yml +.dockerignore + +# 文档 +README.md +docs/ +*.txt +*.png +*.jpg +*.jpeg \ No newline at end of file diff --git a/docker/DEPLOYMENT.md b/docker/DEPLOYMENT.md new file mode 100644 index 0000000..603d2df --- /dev/null +++ b/docker/DEPLOYMENT.md @@ -0,0 +1,197 @@ +# Stock Monitor Docker部署指南 + +## 快速开始 + +### 1. 环境要求 +- Docker 20.10+ +- Docker Compose 1.29+ +- 4GB+ 可用内存 +- 10GB+ 可用磁盘空间 + +### 2. 配置环境变量 +```bash +# 复制环境变量文件到项目根目录 +cp ../.env.example ../.env +# 编辑.env文件,设置必要的配置参数 +``` + +### 3. 快速部署 +```bash +# 进入docker目录 +cd docker + +# 使用部署脚本 +./deploy.sh + +# 或者手动部署 +docker-compose up -d +``` + +### 4. 访问应用 +- 应用地址: http://localhost:8000 +- API文档: http://localhost:8000/docs + +## 部署模式 + +### 开发模式 +```bash +cd docker +docker-compose up -d +``` +包含服务: +- stock-monitor (主应用) +- redis (可选缓存) +- postgres (可选数据库) + +### 生产模式 +```bash +cd docker +docker-compose -f docker-compose.prod.yml up -d +``` +包含服务: +- stock-monitor (主应用) +- redis (缓存) +- postgres (数据库) +- nginx (反向代理) + +## 配置说明 + +### 环境变量 +| 变量名 | 说明 | 默认值 | +|--------|------|--------| +| TUSHARE_TOKEN | Tushare API令牌 | 必填 | +| DB_HOST | 数据库主机 | postgres | +| DB_PORT | 数据库端口 | 5432 | +| DB_NAME | 数据库名称 | stock_monitor | +| DB_USER | 数据库用户 | stock_user | +| DB_PASSWORD | 数据库密码 | stock_password | +| REDIS_HOST | Redis主机 | redis | +| REDIS_PORT | Redis端口 | 6379 | + +### 端口映射 +| 服务 | 容器端口 | 主机端口 | +|------|----------|----------| +| stock-monitor | 8000 | 8000 | +| redis | 6379 | 6379 | +| postgres | 5432 | 5432 | +| nginx | 80/443 | 80/443 | + +## 数据持久化 + +### 卷映射 +- `../logs:/app/logs` - 应用日志 +- `../data:/app/data` - 数据文件 +- `../config.json:/app/config.json` - 配置文件 +- `postgres_data:/var/lib/postgresql/data` - 数据库数据 +- `redis_data:/data` - Redis数据 + +### 备份策略 +```bash +# 备份数据库 +docker exec stock-postgres pg_dump -U stock_user stock_monitor > backup.sql + +# 备份Redis +docker exec stock-redis redis-cli save +docker cp stock-redis:/data/dump.rdb ./redis_backup.rdb +``` + +## 监控和维护 + +### 查看日志 +```bash +# 查看所有服务日志 +docker-compose logs -f + +# 查看特定服务日志 +docker-compose logs -f stock-monitor +``` + +### 性能监控 +```bash +# 查看容器资源使用 +docker stats + +# 查看容器状态 +docker-compose ps +``` + +### 更新应用 +```bash +# 拉取最新镜像 +docker-compose pull + +# 重新部署 +docker-compose up -d + +# 清理旧镜像 +docker image prune -f +``` + +## 故障排查 + +### 常见问题 + +1. **容器启动失败** +```bash +# 查看详细日志 +docker-compose logs [service-name] + +# 检查配置文件 +ls -la ../config.json ../.env +``` + +2. **数据库连接失败** +```bash +# 检查数据库状态 +docker-compose exec postgres pg_isready -U stock_user + +# 检查网络连接 +docker-compose exec stock-monitor ping postgres +``` + +3. **端口冲突** +```bash +# 检查端口占用 +netstat -tulpn | grep :8000 + +# 修改端口映射 +# 编辑docker-compose.yml文件 +``` + +### 健康检查 +```bash +# 检查服务健康状态 +curl http://localhost:8000/health + +# 检查数据库连接 +docker-compose exec stock-monitor python -c "import psycopg2; psycopg2.connect(host='postgres', user='stock_user', password='stock_password', database='stock_monitor')" +``` + +## 安全建议 + +1. **修改默认密码** + - 修改数据库密码 + - 修改Redis密码 + - 修改应用密钥 + +2. **配置SSL证书** + - 将证书文件放置在`./ssl/`目录 + - 配置nginx.conf文件 + +3. **限制访问** + - 配置防火墙规则 + - 使用VPN访问 + - 配置访问白名单 + +## 卸载 + +```bash +# 停止并删除所有容器 +docker-compose down + +# 删除数据卷(谨慎操作) +docker-compose down -v + +# 删除镜像 +docker image rm docker_stock-monitor +``` \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..f737eba --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,32 @@ +# 使用Python 3.11基础镜像 +FROM python:3.11-slim + +# 设置工作目录 +WORKDIR /app + +# 安装系统依赖 +RUN apt-get update && apt-get install -y \ + gcc \ + g++ \ + && rm -rf /var/lib/apt/lists/* + +# 复制依赖文件 +COPY requirements.txt . + +# 安装Python依赖 +RUN pip install --no-cache-dir -r requirements.txt + +# 复制项目文件 +COPY . . + +# 创建必要的目录 +RUN mkdir -p logs data + +# 暴露端口 +EXPOSE 8000 + +# 设置环境变量 +ENV PYTHONUNBUFFERED=1 + +# 运行应用 +CMD ["python", "run.py"] \ No newline at end of file diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..7bb8ed3 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,97 @@ +# Docker部署配置 + +本目录包含Stock Monitor项目的Docker部署配置文件。 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `Dockerfile` | 主应用镜像构建文件 | +| `docker-compose.yml` | 开发环境部署配置 | +| `docker-compose.prod.yml` | 生产环境部署配置 | +| `nginx.conf` | Nginx反向代理配置 | +| `redis.conf` | Redis缓存配置 | +| `deploy.sh` | 自动化部署脚本 | +| `.dockerignore` | Docker构建忽略文件 | +| `DEPLOYMENT.md` | 详细部署指南 | + +## 快速部署 + +### 开发环境 +```bash +# 进入docker目录 +cd docker + +# 启动服务 +docker-compose up -d +``` + +### 生产环境 +```bash +# 进入docker目录 +cd docker + +# 启动生产环境服务 +docker-compose -f docker-compose.prod.yml up -d +``` + +### 使用部署脚本 +```bash +# 进入docker目录 +cd docker + +# 执行部署脚本(Windows请使用Git Bash或WSL) +./deploy.sh +``` + +## 目录结构 +``` +docker/ +├── Dockerfile # 主应用镜像构建 +├── docker-compose.yml # 开发环境配置 +├── docker-compose.prod.yml # 生产环境配置 +├── nginx.conf # Nginx配置 +├── redis.conf # Redis配置 +├── deploy.sh # 部署脚本 +├── .dockerignore # 构建忽略文件 +├── DEPLOYMENT.md # 详细部署指南 +└── README.md # 本文件 +``` + +## 注意事项 + +1. **环境变量配置**:部署前请确保在项目根目录配置`.env`文件 +2. **数据持久化**:日志和数据文件会保存在项目根目录的`logs/`和`data/`目录 +3. **端口冲突**:请确保8000、6379、5432端口未被占用 +4. **权限问题**:Linux/macOS系统需要给部署脚本执行权限 + +## 服务说明 + +### 基础服务 +- **stock-monitor**: 主应用服务(端口8000) +- **redis**: 缓存服务(端口6379) +- **postgres**: 数据库服务(端口5432) + +### 生产环境附加服务 +- **nginx**: 反向代理服务(端口80/443) + +## 维护命令 + +```bash +# 查看服务状态 +docker-compose ps + +# 查看日志 +docker-compose logs -f [服务名] + +# 停止服务 +docker-compose down + +# 重启服务 +docker-compose restart + +# 更新镜像 +docker-compose pull && docker-compose up -d +``` + +详细部署指南请参考 [DEPLOYMENT.md](DEPLOYMENT.md) \ No newline at end of file diff --git a/docker/deploy.sh b/docker/deploy.sh new file mode 100644 index 0000000..719dc71 --- /dev/null +++ b/docker/deploy.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# Stock Monitor Docker部署脚本 + +set -e + +echo "开始部署Stock Monitor..." + +# 检查Docker和Docker Compose是否安装 +if ! command -v docker &> /dev/null; then + echo "错误: Docker未安装,请先安装Docker" + exit 1 +fi + +if ! command -v docker-compose &> /dev/null; then + echo "错误: Docker Compose未安装,请先安装Docker Compose" + exit 1 +fi + +# 创建必要的目录 +echo "创建必要的目录..." +mkdir -p ../logs ../data ../ssl + +# 检查配置文件 +if [ ! -f "../.env" ]; then + echo "创建.env文件..." + cp ../.env.example ../.env + echo "请编辑.env文件,设置必要的配置参数" +fi + +# 构建和启动服务 +echo "构建Docker镜像..." +docker-compose build + +echo "启动服务..." +docker-compose up -d + +# 等待服务启动 +echo "等待服务启动..." +sleep 10 + +# 检查服务状态 +echo "检查服务状态..." +docker-compose ps + +# 显示访问信息 +echo "" +echo "部署完成!" +echo "应用地址: http://localhost:8000" +echo "" +echo "常用命令:" +echo " 查看日志: docker-compose logs -f" +echo " 停止服务: docker-compose down" +echo " 重启服务: docker-compose restart" +echo " 更新服务: docker-compose pull && docker-compose up -d" \ No newline at end of file diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml new file mode 100644 index 0000000..e2b10cd --- /dev/null +++ b/docker/docker-compose.prod.yml @@ -0,0 +1,83 @@ +version: '3.8' + +services: + stock-monitor: + build: + context: .. + dockerfile: docker/Dockerfile + container_name: stock-monitor-prod + ports: + - "8000:8000" + volumes: + - ../logs:/app/logs + - ../data:/app/data + - ../config.json:/app/config.json + environment: + - PYTHONUNBUFFERED=1 + - DEBUG=false + restart: always + depends_on: + - postgres + - redis + networks: + - stock-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + redis: + image: redis:7-alpine + container_name: stock-redis-prod + ports: + - "127.0.0.1:6379:6379" + volumes: + - redis_data:/data + - ./redis.conf:/usr/local/etc/redis/redis.conf + command: redis-server /usr/local/etc/redis/redis.conf + restart: always + networks: + - stock-network + + postgres: + image: postgres:15-alpine + container_name: stock-postgres-prod + ports: + - "127.0.0.1:5432:5432" + environment: + POSTGRES_DB: stock_monitor + POSTGRES_USER: stock_user + POSTGRES_PASSWORD: stock_password + POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./init.sql:/docker-entrypoint-initdb.d/init.sql + restart: always + networks: + - stock-network + + # Nginx反向代理 + nginx: + image: nginx:alpine + container_name: stock-nginx + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + - ./ssl:/etc/nginx/ssl + depends_on: + - stock-monitor + restart: always + networks: + - stock-network + +networks: + stock-network: + driver: bridge + +volumes: + redis_data: + postgres_data: \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..f23aeac --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,55 @@ +version: '3.8' + +services: + stock-monitor: + build: + context: .. + dockerfile: docker/Dockerfile + container_name: stock-monitor + ports: + - "8000:8000" + volumes: + - ../logs:/app/logs + - ../data:/app/data + - ../config.json:/app/config.json + environment: + - PYTHONUNBUFFERED=1 + restart: unless-stopped + networks: + - stock-network + + # 可选:添加Redis缓存服务 + redis: + image: redis:7-alpine + container_name: stock-redis + ports: + - "6379:6379" + volumes: + - redis_data:/data + restart: unless-stopped + networks: + - stock-network + + # 可选:添加PostgreSQL数据库 + postgres: + image: postgres:15-alpine + container_name: stock-postgres + ports: + - "5432:5432" + environment: + POSTGRES_DB: stock_monitor + POSTGRES_USER: stock_user + POSTGRES_PASSWORD: stock_password + volumes: + - postgres_data:/var/lib/postgresql/data + restart: unless-stopped + networks: + - stock-network + +networks: + stock-network: + driver: bridge + +volumes: + redis_data: + postgres_data: \ No newline at end of file diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..92401e3 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,73 @@ +events { + worker_connections 1024; +} + +http { + upstream stock-monitor { + server stock-monitor:8000; + } + + # HTTP服务器配置 + server { + listen 80; + server_name localhost; + + # 重定向到HTTPS + return 301 https://$server_name$request_uri; + } + + # HTTPS服务器配置 + server { + listen 443 ssl http2; + 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; + + # 安全头 + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; + + # Gzip压缩 + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + # 静态文件缓存 + location /static/ { + alias /app/static/; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # API代理 + location /api/ { + proxy_pass http://stock-monitor; + 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 / { + proxy_pass http://stock-monitor; + 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; + } + } +} \ No newline at end of file diff --git a/docker/redis.conf b/docker/redis.conf new file mode 100644 index 0000000..44bc019 --- /dev/null +++ b/docker/redis.conf @@ -0,0 +1,40 @@ +# Redis生产环境配置 + +# 网络配置 +bind 0.0.0.0 +port 6379 + +# 内存配置 +maxmemory 256mb +maxmemory-policy allkeys-lru + +# 持久化配置 +save 900 1 +save 300 10 +save 60 10000 +rdbcompression yes +rdbchecksum yes + +# 安全配置 +requirepass redis_password_here + +# 日志配置 +loglevel notice +logfile "" + +# 性能优化 +tcp-keepalive 300 +timeout 0 +tcp-backlog 511 + +# 客户端配置 +maxclients 10000 + +# AOF配置 +appendonly yes +appendfilename "appendonly.aof" +appendfsync everysec + +# 慢查询日志 +slowlog-log-slower-than 10000 +slowlog-max-len 128 \ No newline at end of file