容器化改造

This commit is contained in:
zlt 2026-07-27 16:02:43 +08:00
parent dc96db734f
commit ec8fb48977
7 changed files with 177 additions and 2 deletions

7
.dockerignore Normal file
View File

@ -0,0 +1,7 @@
.git
.idea
__pycache__
*.pyc
.env
logs
.DS_Store

25
.env.example Normal file
View File

@ -0,0 +1,25 @@
# tradingSystem (PMS) 环境变量模板
# 服务器部署: cp .env.example .env 后填入真实值。.env 已在 .gitignore, 绝不入库。
# 键名与 bionic_trader 对齐, 同一台服务器两系统可参照同一套连接信息。
# 业务参数 (PMS_TOTAL_SCALE 等) 不必写在这里 —— settings.py 有初值,
# 上线后经管理页面调整并持久化到 pms_runtime_param 表。
# ---- 153 代理 (pms_* 全部表 + trading_* + strategy_daily_results, 严格单表访问) ----
PROXY_DB_URL=mysql+pymysql://用户:密码@192.168.16.153:3307/my_quant_db
# ---- 因子分表库 (gp_stock_factor_pro_*, 自算参考位用) ----
SOURCE_DB_EXT_DSN=mysql+pymysql://用户:密码@192.168.16.150:3306/factordb_mysql
# ---- 大盘指数库 (zs_day_data, 页面区制提示用) ----
DB_MYSQL_URL=mysql+pymysql://用户:密码@192.168.18.199:3306/db_gp_cj
# ---- 信号/行情 Redis (208: 决策系统信号流 db2/db3 订阅 + 实时行情 db13) ----
SIGNAL_REDIS_HOST=192.168.18.208
SIGNAL_REDIS_PORT=6379
SIGNAL_REDIS_PASSWORD=密码
# ---- PMS 自己的 Celery 总线 (150 Redis, db8; 决策系统用 db7, 逻辑隔离) ----
PMS_REDIS_URL=redis://:密码@192.168.16.150:6379/8
# ---- 管理页面 ----
PMS_WEB_PORT=38100

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# 机密: 数据库/Redis 连接串与密码, 绝不入库 (服务器上手工维护, 参照 .env.example)
.env
__pycache__/
*.pyc
logs/
.DS_Store
# PyCharm 工程文件目前已跟踪; 如决定不入库, 取消下行注释并执行:
# git rm -r --cached .idea && git commit -m "untrack .idea"
#.idea/

27
Dockerfile Normal file
View File

@ -0,0 +1,27 @@
# tradingSystem (PMS) 运行镜像
# 三个服务 (pms-web / pms-beat / pms-worker) 共用本镜像, 由 docker-compose 以不同 command 启动
FROM python:3.11-slim
ENV TZ=Asia/Shanghai \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# 国内构建默认走清华 PyPI 镜像; 网络环境不同可覆盖:
# docker compose build --build-arg PIP_INDEX_URL=https://pypi.org/simple
ARG PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
WORKDIR /app
# 依赖层单独 COPY, 代码改动不触发重装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -i ${PIP_INDEX_URL} -r requirements.txt
COPY . .
RUN mkdir -p /app/logs
# 默认命令 = 管理页面; beat/worker 由 compose 覆盖 command
CMD ["uvicorn", "app.web.main:app", "--host", "0.0.0.0", "--port", "38100"]

View File

