hcnak.blog

posted at 2017-09-16 16:02:40 +0000

在Ubuntu 16.04上使用 Nginx 和 Gunicorn 托管 Python Flask网站

翻译至:How To Serve Flask Applications with Gunicorn and Nginx on Ubuntu 16.04

引言

通过这个教程我们将会学习到如何利用Gunicorn 结合 Nginx 使 Flask 应用程序运行在Ubuntu 16.04上。本文的大部分内容将介绍如何设置Gunicorn应用程序服务器以启动应用程序,并将Nginx用作前端反向代理。

教程开始之前…

你需要一个可以执行 sudo 命令的用户账户,系统上应该确保安装了systemd (注意,不是upstart)。如果有WSGI的相关知识那就更好不过了,不过没有也不影响。

安装相关组件

这一步我们将会安装 Python 包管理程序 pip 和 Nginx。

如果你的版本为 Python 2.x,使用以下命令安装:

sudo apt-get update
sudo apt-get install python-pip python-dev nginx

如果你的版本是Python 3.x, 使用以下命令:

sudo apt-get update
sudo apt-get install python3-pip python3-dev nginx

创建虚拟环境

设置 Flask 应用程序

首先我们需要安装Flask 和 Gunicorn,通过以下命令进行安装:

pip install gunicorn flask

如果你使用的Python 3,请使用以下命令:

pip3 install gunicorn flask

接下来我们创建 flask 应用程序,我们取名为 myproject.py,其代码如下:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

上面的代码定义了一个非常简单的页面,并将其绑定到本地根域名。 为了访问我们的flask应用程序,首先,我们需要打开 5000端口。通过以下命令打开5000端口:

sudo ufw allow 5000

紧接着,我们开始运行我们的 flask 应用程序:

python myproject.py

然后我们通过主机名或者我们服务器的IP地址来访问该程序,再浏览器中输入以下地址:

http://server_domain_or_IP:5000

一切正常的话,你的应该看起来和下图一样:

Flask sample app

这里配置完毕后,我们通过再控制台按 Ctrl + C命令来结束我们的flask应用程序。

## 创建WSGI入口脚本

接下来,我们将创建一个脚本文件,作为我们应用程序的入口点。这个脚本将告诉我们的Gunicorn服务器应该如何与应用程序进行交互。 我们将文件命名为 wsgi.py,创建文件:

nano ~/myproject/wsgi.py

文件内容如下,只是简单的导入我们flask应用程序的app模块:

from myproject import app

if __name__ == "__main__":
    app.run()

文件写好后保存并推出,接下来我们进行下一步。

## 测试 Gunicorn 能否正常托管我们的flask应用程序

接下来我们测试 Gunicorn是否正常工作。 我们可以通过简单的讲WSGI入口名称传递给Gunicorn,测试是否正常运行。WSGI入口名字通常由以下部分组成:

WSGI入口名称 = 模块名称 + 应用程序中可调用名称

模块名称即WSGI脚本名称(不含文件扩展名),应用程序中可调用名称即 flask 中的 app = Flask(__name__)。在我们的例子中,WSGI入口名称为 wsgi:app 。 在运行Gunicorn的过程中我们同时需要指定 IP地址和端口来确保可以正常访问。

cd ~/myproject
gunicorn --bind 0.0.0.0:5000 wsgi:app

还是和刚刚直接测试 flask 脚本相同,请在浏览器输入以下地址进行访问:

http://server_domain_or_IP:5000

如果出现下图,即表示可以正常运行。

Flask sample app

## 创建 Systemd 单元文件

接下来我们需要创建一个systemd 系统服务文件。该文件将允许Ubuntu在开机的时候自动启动Gunicorn,并为我们的Flask应用程序提供服务。通过这个文件,我们的 flask应用程序已经成为系统的一个服务,可以通过 service 命令来启动/关闭以及重新启动。 创建文件:

sudo nano /etc/systemd/system/myproject.service

在这个文件里面,我们将从[Unit]部分开始,该部分用于指定元数据和依赖关系。我们将在这里描述我们的服务,并告诉init系统只有在达到网络目标后才能启动它(联网?)。

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

接下来,我们编写 [Service] 部分,我们将会指定该服务使用何种用户账户运行。由于flask程序拥有所有必不可少的运行文件,因此我们会给予其常规的用户帐户所有权。我们将会赋予它为 www-data 用户组,这样Nginx和它数据交换更加容易。 然后我们设置工作路径和 PATH 环境变量,这样 初始化系统 就知道Gunicorn可执行程序在哪里。 Systemd 要求我们以完整路径名指定可执行程序。如果你不知道完整路径,可以尝试:

locate [name]

或者

which name

我们将会设置 Gunicorn开启3个工作线程(根据您的需求更改)。我们同时会令 Gunicorn 绑定一个 命名为 myproject.socket 位于我们工作目录的Unix 套接字文件。设置套接字文件的 umask007这样该文件仅能被和myproject服务相同的用户组访问。最后,我们需要将WSGI入口名称传递给Gunicorn,截至目前,myproject.service内容如下:

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

最后,我们会需要添加[Install]块,这可以让 systemd 知道应该在哪种系统启动模式时启动服务。我们希望让这个服务在正常启动系统时随系统启动:

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

至此,我们的 systemd服务文件已经完成。 我们现在可以启动该服务,并令其在系统开机时自动启动:

sudo systemctl start myproject
sudo systemctl enable myproject

配置Nginx

我们的Gunicorn程序目前应该可以正常运行了。接下来我们要配置Nginx来传递网络请求到刚刚创建的套接字文件,这样才能够访问到我们的flask应用程序。

我们可以在Niginx的sites-available文件夹下新增配置文件,避免修改默认配置文件。

我们将我们的配置文件命名为 myproject:

sudo nano /etc/nginx/sites-available/myproject
server { 
  listen 80; 
  server_name server_domain_or_IP;
location / {
    include proxy_params;
    proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
  }
}

我们需要修改上述文件内容中的 server_domain_or_IPserver_domain_or_IP设置为你的域名或者IP地址。 如果你没有使用套接字文件,而是绑定IP端口的形式,请修改 proxy_pass后面的内容到您flask应用程序绑定的对应IP和端口。

保存文件,接下来我们需要让这个配置文件生效,将该文件链接到Nginx的sites-enabled文件目录:

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx
sudo ufw delete allow 5000 sudo ufw allow 'Nginx Full'

访问以下地址:

http://server_domain_or_IP

Flask sample app

总结

我们创立了一个建议flask应用程序,同时我们创建了 WSGI 入口点,这样任何支持 WSGI的服务程序都可以支持我们的flask应用(我们使用的Gunicorn完成这一功能)。

然后我们创建了systemd系统服务文件来让我们的flask应用程序开机自动启动。我们还配置了Nginx来反向代理我们的服务器。



© kanchzl AT kanchz DOT com

last updated on 2022-07-27 01:57:54 +0000