Flask + uWSGI + nginx + mysql + Docker-compose 搭建环境

flask 已经能够简单的使用了,还没有部署过,这次再将其用Docker-compose编排一下,使得可以一句命令搭建生产环境。

相关概念

uWSGI是实现WSGI、uwsgi等协议的web服务器,而搭配nginx可以更好的做到负载均衡。而flask自带的支持WSGI协议的web服务器并不能很好的用作生产环境,只能在开发环境下使用了。

准备Flask代码

下面是一个简单的使用到mysql的flask小程序,数据库操作并没有什么实质性的操作,只要连接上了就可以了,而且在使用docker-compose之前,mysql并没有什么好说的。

/home/jrxnm/webapp/webapp.py

from flask import Flask, render_template_string
import pymysql
app = Flask(__name__)

@app.route("/")
def index():
    try:
        db = DbOperate()
    except:
        return render_template_string('<h1>Mysql Can not connect</h1>')
    return render_template_string('<h1>Hello Flask !!!</h1>')

class DbOperate(object):
    def __init__(self):
        db = pymysql.connect('127.0.0.1', 'root', '123456', 'webapp')

if __name__ == "__main__":
    app.run(debug=True,port=5555)

准备uWSGI

uWSGI是python实现的,pip安装就可以了。pip install uwsgi

当然我们也可以不需要nginx,直接使用uWSGI作为flask的web服务器,但uWSGI提供了socket接口,方便nginx接入。

uWSGI配置文件:uwsgi.ini

[uwsgi]
module = webapp:app
master = true
processes = 4
chdir = /home/jrxnm/webapp
socket = 127.0.0.1:8002
logto = /home/jrxnm/log/app.log
chmod-socket = 666
vacuum = true

chdir 指的是webapp.py的绝对地址,socket就是uWSGI留给nginx接入的接口(如果将socket一行改为http=:5000,就相当于flask直接用uWSGI作为服务器运行了),logto是日志地址,module指的是执行webapp.py文件中的app。

现在执行uwsgi --ini ./uwsgi.ini uWSGI服务器就运行起来了。

当然uWSGI也可以直接用命令行启动,不必写入配置文件,只是每次都需要敲同样的配置。具体方法参考官方手册

准备nginx

ubuntu apt 安装就好了, apt install nginx

nginx 和 apache2 服务器配置方式差不多,如下为/etc目录下nginx部分分支图

nginx
├── conf.d
├── nginx.conf
├── sites-available
│   └── default
├── sites-enabled
├── uwsgi_params

我们可以看到,/etc/nginx/nginx.conf 是nginx的总配置文件,并且在其中include了如下两个文件夹

和apache一样sites-available文件夹是用来存放运行和暂不运行的配置文件,而sites-enabled则是存放运行的配置文件,而且sites-enabled中的配置文件大多是sites-available中配置文件的软链。

现在我们来写一个配置文件,这里只做最简单的配置:nginx.conf

server {
    listen 80;
    server_name 127.0.0.1; 
    location / {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:8002;
    }
}

这里重点是include uwsgi_params;uwsgi_pass 127.0.0.1:8002; 前者确定使用uWSGI,后者确定uWSGI接口。

我们直接将nginx.conf添加到conf.d文件夹重启nginx服务器就好。

Flask + uWSGI + nginx

如果上面的uWSGI服务器运行成功,nginx服务器重启没有报错的话,那么此时在本机的80端口应该就可以看到我们的Flask程序跑起来了

使用docker-compose编排

docker容器是个好东西,一键配置环境,在这里我们也使用docker-compose搭建 Flask + uWSGI + nginx + mysql 的环境。

最终项目树

├── webapp
    └── app.py
    └── Dockerfile
    └── uwsgi.ini
├── bak.sql
├── nginx.conf

docker-compose.yml 如下:

version: "3"

services:

    webapp:
        build: ./webapp
        container_name: webapp
        depends_on:
            - mysql
        volumes:
            - ./app.log:/webapp/app.log

    mysql:
        image: mysql:5.7
        environment: 
            - MYSQL_ROOT_PASSWORD=123456
        volumes: 
            - ./bak.sql:/docker-entrypoint-initdb.d/bak.sql

    nginx:
        image: nginx
        volumes:
            - ./nginx.conf:/etc/nginx/conf.d/default.conf
        depends_on:
            - webapp
        ports:
            - "8888:80"

主要解释一下,每个service对应一个容器,使用build制定Dockerfile位置,使用image制定镜像名称。volumes将本地文件或者文件夹挂载到docker容器中,mysql容器挂载到/docker-entrypoint-initdb.d/文件夹是因为官方实现的mysql镜像有初始化功能,在该文件夹的.sql和.sh文件将被执行。

webapp/Dockerfile

FROM python:3.6
ENV TZ=Asia/Shanghai
RUN mkdir /webapp
WORKDIR /webapp
COPY . /webapp

RUN pip install -r requirements.txt

CMD ["uwsgi", "--ini", "/webapp/uwsgi.ini"]

这个时候,Flask中连接数据库的host就需要改成mysql(与docker-compose.yml中的services名相同)

class DbOperate(object):
    def __init__(self):
        db = pymysql.connect('mysql', 'root', '123456', 'webapp')

nginx.conf改为:

server {
    listen 80;
    server_name 0.0.0.0; 
    location / {
        include uwsgi_params;
        uwsgi_pass webapp:8002;
    }
}

uwsgi.ini改为:

[uwsgi]
module = webapp:app
master = true
processes = 4
chdir = /home/jrxnm/webapp
socket = :8002
logto = /home/jrxnm/log/app.log
chmod-socket = 666
vacuum = true

最后执行docker-compose up 就可以在本机8888端口看到flask程序运行了。

参考资料

https://www.cnblogs.com/franknihao/p/7202253.html

http://docs.jinkan.org/docs/flask/deploying/uwsgi.html#id1

https://blog.csdn.net/Reid_Lv/article/details/80109127