以量化金融研究工具为例: Docker到底给开发人员/测试工程师/数据科学家带来了什么?

我们经常看到关于docker的介绍,例如:


https://us-west-2.console.aws.amazon.com/ecs/home?region=us-west-2#/getStarted

例如:

https://www.aliyun.com/product/eci
https://www.aliyun.com/product/containerservice#

听起来都很牛B!

但是在日常工作中docker给我们带了来什么呢? 假如使用docker之前每天的工作是996.icu, 使用docker之后也是996.icu, 那么我们为什么还要学习和使用一个新的工具呢? 本文展示一下在docker下的日常工作是什么样的,让你决定要不要学这个强大的新工具。

本文只演示docker对我们日常工作的改变,并不讲解docker的底层原理,for that, 请参阅:

如何搞懂容器的核心技术点?

《Demystifying Containers 101: A Deep Dive Into Container Technology for Beginners》

Understand Container - Index Page

Discussing Docker. Pros and Cons.

带着下面这几个疑问:

日常Task 无docker的做法 docker 大法
1.保障开发、测试、生产环境配置的一致性 强迫开发、测试人员都使用Linux工作,尽管不利于生产力提升 docker容器在linux/ win 10 / mac os 运行结果总是一致的
2.不同的项目需要不同的软件运行时版本时 .. 每个容器应用都可以指定自己使用的操作系统版本、软件运行时、依赖库
3.首次配置环境/ 安装一个应用 一大堆的操作,win/linux/mac os 都不尽相同 相同的几个command
4.有不良应用时 会影响整个服务器的其它应用,甚至host机的安全 很容易限制其使用的cpu 和 内存量
5.应用新版本发布和回滚 。。 1-4个command
6.扩容/缩容时 。。 可配置自动的

在everyday work中,我们来感受一下使用docker 和没有使用docker的区别

本地开发环境搭建和应用安装

quantrocket

quantrocket 是一个支持全球主流市场量化交易策略研究和实盘的量化工具:

When the US closes, Asia opens. When Asia closes, Europe opens. Exploit profitable opportunities whenever they occur.
当美国市场闭市,亚洲又开盘了,亚洲闭市之后,欧洲开盘。用quantrocket在全球多个市场中抓住尽可能多的获利机会。

且拥有卓越的架构设计:

在视频中我们看到,强大的quantrocket由近20个微服务组成,要安装配置好是不是挺麻烦的? 至少在docker的帮助下不是, 只需要两个步骤:

step 1 : 下载 https://www.quantrocket.com/composefiles/latest/local/docker-compose.yml 到当前工作路径

step 2 :

确保你的机器上已经安装和启动了docker,然后在vs code中右单击docker-compose.yml 文件,选择 compose up, 一个vs code的terminal会弹出来并执行 docker-compose -f "docker-compose.yml" up -d --build :

compose-up-1

稍等片刻(根据你的网速,首次使用时可能要等超过半个小时),当terminal出现大概20个 "*** up-to-date" , 这个强大的quantrocket, 支持全球主流市场量化交易策略研究和实盘的量化工具就已经安装好了,浏览器打开 http://localhost:1969/jupyter/lab 就可以开始你的量化研究了:
r

关键是,无论在windows , mac os , linux , 上面的两个步骤都是相同的,不需要重新学习。

上面的例子非常的顺利,除非网络链接不畅造成镜像的pull动作失败之外,不太可能有其它失败的原因。

下面我们来看一个不那么顺利的例子。

Tronado

Tornado其实不仅仅是一个Web开发的框架,它还是一个高性能的事件驱动网络访问引擎,内置了高性能的HTTP服务器和客户端(支持同步和异步请求),同时还对WebSocket提供了完美的支持。 底层技术是通过对非阻塞I/O和epoll(Linux 2.5.44内核引入的一种多路I/O复用方式,旨在实现高性能网络服务,在BSD和macOS中是kqueue)的运用,Tornado可以处理大量的并发连接,更轻松的应对C10K(万级并发)问题,是非常理想的实时通信Web框架。在开发实时行情动态的服务器端应用时是一个不错的选择。

