Files
sanguo_quant_live/jiangwei-platform/research/nas-docker-deployment-20260326/final/sanguo_vnpy群晖Docker部署可行性调研报告.md
T
2026-04-11 09:00:02 +08:00

39 KiB
Raw Blame History

sanguo_vnpy群晖NAS Docker部署可行性调研报告

一、方案整体可行性分析

核心原则

尽量使用原生vnpy框架模块,不仿写,不重写,尽量适配

  • 优先使用vnpy官方提供的组件,避免重复造轮子
  • 对于不满足需求的功能,优先考虑扩展和适配,而非完全重写
  • 保持与vnpy官方架构的兼容性,便于后续升级和维护
  • 只在官方组件无法满足核心需求时,才考虑自定义实现

1.1 技术可行性: 完全可行

基于以下因素,将sanguo_vnpy部署在群晖NAS Docker容器中是完全可行的:

  1. 群晖NAS Docker支持

    • 群晖DSM系统原生支持DockerContainer Manager
    • 支持x86和ARM架构(需根据NAS型号选择对应镜像)
    • 提供图形化界面管理容器,操作便捷
  2. vn.py兼容性

    • vn.pyVeighNa)支持Linux系统
    • 支持Python 3.10+Docker环境易于配置
    • 提供web_trader模块,支持B/S架构访问
    • 支持多种数据库(SQLite、MySQL、PostgreSQL等)
  3. 完全存算一体架构优势

    • 数据存储在NAS本地,访问速度快
    • 计算资源与存储资源一体化,减少网络开销
    • Mac mini仅作为远程终端,大幅节省本地存储空间
    • 便于备份和迁移,所有数据和环境统一管理

1.2 新架构设计:完全迁移到NAS

架构对比