@ -23,9 +23,31 @@
2. **分工不越权**:持仓系统管「做什么、多少」,决策系统管「该不该、何时」,下游只管执行;研判不可用时降级为保守规则 + 人工确认,不自建第二套研判。
3. **先记账后动作 + 故障即守成**:指令先落表再下发;故障不产生新指令;账本与下游定期对账,以下游为实际持仓事实源。
## Docker 部署(项目统一以容器方式构建运行)
服务共用一个镜像:`pms-web`(管理页面,端口 38100+ `pms-beat` / `pms-worker`Celery 调度与执行,挂在 `sched` profile 下,调度器代码就绪后启用)。
```bash
# 服务器首次部署
git clone <仓库地址> && cd tradingSystem
cp .env.example .env && vim .env # 填入真实连接串 (.env 不入库)
docker compose build # 默认走清华 PyPI 镜像; 可 --build-arg PIP_INDEX_URL=... 覆盖
docker compose run --rm pms-web python scripts/test_core_units.py # 构建验证: 应输出 ALL PASS (14 cases)
docker compose up -d # 当前仅启动 pms-web
curl http://127.0.0.1:38100/health # 健康检查 + 配置装载自证
# 调度器代码就绪后
docker compose --profile sched up -d
# 日常更新
git pull && docker compose build && docker compose up -d
```
基础镜像 `python:3.11-slim` 拉取慢时,先给服务器 Docker 配置 registry 镜像加速。日志落 `./logs`(已挂载卷);容器时区 Asia/Shanghai。
## 开发约定
- 开发机与服务器经 git 同步代码;测试脚本由用户在实机运行,结果回传后迭代。
- 开发机与服务器经 git 同步代码;**构建与运行统一走 Docker**`docker compose build` → 容器内跑测试脚本 → `up -d`),测试结果回传后迭代。
- 153 代理侧数据库严格单表访问;持仓系统内部代码统一 Tushare 点式。
- 配置全部在 `config/settings.py` 显式声明字段;参数可经管理页面在线修改并持久化。
- 配置分两层:基础设施连接串在 `.env`(服务器手工维护,不入库,模板见 `.env.example`);业务参数在 `config/settings.py` 只是初值,上线后经管理页面修改并持久化到 `pms_runtime_param`
- 里程碑(设计定稿、建表、各期上线)及时 git 提交。

38
app/web/main.py Normal file
View File

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
"""
PMS 管理页面 · Web 入口 (当前为最小骨架)
==========================================
现阶段职责: pms-web 容器可启动可健康检查, 验证 Docker 构建与配置装载链路
后续在此基础上扩展四块页面 (POSITION_MGMT_DESIGN.md §3.3):
参数设置 / 命令台 / 持仓与账本 / 提议确认
"""
from fastapi import FastAPI
from config.settings import settings
VERSION = "0.1.0-dev"
app = FastAPI(title="PMS 持仓管理系统", version=VERSION)
@app.get("/health")
def health():
"""容器健康检查 + 配置装载自证 (不连库, 只回显关键初值)。"""
return {
"status": "ok",
"version": VERSION,
"service": "pms-web",
"config_loaded": {
"total_scale": settings.PMS_TOTAL_SCALE,
"portfolio_cap": settings.PMS_PORTFOLIO_CAP,
"stock_cap": settings.PMS_STOCK_CAP,
"max_names": settings.PMS_MAX_NAMES,
"autonomy": settings.PMS_AUTONOMY,
"web_port": settings.PMS_WEB_PORT,
},
}
@app.get("/")
def index():
return {"hint": "PMS 管理页面骨架。健康检查: /health ; 页面四块随后续开发接入。"}

45
docker-compose.yml Normal file
View File

@ -0,0 +1,45 @@
# tradingSystem (PMS) 容器编排
# 用法见 README「Docker 部署」。.env 放在本文件同目录 (服务器上手工维护, 不入库)。
# 当前默认只启动 pms-web; pms-beat / pms-worker 挂在 sched profile 下,
# 调度器代码 (app/scheduler.py) 就绪后用 --profile sched 启用。
x-pms-base: &pms-base
build: .
image: pms:latest
env_file: .env
environment:
- TZ=Asia/Shanghai
volumes:
- ./logs:/app/logs
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"
services:
pms-web:
<<: *pms-base
container_name: pms-web
command: uvicorn app.web.main:app --host 0.0.0.0 --port 38100
ports:
- "38100:38100"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:38100/health', timeout=3)"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
pms-beat:
<<: *pms-base
container_name: pms-beat
profiles: ["sched"]
command: celery -A app.scheduler.celery_app beat -l info
pms-worker:
<<: *pms-base
container_name: pms-worker
profiles: ["sched"]
command: celery -A app.scheduler.celery_app worker -l info -c 2