接下来我们演示用docker来搭建tronado的本地开发环境:

step 1: 把https://github.com/tornadoweb/tornado/tree/master/demos/blog clone 到本地
step 2: 然后在vs code中右单击docker-compose.yml 文件,选择 compose up <-是的,和上面的例子的步骤是一样的。

但是浏览器访问 http://localhost:8888/ 发现可能并没有运行。这是什么原因呢? 我们手动在terminal运行 docker-compose up 并观察输出发现:

pg

原因是postgres启动得比tronado慢, tronado应用启动的时候尝试链接postgres数据库失败。解决的方案有好几种:

第1种(这方案有点粗暴): 在docker-compose.yml 增加图中2的配置,这个配置选项的含义是如果tronado启动失败,总是尝试重启,等它多试几次之后 postgres也应该启动完成并且准备好接受连接了,tronado也不会再报错了。

ps : 上面图中1的配置 无法确保tronado等待postgres可以接受连接再启动,它只是让docker-compose先启动postgres的容器再去启动tronado容器,但是postgres的容器启动之后并不意味着能立即接受连接,可能还需要一点时间做一些初始化动作

第2种:把docker-compose.yml 的command配置项改成图中3, 让这个容器等待postgres可以正常接受连接的时候再启动tronado应用。

还有一些其它的方案:

https://docs.docker.com/compose/startup-order/

https://stackoverflow.com/questions/43998313/waiting-for-a-docker-container-to-be-ready#

gecko

Gekko is a free and open source Bitcoin TA trading and backtesting platform that connects to popular Bitcoin exchanges. It is written in javascript and runs on nodejs.
Gekko是使用node.js开发的开源的比特币量化交易回测和实盘工具,支持主流的比特币交易所。

当我们打开它的安装文档页面的时候,差点被吓退了:

NOTE: unfortunately installing and managing Gekko is hard. You will need to touch the commandline and install a few developer tools. I am creating an official Gekko service called Gekko Plus that will NOT require any installation.
很不幸,安装和管理Gekko有难度,你需要接触命令行,和安装一些开发工具.。。。。。

别怕,好在我们有docker。 步骤和上面的是一样的:

step 1: 把 https://github.com/askmike/gekko.git clone到本地。
step 2: 然后在vs code中右单击docker-compose.yml 文件,选择 compose up

是的,和上面的例子的步骤是一样的。既然都是同样的步骤,那么我们为什么要举这个例子呢?

