背景
手里有一个web项目,代码按照前端代码库、后端代码库分别在GitHub上,分散带来的结果是,不容易持续集成,比如你可能需要很多的job去保证一个项目的正常运作,但是这个项目也不是特别大,所以尝试将代码融合,于此同时将代码docker化,用于持续部署。
技术架构
原来的代码使用gunicorn+gevent+supervisor+flask+DB的架构;具体的细节如下:
- 本地服务器搭建了一个nginx域名服务器,里面区分PC端还是手机端;
- 访问域名通过nginx,访问前端静态页面的内容
- 静态页面中加载指定地址的数据,提供数据的服务由flask后端提供接口;
- 后端提供的接口,通过访问redis缓存和mongodb数据库,返回相应的数据;
整改方案
首先我们需要将DB和Flask App拆分开,使用supervisor将包括DB在哪的所有进程,都控制在一起,所以我们需要经他们分开:
- 直接使用docker pull 下载指定版本的redis和mongo就可以
构建flask app的dockerfile
- 在dockerfile中,我们决定不实用supervisor,具体原因下面说;
由于之前的supervisor是安装在centos中的,我们代码使用python3,所以在centos上装了一个虚拟环境,用于跑flask代码,所以我们使用python:3.6-slim为基础镜像;在使用apline镜像的时候,不能安装一些依赖,包括supervisor,所以我选择了slim,后面拆分的时候因为supervisor在slim中,每次启动都有问题,所以我放弃了supervisor,这样你也可以使用apline,但是我还是保持了slim;
FROM python:3.6-slim COPY . /app WORKDIR /app RUN pip install -i https://pypi.douban.com/simple -r requirements.txt EXPOSE 5000 ENV FLASK_APP=manage.py
- 上面构建的是整个flask项目的镜像,包括写数据库的进程(可独立运行),还有一个广播的进程,最后就是flask本身的进程;我们已经将数据库独立出来,所以在原来的代码中需要将访问数据库的URL host修改对应的IP,也可以使用–link,直接指定contianer的名字代替host,具体原理没有详细研究。(后来发现,在平滑升级的时候还是需要将DB对应的端口暴露给宿主机,本来使用–link是不需要的);
- flask镜像包含了写数据库,flask本身(可以理解为读数据库)和广播功能,我们在启动镜像的时候,需要启动这三个进程,分别是:
flask run --host 0.0.0.0; flask wdb; flask broadcast;
- 为了保持代码的完整,我们不使用flask run命令,而使用原来的gunicorn+gevent的方式执行代码;