原文转载自「刘悦的技术博客」v3u.cn/a_id_164python
书接上回,以前一篇:Win10环境下使用Flask配合Celery异步推送实时/定时消息(Socket.io)/2020年最新攻略,阐述了如何使用Celery异步推送Websocket消息,如今咱们利用Docker将这个完整项目部署起来,为何用Docker呢?缘由很简单,这种容器技术能够将整个项目用单个容器装起来,仅仅只须要维护一个简单的配置文件就告诉电脑每次部署要把什么东西装进容器,甚至把这个过程自动化,部署流程就会变得简单、方便。mysql
简单理解就是Docker的镜像就相似《精灵宝可梦》中小智手里的精灵球,咱们的项目就相似那些宠物小精灵,当咱们开发完毕就能够利用DockerFile对项目进行打包制做成镜像(小精灵被吸入精灵球),部署时就能够理解为小精灵被释放出来进行战斗(经过打包好的镜像运行容器),而Docker的仓库则提升了镜像的便捷性,可让咱们随时随地只要联网就可使用本身的镜像(至关于小智不用随身携带精灵球,而是经过网络随时下载须要的精灵球)。git
同时Docker其强大的跨平台特性,可让咱们在任何系统下部署项目,包括常常使人诟病的Windows,值得一提的是本次在Win10下部署项目的流程一样适用于Centos、Mac os、Ubuntu等系统,其兼容性可见一斑。redis
关于Win10如何折腾和配置Docker,请参照这篇文章:win10系统下把玩折腾DockerToolBox以及更换国内镜像源(各类神坑)sql
首先简单看一下项目结构:docker
manage.py是项目的入口文件,这里咱们利用Sockert.io让Flask支持Websocketdjango
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import pymysql
from flask import request,jsonify
from flask_cors import CORS
from flask_socketio import SocketIO,send,emit,join_room, leave_room
import urllib.parse
import user_view
from celery import Celery
from datetime import timedelta
pymysql.install_as_MySQLdb()
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:root@localhost:3306/md"
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['BROKER_URL'] = 'redis://localhost:6379'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379'
app.config['CELERY_ACCEPT_CONTENT'] = ['json', 'pickle']
app.config['REDIS_URL'] = 'redis://localhost:6379'
app.config['JSON_AS_ASCII'] = False
CORS(app,cors_allowed_origins="*")
app.register_blueprint(user_view.user)
db = SQLAlchemy(app)
socketio = SocketIO(app,cors_allowed_origins='*',async_mode="threading",message_queue=app.config['CELERY_RESULT_BACKEND'])
celery = Celery(app.name)
celery.conf.update(app.config)
celery.conf.CELERYBEAT_SCHEDULE = {
"test":{
"task":"get_cron",
"schedule":timedelta(seconds=10)
}
}
@celery.task(name="get_cron")
def get_cron():
get_sendback.delay()
@celery.task()
def get_sendback():
socketio.emit('sendback','message',broadcast=True)
@app.route('/task')
def start_background_task():
get_sendback.delay()
return '开始'
@app.route('/',methods=['GET','POST',"PUT","DELETE"])
def hello_world():
#res = db.session.execute("insert into user (`username`) values ('123') ")
# res = db.session.execute(" select id,username from user ").fetchall()
# data = request.args.get("id")
# #data = request.form.get("id")
# print(data)
# print(res)
# #return 'Hello Flask'
# return jsonify({'result': [dict(row) for row in res]})
return jsonify({'message':'你好,Docker'})
@socketio.on('join')
def on_join(data):
username = 'user1'
room = 'room1'
join_room(room)
send(username + ' has entered the room.', room=room)
@socketio.on('message')
def handle_message(message):
message = urllib.parse.unquote(message)
print(message)
send(message,broadcast=True)
@socketio.on('connect', namespace='/chat')
def test_connect():
emit('my response', {'data': 'Connected'})
@socketio.on('disconnect', namespace='/chat')
def test_disconnect():
print('Client disconnected')
@app.route("/sendback",methods=['GET'])
def sendback():
socketio.emit('sendback','message')
return 'ok'
if __name__ == '__main__':
socketio.run(app,debug=True,host="0.0.0.0",port=5000)
复制代码
接下来使用Gunicorn+gevent来运行Flask项目,Gunicorn服务器做为wsgi app的容器,可以与各类Web框架兼容(flask,django等),得益于gevent等技术,使用Gunicorn可以在基本不改变wsgi app代码的前提下,大幅度提升wsgi app的性能。那到底怎么提高性能?说简单点,Gunicorn 默认的网络模型是 select ,当咱们把worker 替换成 gevent 后,则改成 epoll 监听模型,关于select、poll、epoll请参照这篇文章:关于Tornado:真实的异步和虚假的异步,这里再也不赘述。json
安装相应的库flask
pip install gunicorn gevent --user
复制代码
编辑项目目录下的gunicorn.conf.pybash
workers = 3 # 进程数
worker_class = "gevent" # 异步模式
bind = "0.0.0.0:5000"
复制代码
因为Gunicorn并不支持Windows环境,因此只须要写好配置,不须要运行。
编辑项目目录下的requirements.txt文件,这里面都是咱们项目所依赖的库
flask==1.0.2
flask-cors
flask-socketio
flask-sqlalchemy
pymysql
celery
gunicorn
gevent
redis==3.3.11
复制代码
随后在项目目录下建立一个 Dockerfile 文件,这个文件能够理解为打包镜像的脚本,你须要这个镜像作什么,就把任务写到脚本中,Docker经过执行这个脚原本打包镜像
FROM python:3.6
WORKDIR /Project/myflask
COPY requirements.txt ./
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY . .
ENV LANG C.UTF-8
CMD ["gunicorn", "manage:app", "-c", "./gunicorn.conf.py"]
复制代码
能够看到,咱们项目的镜像首先基于python3.6这个基础镜像,而后声明项目目录在/Project/myflask中,拷贝依赖表,以后安装相应的依赖,这里在安装过程当中咱们指定了国内的源用来提升打包速度,最后利用gunicorn运行项目,值得一提的是,ENV LANG C.UTF-8是为了声明Docker内部环境中的编码,防止中文乱码问题。
最后咱们就能够愉快的打包整个项目了,在项目根目录下执行
docker build -t 'myflask' .
复制代码
此时看到Docker经过读取Dockerfile文件来下载所需的基础镜像和依赖库,这里必定要指定Docker的下载源,不然速度会很是缓慢,打包好的镜像文件大概有1g左右。
下载结束以后,能够看到myflask这个镜像已经静静躺在镜像库中了,运行
docker images
复制代码
命令来查看
而后咱们就能够利用这个镜像来经过容器跑Flask项目了,运行命令
docker run -it --rm -p 5000:5000 myflask
复制代码
这里的命令是经过端口映射把docker内部的端口5000映射到宿主机的5000端口上,后面的参数是镜像名称。咱们看到,在Win10下,已经难以想象的经过Gunicorn把Flask跑起来了,这在以前没有Docker技术以前是不可想象的。
经过网址访问一下,这里注意一点,就是Windows系统下,访问Docker容器须要经过分配的ip来访问,而不是咱们经常使用的localhost。
彻底没有任何问题。
结语:到这里咱们的 Docker+Flask + Gunicorn就部署完毕了,将这个镜像上传Dockerhub仓库,在任什么时候间、任何地点、任何系统上,只要连着网、只要咱们想,就均可以在短短1分钟以内部署好咱们的项目,这就是Docker技术对开发人员最好的馈赠。最后奉上项目地址:gitee.com/QiHanXiBei/…
原文转载自「刘悦的技术博客」 v3u.cn/a_id_164