因为这次,如果你身处中国,你可能要等特别久,最终还可能因为网络原因失败,原因是什么呢? 打开根目录的Dockerfile (https://github.com/askmike/gekko/blob/develop/Dockerfile )会发现很多npm install 从外网拉取数据,这就是要等很久的原因。 把Dockerfile 中和npm相关的内容改为使用yarn :

ps: Dockerfile定义了一个容器应用使用了什么操作系统版本,安装哪些库 ,暴露了哪些端口 等等,总之具备这个容器应用所需的一切

FROM node:8

ENV HOST localhost
ENV PORT 3000

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

RUN apt-get update && apt-get install -y  apt-utils  curl apt-transport-https && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y  yarn 

# Install GYP dependencies globally, will be used to code build other dependencies
RUN npm config set registry https://registry.npm.taobao.org && \
     npm install -g --production node-gyp && \
    npm cache clean --force

# Install Gekko dependencies
COPY package.json .
# RUN npm install --production && \
#     npm install --production [email protected] [email protected] [email protected] pg && \
#     npm cache clean --force
RUN yarn install --production && \
     yarn add --production [email protected] [email protected] [email protected] pg  && \
     yarn cache clean

# Install Gekko Broker dependencies
WORKDIR exchange
COPY exchange/package.json .
# RUN npm install --production && \
#     npm cache clean --force
RUN yarn install --production  && yarn cache clean

WORKDIR ../

# Bundle app source
COPY . /usr/src/app

EXPOSE 3000
RUN chmod +x /usr/src/app/docker-entrypoint.sh
ENTRYPOINT ["/usr/src/app/docker-entrypoint.sh"]

CMD ["--config", "config.js", "--ui"]

重复上面的两个步骤, 稍等片刻就可以开始比特币交易研究了:

gekko

上面3个例子都提供了docker-compose.yml , 虽然有时候我需要稍微的修改一下,但总体来说还是挺方便的。

温习一下docker compose:

Compose is a tool for defining and running multi-container Docker applications
Compose是一个用于编排和运行多容器应用的工具。

底层技术specifications请查阅: https://docs.docker.com/compose/overview/

下面是一个没有提供 docker-compose.yml 的例子。

abupy

阿布量化交易系统(股票,期权,期货,比特币,机器学习) 基于python的开源量化交易

和刚才的例子不同,当我们把项目clone到本地的时候发现作者并没有提供docker-compose.yml, 这时我们需要自己动手 写 dockerfiledocker-compose.yml

从文档中我们了解到作者推荐使用Anaconda运行abupy。我们基于Anaconda镜像定制。

dockerfile:

FROM  continuumio/miniconda3

# RUN  apt-get install -y gfortran
# RUN  apt update && apt install apt-transport-https

# ./sources.list的content如下:
# deb https://mirrors.tuna.tsinghua.edu.cn/debian/ stretch main contrib non-free
# deb https://mirrors.tuna.tsinghua.edu.cn/debian/ stretch-updates main contrib non-free
# deb https://mirrors.tuna.tsinghua.edu.cn/debian/ stretch-backports main contrib non-free
# deb https://mirrors.tuna.tsinghua.edu.cn/debian-security stretch/updates main contrib non-free
COPY ./sources.list /etc/apt/sources.list

RUN  apt-get update && \
  apt-get install -y apt-transport-https python3-dev   build-essential libblas3 liblapack3  liblapack-dev libblas-dev && \
  apt upgrade -y 

RUN  pip install -U setuptools --no-cache-dir  -i "https://mirrors.aliyun.com/pypi/simple/" 

# TA-Lib安装:  https://stackoverflow.com/questions/45406213/unable-to-install-ta-lib-on-ubuntu
RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \
  tar -xvzf ta-lib-0.4.0-src.tar.gz && \
  cd ta-lib/ && \
  ./configure --prefix=/usr && \
  make && \
  make install &&  \
  apt upgrade -y && \
  pip install ta-lib -i "https://mirrors.aliyun.com/pypi/simple/"  && \
  cd  ../ &&  rm -R ta-lib ta-lib-0.4.0-src.tar.gz

RUN /opt/conda/bin/conda install -y jupyterlab   && \
    /opt/conda/bin/conda install -y pypy3.6     && \
    /opt/conda/bin/conda install -y scikit-learn  matplotlib numpy pandas=0.22.0  \
        scipy  seaborn openpyxl ipywidgets requests bokeh  toolz  psutil  Pillow numba  libcurl urllib3 && \
    /opt/conda/bin/conda clean -tipsy 

RUN pip install  -i "https://mirrors.aliyun.com/pypi/simple/" --no-cache-dir   \
            tushare 
            #abupy    # sklearn

# COPY ./  /opt/notebooks/abu

CMD  /opt/conda/bin/jupyter lab --notebook-dir=/opt/notebooks/my --ip='0.0.0.0' --allow-root --port=9999 --no-browser

docker-compose.yml

version: '3'
services:
  abupy:
    build:./   
    entrypoint:  ["/opt/conda/bin/jupyter", "lab", "--allow-root", "--ip=0.0.0.0", "--notebook-dir=/opt/notebooks/my","--port=9999", "--no-browser"]   
    volumes:
      # - ./volumes/jupyter-runtime-my:/root/.local/share/jupyter/runtime/
      - ./:/opt/notebooks/my
    ports: 
      - "9999:9999"

然后就是和刚才的例子中同样的步骤了: 在terminal中执行 docker-compose up , 然后打开./volumes/jupyter-runtime-my 下的html文件 就可以在jupyter lab中使用abupy进行量化交易研究了。

上面几个例子就演示了当我们需要在本地安装一些配置过程复杂的应用时,或者配置开发环境时,使用docker的便利。 你可能遇到的3种情况:

  1. 应用的author提供了docker-compose.yml 文件,这时可以compose up 就运行了,节省大量时间。
  2. 应用的author只提供了dockerfile 文件,需要自己动手编写docker-compose.yml ,也节省了大量时间。
  3. 都没有提供,需要自己编写 dockerfile 和 docker-compose.yml,但肯定比不使用docker要快和省事

你也许会问在最后的abupy例子中,我直接在本地机器安装Anaconda好像也不是很费时啊! 但当你打开https://conda.io/projects/conda/en/latest/user-guide/install/index.html 会发现Anaconda在Windows/macOS/Linux都有不同的安装和配置方式,你得重新学习。 而使用docker, 在不同的平台都是一致的 dockerfile 和 docker-compose.yml 文件 和 docker-compose up命令。而且如果你需要更换设备你得重新安装配置一次,而使用docker还是那个docker-compose up命令。

生产环境部署和新版本升级。

我们重用上面的 tronado 例子。

在everyday work中,需要部署一个或者几十个容器应用到云端,无论是首次部署还是版本升级,无论是部署到1台服务器还是2000多台机器的集群,一般只需要执行下面的1-5行command:


# 首次使用hub.docker.com需要登陆,也可以使用阿里云提供的免费registry
docker login -u=wz -p="<密码隐藏了>"   hub.docker.com
# 最新的master分支build一个新的docker镜像 
docker build -t "wz/ladyluck_web:0.1.1" ./
# 推送到docker hub 或者阿里云提供的免费registry
docker push  wz/lady_luck_web:0.1.1
# 使用stack-test.yml文件部署到测试用的docker集群
docker  --host tcp://<隐藏了的测试环境ip>:<隐藏了的端口> \
        --tlsverify  --tlscacert  "./_cert/ca.pem"  --tlscert "./_cert/cert.pem" \
        --tlskey "./_cert/key.pem" --with-registry-auth \
        stack deploy -c stack-test.yml  ladyluck_web
# 测试通过之后使用stack.yml文件部署到生产环境
docker  --host tcp://<隐藏了的生产环境ip>:<隐藏了的端口> \
        --tlsverify  --tlscacert  "./_cert/ca.pem"  --tlscert "./_cert/cert.pem" \
        --tlskey "./_cert/key.pem" --with-registry-auth \
        stack deploy -c stack.yml  ladyluck_web

tips 1: 上面1-4个command可以一次性拷贝到terminal执行(或者写到vs code的task里),然后去喝杯咖啡,回来后应该完成部署了,不需要单独一行一行执行。

而且不用提前备份当前本版,不用担心部署失败造成服务中断。留意一下上面部署command中使用的stack.yml中的注释,希望你已经找到了本文开头的表格中留下疑问的答案了:

stack

详细技术细节可参阅 《通往罗马的一条大道:一种基于docker的微服务架构的可行方案》

Docker给你的日常工作带来了什么? 希望你已经有了答案。

更多

了解docker的最新发展:

https://dockercon2018.hubs.vidyard.com/watch/w3RJr1Su6oamQmemhGtaK3

开始学习docker的基础理论:

https://yeasy.gitbooks.io/docker_practice/

dockerfile最佳实践: https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices/

docker的实战举例:

https://mherman.org/blog/dockerizing-a-react-app/

https://github.com/jackfrued/Python-100-Days/blob/master/Day91-100/92.Docker在项目中的应用.md


最后

May the fortune be with you:
愿财富与你同在:

new-image---c3ct5