在Nginx上部署Python Flask应用
由 Find · 2017年11月30日 11 看过
- Introduction
本文主要系翻译自digitalocean的教程How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 16.04 ,部分进行了修改。
主要介绍了在nginx服务器上利用uWSGI部署Flask应用的步骤。
之前写过的相关内容:
uwsgi配置https以及python2无法使用supervisor
- 准备工作
在开始之前,先确保有一个非root的用户部署在你的服务器上,这个用户必须使用sudo
才能执行管理员命令。
FindHao注:非root用户是为了安全性考虑,但是由于购买的vps系统一般默认root用户,通过lnmp.org一键安装lnmp之后,会创建www用户和www用户组,因此下文的配置是以root用户配置为例,但是期间会插入修改目录权限的步骤。
- 安装必要的软件
我们将尽量通过pip
orpip3
来安装包,而非使用发行版源里的工具,避免源里工具版本过低造成的问题。
更新源,并安装python。
python2:
1 | 复制代码apt update |
python3:
1 | 复制代码apt update |
- 创建python虚拟环境
4.1 安装virtualenv
为了将我们的Flask应用与系统里的其他python文件项目隔离开,接下来配置python虚拟环境。
使用pip
安装virtualenv
:
1 | 复制代码# python2 |
现在,为我们的Flask应用创建目录:
1 | 复制代码mkdir ~/myproject |
或者直接在lnmp的目录里,clone你的项目:
1 | 复制代码cd /home/wwwroot/ |
FindHao注:
由于我们是在root下操作的,因此应该将项目的文件所属权都移交给www
1
2
3 > 复制代码chown -R www.www ./*
>
>
由于lnmp会在域名目录下创建一个.user.ini
的文件,导致你无法删除lnmp创建的目录,运行下面代码后删除即可:
chattr -i ``/home/wwwroot/yoursite/``.user.ini
如果是需要修改文件,记得修改完以后运行:
chattr +i ``/home/wwwroot/yoursite/``.user.ini
4.2 创建并激活虚拟环境
创建虚拟环境的目录:
1 | 复制代码virtualenv myenv |
myenv
的目录是用来存放本地python的镜像,以及后面通过pip
安装的包将安装到myenv
目录里,而不是系统的目录里。
在安装之前,需要先激活刚刚建立的虚拟环境:
1 | 复制代码source myenv/bin/activate |
你的命令行前面会多个提示,表明你是在虚拟环境操作:
1 | 复制代码(myenv)user@host:~/myproject#. |
- 设置Flask应用
5.1 安装Flaks和uWSGI
注意,无论你使用的哪个python版本,进入虚拟环境以后,应该使用
pip
,而不是pip3
1 | 复制代码(myenv) # pip install uwsgi flask |
5.2 建立sample
现在我们创建一个简单的样例程序来测试flask和uwsgi是否正常运行。
1 | 复制代码(myenv) # vim index.py |
FindHao注:
修改文件权限:
1
2
3 > 复制代码chown www.www index.py
>
>
内容如下:
1 | 复制代码from flask import Flask |
如果你开启了防火墙,要在你防火墙规则里关闭对5000端口的禁用。
运行我们的flask sample:
1 | 复制代码(myenv) # python index.py |
在浏览器里访问你的vps ip+:5000端口:
1 | 复制代码http://server_domain_or_IP:5000 |
如果看到如下内容表示运行正常,可以CTRL C终止sample的运行继续下一步了。
- 配置uWSGI
6.1 测试uWSGI
首先我们需要测试uWSGI运行正常:
1 | 复制代码(myenv) # uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app |
你应该再次看到上面的hell there的提示。
CTRL C终止,并deactivate
退出虚拟环境
6.2 创建uWSGI配置文件
为了让我们的项目启动和配置更灵活,我们创建uWSGI配置文件:
1 | 复制代码# vim myproject.ini |
内容如下:
1 | 复制代码[uwsgi] |
[uwsgi]
头表示我们这是个uwsgi的配置。module
指向wsgi.py
文件,文件里的回调是app。
接下来的部分表明项目运行在master mode,并且有五个worker进程处理请求。
在上面测试的时候,我们的uWSGI是通过网络端口暴露出来的,但是由于后面我们将使用nginx来处理实际的client连接,然后传递给uwsgi,而由于这些操作都是在一个机器上运行的,因此这里我们改成socket的模式更安全快速。我们指定socket文件是当前项目目录下的myproject.sock
。
我们还必须改变socket的权限。待会我们会迁移uWSGI进程的所属组到nginx的组,因此我们必须确保socket的所属组用户能从它那里读写信息。同时在进程结束的时候,也需要清理socket(vacuum
)。
die-on-term
,可以确保init system和uWSGI有相同的环境。
logto
是保存日志文件。
你可能会注意到,我们没有像前面命令行一样指定一个协议,这是因为uWSGI默认使用uwsgi
协议,一个快速的二进制协议,nginx内置了这个协议,用这个协议比http协议更快。
6.3 日志
前面我们指定了logto
来保存日志,但是www用户对日志的目录没有写权限,因此需要手动建立这个log文件,并chown给www。
同时由于默认日志是一直在写入,文件会不停的增长,因此还需要使用系统的logrotate
日志工具对其进行处理。
创建一个日志的配置文件
1 | 复制代码# vim /etc/logrotate.d/myproject-log-file |
内容如下:
1 | 复制代码/var/log/myproject.log { |
- monthly: 日志文件将按月轮循。其它可用值为‘daily’,‘weekly’或者‘yearly’。
- rotate 5: 一次将存储5个归档日志。对于第六个归档,时间最久的归档将被删除。
- compress: 在轮循任务完成后,已轮循的归档将使用gzip进行压缩。
- delaycompress: 总是与compress选项一起用,delaycompress选项指示logrotate不要将最近的归档压缩,压缩将在下一次轮循周期进行。这在你或任何软件仍然需要读取最新归档时很有用。
- missingok: 在日志轮循期间,任何错误将被忽略,例如“文件无法找到”之类的错误。
- notifempty: 如果日志文件为空,轮循不会进行。
- create 644 root root: 以指定的权限创建全新的日志文件,同时logrotate也会重命名原始日志文件。
- postrotate/endscript: 在所有其它指令完成后,postrotate和endscript里面指定的命令将被执行。在这种情况下,rsyslogd 进程将立即再次读取其配置并继续运行。
- 创建systemd文件
Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置。
接下来我们将创建一个service文件来保证系统自动启动uWSGI和我们的Flask应用。
以Debian为例,创建一个myproject.service
文件:
1 | 复制代码# vim /lib/systemd/system/myproject.service |
内容如下:
1 | 复制代码[Unit] |
7.1 Unit字段
[Unit]
区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系。
Description
:简短描述After
:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动
7.2 Service字段
[Service]
区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。
ExecStart
:启动当前服务的命令ExecReload
:重启当前服务时执行的命令ExecStop
:停止当前服务时执行的命令Environment
:指定环境变量KillMode
: mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
user和group用来指定进程所属用户和组。lnmp默认是www.www。设置working directory和path来告诉init system我们的项目在哪里,虚拟环境是怎样的。然后执行uwsgi开启Flask应用。
FindHao注:
在这个service文件里,我添加了PIDFile
、ExecReload
、ExecStop
等几个字段,因为如果没有reload和stop字段,要重启我们的Flask应用,只能通过重启vps或者杀掉uwsgi进程的方式。
PIDFile
指定了我们Flask应用的进程文件,可以传给后面stop和reload用。
reload使用uwsgi自带的reload。
stop则通过进程文件的防止找到指定进程并结束掉它。
7.3 Install 字段
[Install]
通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。
WantedBy
:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system
目录下面以 Target 名 +.wants
后缀构成的子目录中
7.4 运行
保存上面的配置文件后,常用的systemd命令有:
1 | 复制代码systemctl start myproject # 开启应用 |
开启应用后,查看应用状态,如果是active,表明成功启动运行,如果failed,可以通过journalctl
查看运行日志,并G
(vim的查看形式,即Shift + g到最后一行)看看启动的错误是什么。
- 配置Nginx来处理请求
如果是lnmp安装的nginx,则nginx的配置目录为/usr/local/nginx/conf/vhost
。
如果之前没有安装,则可以通过apt直接安装nginx,但是源里的nginx可能版本比较老,对于一些新特性不支持,建议添加nginx官方源里安装,参考 《nginx配置https》 3.6 nginx 支持HTTP2。单独安装的nginx配置文件目录一般为/etc/nginx/sites-available
在nginx的配置目录新建一个nginx的配置文件myproject
,内容如下:
1 | 复制代码server { |
listen表示监听80端口,server_name则是你的域名或者ip。
localtion /
则表示对于域名或者ip/
的请求处理方式。首先通过包含uwsgi_params
来加载一些默认的uWSGI参数。然后uwsgi_pass
转发请求给我们定义的socket。
这只是创建了可用的配置文件,如果要启用,还需要将其软连接到enable目录:
1 | 复制代码# ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled |
检查我们的配置文件是否编写正确:
1 | 复制代码# nginx -t |
如果提示ok,则重启nginx:
1 | 复制代码systemctl restart nginx |
访问我们的域名或者ip,可以看成已经正常运行。
Reference
How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 16.04
uwsgi配置https以及python2无法使用supervisor
本文转载自: 掘金