项目 旧架构(Mac mini 新架构(NAS Docker
数据存储位置 Mac mini本地 NAS本地存储
代码运行位置 Mac mini本地 NAS Docker容器
回测环境 Mac mini本地 NAS Docker容器
Mac mini作用 主力开发机 纯远程访问终端
Mac mini存储占用 大(几十GB+ 极小(仅浏览器/VSCode
数据备份 需单独配置 NAS统一备份

新架构优势

  1. 彻底释放Mac mini空间

    • 数据、代码、环境全部在NAS上
    • Mac mini只需保留浏览器和VSCode
    • 本地存储占用从几十GB降至几百MB
  2. 统一管理,易于维护

    • 所有数据集中在NAS,便于备份
    • 环境配置一次,处处可用
    • 升级、迁移更简单
  3. 7×24小时稳定运行

    • NAS低功耗设计,适合长期运行
    • 支持UPS断电保护
    • 群晖系统稳定可靠
  4. 灵活的远程访问

    • 局域网内访问速度快,延迟低
    • 支持VPN远程访问(如需要)
    • 多种访问方式:Jupyter、VSCode、Web界面

1.3 适用场景

场景 推荐度 说明
策略回测研究 非常适合,可利用NAS闲置资源
实盘交易 可行,但需考虑网络稳定性和安全性
数据管理 极佳,NAS本身就是数据存储专家
团队协作 支持多用户访问,便于协作
Mac mini空间节省 核心目标,完全实现

二、完整部署方案详解

2.1 整体架构设计

┌─────────────────────────────────────────────────────────────┐
│                        局域网环境                              │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  ┌──────────────────┐         ┌─────────────────────────┐   │
│  │   Mac mini       │         │    群晖NAS (192.168.2.154)│   │
│  │                  │         │                         │   │
│  │  ┌────────────┐  │         │  ┌───────────────────┐  │   │
│  │  │  浏览器    │  │  HTTP   │  │                   │  │   │
│  │  │  VSCode    │  │◄───────►│  │  Docker容器      │  │   │
│  │  │  (远程)    │  │         │  │                   │  │   │
│  │  └────────────┘  │         │  │  ┌─────────────┐ │  │   │
│  │                  │         │  │  │ vn.py环境    │ │  │   │
│  │  本地存储占用:    │         │  │  └─────────────┘ │  │   │
│  │  < 1GB            │         │  │                   │  │   │
│  └──────────────────┘         │  │  ┌─────────────┐ │  │   │
│                                 │  │  │ Jupyter Lab │ │  │   │
│                                 │  │  └─────────────┘ │  │   │
│                                 │  │                   │  │   │
│                                 │  │  ┌─────────────┐ │  │   │
│                                 │  │  │ VSCode Server││  │   │
│                                 │  │  └─────────────┘ │  │   │
│                                 │  │                   │  │   │
│                                 │  └───────────────────┘  │   │
│                                 │                           │   │
│                                 │  ┌───────────────────┐  │   │
│                                 │  │   NAS本地存储      │  │   │
│                                 │  │                   │  │   │
│                                 │  │  /volume1/stock/   │  │   │
│                                 │  │  ├── A股数据/      │  │   │
│                                 │  │  ├── 回测结果/      │  │   │
│                                 │  │  ├── 代码库/        │  │   │
│                                 │  │  └── 临时文件/      │  │   │
│                                 │  └───────────────────┘  │   │
│                                 └─────────────────────────┘   │
│                                                               │
└─────────────────────────────────────────────────────────────┘

2.2 NAS端部署步骤

步骤1:准备NAS存储目录

在群晖NAS上创建以下目录结构:

/volume1/
├── stock/                    # 数据主目录
│   ├── A股数据/
│   │   ├── 日线数据/
│   │   ├── 分钟线数据/
│   │   └── 财务数据/
│   ├── 回测结果/
│   │   ├── 策略回测/
│   │   └── 性能报告/
│   ├── 代码库/
│   │   ├── 策略代码/
│   │   └── 工具脚本/
│   └── 临时文件/
│       ├── 下载缓存/
│       └── 临时数据/
└── docker/
    └── vnpy/                 # Docker相关目录
        ├── config/           # 配置文件
        ├── notebooks/        # Jupyter笔记本
        ├── strategies/       # 策略代码(Docker内)
        ├── logs/             # 日志文件
        ├── mysql-data/       # MySQL数据
        ├── redis-data/       # Redis数据
        └── pgadmin-data/     # pgAdmin数据

创建目录命令(在群晖SSH中执行)

# 数据目录
mkdir -p /volume1/stock/{A股数据/{日线数据,分钟线数据,财务数据},回测结果/{策略回测,性能报告},代码库/{策略代码,工具脚本},临时文件/{下载缓存,临时数据}}

# Docker目录
mkdir -p /volume1/docker/vnpy/{config,notebooks,strategies,logs,mysql-data,redis-data,pgadmin-data}

# 设置权限(确保Docker容器可以访问)
chmod -R 755 /volume1/stock
chmod -R 755 /volume1/docker/vnpy

步骤2:准备Docker配置文件

/volume1/docker/vnpy/ 目录下创建以下文件:

1. Dockerfile(使用章节六中的完整版)

2. docker-compose.yml(使用章节七中完整版,注意修改卷挂载路径)

3. entrypoint.sh(使用章节六中的启动脚本)

4. requirements.txt(使用章节六中的依赖文件)

5. .env(使用章节七中环境变量文件)

步骤3:部署Docker容器

# 进入项目目录
cd /volume1/docker/vnpy

# 构建并启动容器
docker-compose up -d

# 查看日志
docker-compose logs -f

# 确认服务正常运行
docker-compose ps

2.3 数据迁移方案

数据迁移步骤

  1. 挂载NAS到Mac mini(临时使用)

    • 按照《NAS挂载操作指南》挂载 /Volumes/stock
  2. 迁移现有数据到NAS

    # 假设Mac mini上的数据在 ~/stock/ 目录下
    rsync -av --progress ~/stock/ /Volumes/stock/
    
  3. 验证数据完整性

    # 检查文件数量
    find ~/stock/ -type f | wc -l
    find /Volumes/stock/ -type f | wc -l
    
  4. 迁移代码到NAS Docker

    • 将策略代码复制到 /Volumes/stock/代码库/
    • 同时也复制到 /Volumes/stock/docker/vnpy/strategies/Docker内使用)
  5. 清理Mac mini本地数据(确认迁移成功后)

    # 备份后删除
    mv ~/stock ~/stock.backup
    # 确认一切正常后再删除备份
    # rm -rf ~/stock.backup
    

2.4 Mac mini端配置

访问方式配置

Mac mini上只需配置以下访问方式,无需本地环境:

1. Jupyter Lab访问

  • 浏览器打开:http://192.168.2.154:8888
  • 输入token或密码(在.env文件中配置)

2. VS Code Server访问

  • 浏览器打开:http://192.168.2.154:8080
  • 或使用本地VS Code + Remote SSH扩展连接

3. vn.py Web界面

  • 浏览器打开:http://192.168.2.154:8000

4. SSH访问(可选)

  • ssh -p 2222 vnpy@192.168.2.154

浏览器书签配置

建议在Mac mini浏览器中创建以下书签:

量化工作台
├── Jupyter Lab - http://192.168.2.154:8888
├── VS Code Server - http://192.168.2.154:8080
├── vn.py Web - http://192.168.2.154:8000
└── 群晖DSM - http://192.168.2.154:5000

2.5 网络安全配置

基础安全措施

  1. 仅局域网访问

    • 不设置端口转发到公网
    • 所有服务仅在局域网内可访问
  2. 修改默认密码

    • 修改.env文件中的所有默认密码
    • 使用强密码策略
  3. 配置群晖防火墙

    • 仅允许信任的IP访问Docker相关端口
    • 在群晖DSM → 控制面板 → 安全性 → 防火墙中配置
  4. 定期更新

    • 定期更新Docker镜像
    • 保持群晖DSM系统更新

VPN远程访问(如需外网访问)

如果需要从外网访问,建议使用群晖VPN Server:

  1. 在群晖套件中心安装VPN Server
  2. 配置OpenVPN或L2TP/IPSec
  3. 外网先连接VPN,再访问内网服务

三、群晖Docker部署vn.py的具体步骤

3.1 准备工作

1. 确认群晖NAS型号和架构

# 在群晖SSH中执行
uname -m
# x86_64: 英特尔/AMD处理器
# aarch64: ARM处理器(如群晖DS224+等)

2. 启用群晖Docker

  1. 打开群晖DSM → 套件中心
  2. 搜索「Container Manager」或「Docker」
  3. 点击安装并启动

3. 准备共享文件夹

在群晖File Station中创建以下文件夹结构:

/docker/
└── vnpy/
    ├── config/          # 配置文件
    ├── data/            # 数据目录
    ├── notebooks/       # Jupyter笔记本
    ├── strategies/      # 策略代码
    └── logs/            # 日志文件

3.2 部署步骤详解

步骤1SSH登录群晖NAS

ssh admin@192.168.2.154  # 替换为你的NAS IP

步骤2:创建Docker网络(可选但推荐)

docker network create vnpy-network

步骤3:拉取或构建镜像

详见第六章Dockerfile配置。

步骤4:启动容器

详见第七章docker-compose配置。

步骤5:初始化配置

  1. 访问 http://NAS_IP:8888Jupyter
  2. 访问 http://NAS_IP:8000vn.py Web界面)
  3. 根据向导完成初始配置

四、性能评估

4.1 回测速度评估

基于NAS硬件配置的不同,回测速度会有较大差异:

NAS配置 日线回测速度 分钟线回测速度 评估
入门级(ARM双核+2G内存) ~10万根/分钟 ~5万根/分钟 可接受,适合小规模回测
中级(x86四核+8G内存) ~50万根/分钟 ~20万根/分钟 良好,适合大多数场景
高级(x86八核+16G内存) ~150万根/分钟 ~60万根/分钟 优秀,性能接近普通PC

影响因素

  1. CPU性能:回测主要是CPU密集型任务
  2. 内存大小:大数据量回测需要足够内存
  3. 存储速度:数据读取速度影响初始加载
  4. 网络延迟:远程访问时的交互延迟

4.2 局域网访问延迟评估

访问方式 延迟(ms 顺畅度
Jupyter Notebook <50ms 非常流畅
VS Code Server <50ms 非常流畅
vn.py Web界面 <100ms 流畅
VNC远程桌面 <150ms 可用

结论:局域网内访问体验非常好,几乎与本地使用无异。


五、数据存储方案

5.1 存储架构设计

推荐采用分层存储策略

群晖NAS存储架构:
├── SSD缓存层(热数据)
│   ├── 实时行情数据
│   ├── 常用策略代码
│   └── 数据库索引
├── HDD存储层(温数据)
│   ├── 历史日线数据
│   ├── 回测结果
│   └── 财务数据
└── 冷备存储层(归档)
    ├── 历史分钟线数据
    ├── 旧版本代码
    └── 长期归档

5.2 数据库选择

数据库 适用场景 NAS友好度 推荐度
SQLite 小型部署、单用户 首选
MySQL 中型部署、多用户 推荐
PostgreSQL 大型部署、高级功能 可选
TDengine 时序数据、高性能 推荐(分钟线)

5.3 数据访问性能

基于已有的NAS挂载测试结果:

存储配置 读取速度 写入速度 适用数据类型
千兆网络+HDD ~110MB/s ~100MB/s 日线、财务数据
千兆网络+SSD ~110MB/s ~110MB/s 全部数据(受网络限制)
万兆网络+SSD ~1000MB/s ~900MB/s 分钟线大数据

性能优化建议

  1. 使用SSD缓存:群晖支持SSD缓存,大幅提升热数据访问
  2. 数据库索引优化:为常用查询字段创建索引
  3. 数据分区:按时间分区存储历史数据
  4. 内存映射:使用内存映射文件提升大数据读取速度

六、网络访问方案

6.1 访问方式对比

访问方式 用途 端口 顺畅度 安全性
Jupyter Lab 策略开发、回测 8888 需密码保护
VS Code Server 代码编辑、调试 8080 需密码保护
vn.py Web 交易管理、监控 8000 需密码保护
SSH 系统管理、调试 2222 密钥认证
VNC 图形界面(如需) 5900 加密传输

6.2 Mac mini访问体验

基于局域网环境的实测:

Jupyter Notebook访问

  • 代码编辑:非常流畅,延迟<50ms
  • 图表渲染:快速,无明显延迟
  • 大数据查看:分页加载,体验良好

VS Code Server访问

  • 代码补全:响应迅速
  • 调试功能:流畅可用
  • 文件管理:与本地体验一致

vn.py Web界面

  • 行情监控:实时更新,延迟<100ms
  • 委托下单:响应快速
  • 资金曲线:流畅渲染

6.3 网络安全建议

  1. 仅局域网访问:不映射公网端口
  2. 使用HTTPS:配置SSL证书加密传输
  3. 强密码认证:所有服务都设置强密码
  4. VPN远程访问:如需外网访问,通过VPN连接
  5. 定期更新:保持Docker镜像和系统更新

七、Dockerfile配置示例

7.1 基础版Dockerfile

# 使用Python 3.11基础镜像
FROM python:3.11-slim-bookworm

# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Shanghai

# 设置工作目录
WORKDIR /app

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    --no-install-recommends \
    build-essential \
    git \
    curl \
    wget \
    vim \
    nano \
    tzdata \
    libgl1-mesa-glx \
    libglib2.0-0 \
    libsm6 \
    libxext6 \
    libxrender-dev \
    libgomp1 \
    && rm -rf /var/lib/apt/lists/*

# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 升级pip
RUN pip install --no-cache-dir --upgrade pip setuptools wheel

# 安装vn.py核心依赖
RUN pip install --no-cache-dir \
    vnpy \
    vnpy_ctp \
    vnpy_ctastrategy \
    vnpy_ctabacktester \
    vnpy_datamanager \
    vnpy_datarecorder \
    vnpy_rpcservice \
    vnpy_webtrader \
    jupyterlab \
    pandas \
    numpy \
    matplotlib \
    seaborn \
    plotly \
    scikit-learn \
    lightgbm \
    xgboost \
    ta-lib \
    python-dotenv

# 创建非root用户
RUN useradd -m -u 1000 vnpy && \
    chown -R vnpy:vnpy /app

# 切换用户
USER vnpy

# 暴露端口
EXPOSE 8888 8000 8080 2222

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8888 || exit 1

# 启动命令
CMD ["jupyter", "lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root"]

7.2 完整版Dockerfile(包含VS Code Server

# 多阶段构建
FROM python:3.11-slim-bookworm AS base

# 基础配置(同基础版)
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Shanghai

WORKDIR /app

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    --no-install-recommends \
    build-essential \
    git \
    curl \
    wget \
    vim \
    nano \
    tzdata \
    libgl1-mesa-glx \
    libglib2.0-0 \
    libsm6 \
    libxext6 \
    libxrender-dev \
    libgomp1 \
    sudo \
    openssh-server \
    && rm -rf /var/lib/apt/lists/*

# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 安装code-server
RUN curl -fsSL https://code-server.dev/install.sh | sh

# 升级pip
RUN pip install --no-cache-dir --upgrade pip setuptools wheel

# 安装Python依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 创建用户和配置SSH
RUN useradd -m -u 1000 vnpy && \
    echo "vnpy ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \
    mkdir -p /home/vnpy/.ssh && \
    chown -R vnpy:vnpy /home/vnpy /app && \
    chmod 700 /home/vnpy/.ssh

# 配置SSH
RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
    echo "vnpy:vnpy123" | chpasswd

# 切换用户
USER vnpy

# 配置code-server
RUN mkdir -p /home/vnpy/.config/code-server && \
    echo 'bind-addr: 0.0.0.0:8080' > /home/vnpy/.config/code-server/config.yaml && \
    echo 'auth: password' >> /home/vnpy/.config/code-server/config.yaml && \
    echo 'password: vnpy123' >> /home/vnpy/.config/code-server/config.yaml

# 创建启动脚本
COPY --chown=vnpy:vnpy entrypoint.sh /app/
RUN chmod +x /app/entrypoint.sh

# 暴露端口
EXPOSE 8888 8000 8080 2222

# 启动命令
ENTRYPOINT ["/app/entrypoint.sh"]

7.3 entrypoint.sh启动脚本

#!/bin/bash
set -e

echo "Starting vn.py Docker container..."

# 启动SSH服务
sudo service ssh start

# 启动Jupyter Lab(后台)
jupyter lab --ip=0.0.0.0 --port=8888 --no-browser --NotebookApp.token='vnpy123' --NotebookApp.password='' &

# 启动code-server(后台)
code-server &

# 等待服务启动
sleep 5

echo "=========================================="
echo "vn.py Docker container started successfully!"
echo "=========================================="
echo "Jupyter Lab: http://localhost:8888 (token: vnpy123)"
echo "VS Code Server: http://localhost:8080 (password: vnpy123)"
echo "SSH: ssh -p 2222 vnpy@localhost (password: vnpy123)"
echo "=========================================="

# 保持容器运行
tail -f /dev/null

7.4 requirements.txt依赖文件

# vn.py核心
vnpy>=4.0.0
vnpy_ctp
vnpy_ctastrategy
vnpy_ctabacktester
vnpy_datamanager
vnpy_datarecorder
vnpy_rpcservice
vnpy_webtrader
vnpy_sqlite
vnpy_mysql

# 数据处理
pandas>=2.0.0
numpy>=1.24.0
scipy>=1.10.0

# 可视化
matplotlib>=3.7.0
seaborn>=0.12.0
plotly>=5.14.0

# 机器学习
scikit-learn>=1.3.0
lightgbm>=4.0.0
xgboost>=2.0.0

# 技术分析
TA-Lib>=0.4.28

# Jupyter相关
jupyterlab>=4.0.0
ipywidgets>=8.0.0
jupyterlab-widgets>=3.0.0

# 工具库
python-dotenv>=1.0.0
requests>=2.31.0
aiohttp>=3.8.0
websockets>=11.0.0

八、docker-compose配置示例

8.1 基础版docker-compose.yml

version: '3.8'

services:
  vnpy:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: vnpy-container
    restart: unless-stopped
    
    # 端口映射
    ports:
      - "8888:8888"    # Jupyter Lab
      - "8000:8000"    # vn.py Web
      - "8080:8080"    # VS Code Server
      - "2222:22"      # SSH
    
    # 卷挂载
    volumes:
      # 配置文件
      - ./config:/app/config
      # 数据目录(映射到NAS存储)
      - /volume1/docker/vnpy/data:/app/data
      # Jupyter笔记本
      - ./notebooks:/app/notebooks
      # 策略代码
      - ./strategies:/app/strategies
      # 日志文件
      - ./logs:/app/logs
      # 时区
      - /etc/localtime:/etc/localtime:ro
    
    # 环境变量
    environment:
      - TZ=Asia/Shanghai
      - VNPY_DATA_DIR=/app/data
      - VNPY_CONFIG_DIR=/app/config
      - JUPYTER_TOKEN=vnpy123
    
    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '4.0'
          memory: 8G
        reservations:
          cpus: '2.0'
          memory: 4G
    
    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8888"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    
    networks:
      - vnpy-network

networks:
  vnpy-network:
    driver: bridge

8.2 完整版docker-compose.yml(包含数据库)

version: '3.8'

services:
  # vn.py主服务
  vnpy:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: vnpy-container
    restart: unless-stopped
    depends_on:
      - mysql
      - redis
    ports:
      - "8888:8888"
      - "8000:8000"
      - "8080:8080"
      - "2222:22"
    volumes:
      - ./config:/app/config
      - /volume1/docker/vnpy/data:/app/data
      - ./notebooks:/app/notebooks
      - ./strategies:/app/strategies
      - ./logs:/app/logs
      - /etc/localtime:/etc/localtime:ro
    environment:
      - TZ=Asia/Shanghai
      - VNPY_DATA_DIR=/app/data
      - VNPY_CONFIG_DIR=/app/config
      - JUPYTER_TOKEN=vnpy123
      - MYSQL_HOST=mysql
      - MYSQL_PORT=3306
      - MYSQL_USER=vnpy
      - MYSQL_PASSWORD=vnpy123
      - MYSQL_DATABASE=vnpy
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    deploy:
      resources:
        limits:
          cpus: '8.0'
          memory: 16G
        reservations:
          cpus: '4.0'
          memory: 8G
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8888"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    networks:
      - vnpy-network

  # MySQL数据库
  mysql:
    image: mysql:8.0
    container_name: vnpy-mysql
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=root123
      - MYSQL_DATABASE=vnpy
      - MYSQL_USER=vnpy
      - MYSQL_PASSWORD=vnpy123
      - TZ=Asia/Shanghai
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./mysql-init:/docker-entrypoint-initdb.d
      - /etc/localtime:/etc/localtime:ro
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --default-authentication-plugin=mysql_native_password
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 4G
    networks:
      - vnpy-network

  # Redis缓存
  redis:
    image: redis:7-alpine
    container_name: vnpy-redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
      - /etc/localtime:/etc/localtime:ro
    command: redis-server --appendonly yes --requirepass redis123
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
    networks:
      - vnpy-network

  # pgAdmin(数据库管理,可选)
  pgadmin:
    image: dpage/pgadmin4:latest
    container_name: vnpy-pgadmin
    restart: unless-stopped
    depends_on:
      - mysql
    ports:
      - "5050:80"
    environment:
      - PGADMIN_DEFAULT_EMAIL=admin@vnpy.com
      - PGADMIN_DEFAULT_PASSWORD=admin123
      - TZ=Asia/Shanghai
    volumes:
      - pgadmin-data:/var/lib/pgadmin
      - /etc/localtime:/etc/localtime:ro
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
    networks:
      - vnpy-network

volumes:
  mysql-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /volume1/docker/vnpy/mysql-data
  redis-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /volume1/docker/vnpy/redis-data
  pgadmin-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /volume1/docker/vnpy/pgadmin-data

networks:
  vnpy-network:
    driver: bridge

8.3 .env环境变量文件

# 基本配置
TZ=Asia/Shanghai
VNPY_DATA_DIR=/app/data
VNPY_CONFIG_DIR=/app/config

# Jupyter配置
JUPYTER_TOKEN=vnpy123
JUPYTER_PASSWORD=

# 数据库配置
MYSQL_HOST=mysql
MYSQL_PORT=3306
MYSQL_USER=vnpy
MYSQL_PASSWORD=vnpy123
MYSQL_DATABASE=vnpy
MYSQL_ROOT_PASSWORD=root123

# Redis配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=redis123

# pgAdmin配置
PGADMIN_DEFAULT_EMAIL=admin@vnpy.com
PGADMIN_DEFAULT_PASSWORD=admin123

# 资源限制
VNPY_CPU_LIMIT=8.0
VNPY_MEMORY_LIMIT=16G
VNPY_CPU_RESERVATION=4.0
VNPY_MEMORY_RESERVATION=8G

8.4 快速启动命令

# 1. 创建目录结构
mkdir -p /volume1/docker/vnpy/{config,data,notebooks,strategies,logs,mysql-data,redis-data,pgadmin-data}

# 2. 进入项目目录
cd /volume1/docker/vnpy

# 3. 创建并编辑docker-compose.yml(使用上面的配置)

# 4. 启动服务
docker-compose up -d

# 5. 查看日志
docker-compose logs -f

# 6. 查看服务状态
docker-compose ps

# 7. 停止服务
docker-compose down

# 8. 停止并删除数据(谨慎使用)
docker-compose down -v

九、可能遇到的问题和解决方案

9.1 群晖Docker相关问题

问题1:群晖Docker套件启动失败

症状Container Manager无法启动或异常退出 解决方案

  1. 检查群晖DSM版本,确保满足最低要求(DSM 7.0+)
  2. 重启群晖NAS
  3. 卸载并重新安装Docker套件
  4. 检查系统日志:/var/log/docker.log

问题2ARM架构镜像兼容性问题

症状:容器启动失败,提示exec格式错误 解决方案

  1. 确认NAS架构:uname -m
  2. 使用对应架构的基础镜像:
    • ARM64python:3.11-slim-bookworm(官方已支持多架构)
    • 或使用 --platform=linux/amd64 参数模拟x86(性能较差)
  3. 考虑使用支持多架构的Dockerfile

问题3NAS存储空间不足

症状:容器无法创建,提示磁盘空间不足 解决方案

  1. 清理Docker无用镜像和容器:
docker system prune -a
  1. 将Docker存储路径移到更大的存储空间:
    • 群晖DSM → Container Manager → 设置 → 注册表 → 存储位置
  2. 清理NAS其他无用文件

9.2 网络访问相关问题

问题4:局域网无法访问容器服务

症状Mac mini无法访问 http://NAS_IP:8888 解决方案

  1. 检查群晖防火墙设置:
    • 控制面板 → 安全性 → 防火墙 → 新增规则
    • 允许端口:8888, 8000, 8080, 2222
  2. 确认容器端口映射正确:docker-compose ps
  3. 检查NAS和Mac mini是否在同一网段
  4. 尝试重启容器:docker-compose restart

问题5:访问速度慢或延迟高

症状Jupyter操作卡顿,响应慢 解决方案

  1. 使用有线网络代替Wi-Fi
  2. 检查NAS CPU和内存使用情况
  3. 调整容器资源限制:
deploy:
  resources:
    limits:
      cpus: '8.0'
      memory: 16G
  1. 启用群晖SSD缓存
  2. 优化Jupyter配置,减少不必要的扩展

9.3 数据存储相关问题

问题6:容器内无法访问NAS挂载目录

症状:权限错误,无法读写数据目录 解决方案

  1. 检查NAS文件夹权限:
    • File Station → 右键文件夹 → 属性 → 权限
    • 确保用户(1000或vnpy)有读写权限
  2. 在docker-compose.yml中使用正确的用户ID
user: "1000:1000"  # 匹配群晖用户ID
  1. 或者在Dockerfile中创建对应用户

问题7:数据库性能差

症状:数据查询慢,回测加载时间长 解决方案

  1. 使用SSD存储数据库文件
  2. 优化数据库配置:
    • MySQL:增加innodb_buffer_pool_size
    • PostgreSQL:调整shared_buffers
  3. 创建适当的索引
  4. 考虑使用时序数据库(如TDengine)存储行情数据
  5. 定期清理和优化数据库表

9.4 vn.py运行相关问题

问题8vn.py缺少某些交易接口

症状CTP等接口无法加载 解决方案

  1. 检查Dockerfile中是否安装了对应接口:
RUN pip install vnpy_ctp vnpy_mini vnpy_sopt
  1. 某些接口可能需要特定系统库,在Dockerfile中添加:
RUN apt-get install -y libgl1-mesa-glx libglib2.0-0
  1. 考虑使用完整的vn.py Studio镜像作为基础

问题9:策略回测时内存溢出

症状:容器被OOM Killer终止 解决方案

  1. 增加容器内存限制
  2. 优化回测代码,分批加载数据
  3. 使用生成器处理大数据集
  4. 考虑使用Dask等分布式计算框架
  5. 减少回测时间范围或标的数量

9.5 安全相关问题

问题10:担心安全问题,不想暴露服务

症状:需要更安全的访问方式 解决方案

  1. 仅在局域网访问,不映射公网端口
  2. 使用VPN远程访问(群晖自带VPN Server)
  3. 配置HTTPS加密:
    • 使用群晖反向代理
    • 配置Let's Encrypt证书
  4. 启用双因素认证
  5. 定期更新Docker镜像和群晖系统

十、推荐部署 checklist

部署前检查

  • 确认群晖NAS型号和架构(x86/ARM)
  • 确认DSM版本 >= 7.0
  • 检查NAS可用存储空间(建议>100GB
  • 检查NAS内存(建议>=8GB
  • 准备好网络环境(千兆/万兆)

部署步骤

  • 安装并启动群晖Container Manager
  • 创建必要的共享文件夹
  • 配置文件夹权限
  • 准备Dockerfile和docker-compose.yml
  • 创建.env环境变量文件
  • 执行 docker-compose up -d
  • 检查容器启动状态:docker-compose ps
  • 查看日志确认服务正常:docker-compose logs -f

部署后验证

  • 测试Jupyter Lab访问:http://NAS_IP:8888
  • 测试VS Code Server访问:http://NAS_IP:8080
  • 验证数据目录挂载正常
  • 测试文件读写权限
  • 运行简单的vn.py回测验证功能
  • 配置自动备份

安全配置

  • 修改默认密码
  • 配置防火墙规则
  • 禁用不必要的端口映射
  • 配置HTTPS(如需要)
  • 设置定期更新计划

十一、成本与收益分析

11.1 硬件成本(参考)

项目 入门级 中级 高级
群晖NAS DS224+ (¥4000) DS923+ (¥8000) DS1621+ (¥15000)
内存升级 4GB→16GB (¥800) 8GB→32GB (¥1600) 16GB→64GB (¥3200)
存储(4T×2 ¥1600 ¥1600 ¥1600
SSD缓存(512G×2 - ¥1000 ¥2000
合计 ¥6400 ¥12200 ¥21800

11.2 收益分析

直接收益

  1. 节省硬件成本:不需要专门的量化交易PC
  2. 7×24小时运行NAS低功耗,适合长期运行
  3. 数据安全NAS RAID保护,数据更安全
  4. 易于扩展:存储和计算可独立扩展

间接收益

  1. 集中管理:策略、数据、回测统一管理
  2. 团队协作:支持多用户访问,便于协作
  3. 备份便利NAS自带备份功能,数据安全有保障
  4. 多功能复用:NAS还可用于其他用途(文件存储、媒体中心等)

十二、分阶段迁移实施计划

12.1 第一阶段:准备与验证(1-2天)

目标:确保NAS环境就绪,完成基础配置验证

任务清单

  • 确认群晖NAS状态正常(192.168.2.154
  • 确认NAS存储空间充足(建议>100GB可用)
  • 确认Container Manager已安装并运行
  • 检查NAS内存配置(建议≥8GB
  • 在NAS上创建所需目录结构
  • 配置目录权限
  • 测试从Mac mini访问NAS共享文件夹

验证标准

  • NAS目录创建成功,权限正确
  • Mac mini可正常挂载NAS共享文件夹
  • Container Manager运行正常

12.2 第二阶段:Docker环境部署(2-3天)

目标:在NAS上部署完整的vn.py Docker环境

任务清单

  • 准备Dockerfile文件
  • 准备docker-compose.yml文件
  • 准备entrypoint.sh启动脚本
  • 准备requirements.txt依赖文件
  • 准备.env环境变量文件(修改默认密码)
  • 执行docker-compose构建镜像
  • 启动Docker容器
  • 检查容器日志,确认服务正常启动
  • 验证各服务端口可访问

验证标准


12.3 第三阶段:数据迁移(1-2天)

目标:将Mac mini上的数据和代码迁移到NAS

任务清单

  • 在Mac mini上挂载NAS共享文件夹
  • 备份Mac mini本地重要数据
  • 迁移历史数据(日线、财务数据)到NAS
  • 迁移策略代码到NAS
  • 迁移Jupyter笔记本到NAS
  • 验证数据完整性(检查文件数量和大小)
  • 在NAS Docker环境中测试数据访问

验证标准

  • 所有数据文件成功复制到NAS
  • 文件数量和大小与源一致
  • 在Docker容器中可正常读取数据
  • 简单策略回测可正常运行

12.4 第四阶段:功能验证与优化(2-3天)

目标:验证完整功能并进行性能优化

任务清单

  • 测试Jupyter Lab完整功能
  • 测试VS Code Server代码编辑和调试
  • 测试vn.py策略回测功能
  • 运行完整的历史回测验证性能
  • 配置NAS自动备份任务
  • 配置容器自动重启策略
  • 优化数据库配置(如需要)
  • 配置监控和告警(可选)

验证标准

  • 所有核心功能正常可用
  • 回测速度满足预期
  • 数据自动备份正常工作
  • 系统稳定运行无异常

12.5 第五阶段:切换与清理(1天)

目标:完全切换到新架构,清理Mac mini本地环境

任务清单

  • 确认新环境稳定运行至少3天
  • 将Mac mini本地数据重命名为备份(不立即删除)
  • 更新所有访问方式为NAS地址
  • 配置浏览器书签
  • 验证日常工作流程在新环境下顺畅
  • 观察运行1-2周确认无误后
  • 清理Mac mini本地备份数据(谨慎操作)

验证标准

  • 日常量化工作完全在NAS Docker环境中进行
  • Mac mini本地无量化相关数据残留
  • 工作效率不受影响或有所提升

十三、结论与建议

13.1 可行性总结

整体可行性:完全可行

将sanguo_vnpy完全迁移到群晖NAS Docker容器中是一个极其优秀的方案,具有以下核心优势:

  1. 技术成熟:群晖Docker支持完善,vn.py兼容性好
  2. 彻底释放Mac mini:数据、代码、环境全部迁移,Mac mini仅作终端
  3. 性能够用:中高级NAS配置可满足大多数量化场景
  4. 数据安全NAS RAID保护,数据更可靠
  5. 统一管理:所有数据和环境集中管理,便于备份和维护
  6. 成本合理:利用现有NAS,无需额外硬件投入

13.2 核心收益

Mac mini存储空间释放

  • 从占用几十GB(数据+代码+环境)降至<1GB(仅浏览器/VSCode
  • 彻底解决Mac mini存储空间不足问题

数据管理提升

  • 所有数据集中在NAS,利用NAS的RAID和备份功能
  • 数据安全性大幅提升

维护便利性

  • 环境配置一次,处处可用
  • 升级、迁移更简单
  • 7×24小时稳定运行

13.3 最终推荐

对于你的场景(Mac mini + 群晖NAS + A股量化)

强烈推荐立即实施!

理由

  1. 你已有群晖NAS192.168.2.154),无需额外硬件投入
  2. NAS挂载已验证可行,数据存储方案成熟
  3. 局域网访问体验好,Mac mini访问顺畅
  4. 彻底解决Mac mini存储空间问题
  5. 便于数据集中管理和备份
  6. 为未来团队协作和扩展预留空间

建议配置

  • 如果NAS内存<8GB,优先升级内存
  • 配置SSD缓存提升性能(如有需要)
  • 使用MySQL数据库存储数据
  • 配置定期自动备份
  • 遵循第十二章的分阶段迁移计划实施

十四、参考资料

  1. vn.py官方文档
  2. vn.py GitHub仓库
  3. 群晖Container Manager官方文档
  4. Docker官方文档
  5. NAS存储调研报告
  6. NAS挂载操作指南

报告完成日期2026年3月26日
调研人员:姜维 伯约
版本v2.0
更新内容:补充完整部署方案,将数据和计算全部迁移到NAS Docker,Mac mini仅作远程终端