如何在CentOS7上使用Gunicorn和Nginx服务Flask应用程序

来自菜鸟教程
跳转至:导航、​搜索

介绍

在本指南中,我们将在 CentOS 7 上使用 Flask 微框架设置一个简单的 Python 应用程序。 本文的大部分内容将是关于如何设置 Gunicorn 应用程序服务器来启动应用程序和 Nginx 作为前端反向代理。

先决条件

在开始阅读本指南之前,您应该在服务器上配置一个非 root 用户。 此用户需要具有 sudo 权限,才能执行管理功能。 要了解如何设置,请按照我们的 初始服务器设置指南

要了解有关我们的应用程序服务器将用于与我们的 Flask 应用程序通信的 WSGI 规范的更多信息,您可以阅读 本指南 的链接部分。 了解这些概念将使本指南更易于理解。

当您准备好继续时,请继续阅读。

从 CentOS 和 EPEL 存储库安装组件

我们的第一步是从存储库中安装我们需要的所有部分。 我们需要添加 EPEL 存储库,其中包含一些额外的包,以便安装我们需要的一些组件。

您可以通过键入以下内容启用 EPEL 存储库:

sudo yum install epel-release

一旦在我们的系统上配置了对 EPEL 存储库的访问权限,我们就可以开始安装我们需要的包。 我们将安装 Python 包管理器 pip,以便安装和管理我们的 Python 组件。 我们还将获得 Gunicorn 所需的编译器和 Python 开发文件。 我们现在也将安装 Nginx。

您可以通过键入以下内容来安装所有这些组件:

sudo yum install python-pip python-devel gcc nginx

创建 Python 虚拟环境

接下来,我们将设置一个虚拟环境,以便将我们的 Flask 应用程序与系统上的其他 Python 文件隔离开来。

首先使用 pip 安装 virtualenv 包:

sudo pip install virtualenv

现在,我们可以为我们的 Flask 项目创建一个父目录。 创建后进入目录:

mkdir ~/myproject
cd ~/myproject

我们可以通过键入以下内容来创建一个虚拟环境来存储我们的 Flask 项目的 Python 需求:

virtualenv myprojectenv

这会将 Python 和 pip 的本地副本安装到项目目录中名为 myprojectenv 的目录中。

在我们在虚拟环境中安装应用程序之前,我们需要激活它。 您可以通过键入:

source myprojectenv/bin/activate

您的提示将更改以指示您现在正在虚拟环境中操作。 它看起来像这样 (myprojectenv)user@host:~/myproject$

设置 Flask 应用程序

现在您已经进入了虚拟环境,我们可以安装 Flask 和 Gunicorn 并开始设计我们的应用程序:

安装 Flask 和 Gunicorn

我们可以使用 pip 的本地实例来安装 Flask 和 Gunicorn。 键入以下命令以获取这两个组件:

pip install gunicorn flask

创建示例应用程序

现在我们有了可用的 Flask,我们可以创建一个简单的应用程序。 Flask 是一个微型框架。 它不包括功能更全面的框架可能提供的许多工具,主要作为一个模块存在,您可以将其导入项目以帮助您初始化 Web 应用程序。

虽然您的应用程序可能更复杂,但我们将在单个文件中创建 Flask 应用程序,我们将其称为 myproject.py

nano ~/myproject/myproject.py

在这个文件中,我们将放置我们的应用程序代码。 基本上,我们需要导入 flask 并实例化一个 Flask 对象。 我们可以使用它来定义在请求特定路由时应该运行的函数。 我们将在代码 application 中调用我们的 Flask 应用程序来复制您在 WSGI 规范中找到的示例:

from flask import Flask
application = Flask(__name__)

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

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

这基本上定义了访问根域时要呈现的内容。 完成后保存并关闭文件。

您可以通过键入以下内容来测试您的 Flask 应用程序:

python myproject.py

在您的网络浏览器中访问您的服务器的域名或 IP 地址,然后访问终端输出中指定的端口号(很可能是 :5000)。 您应该看到如下内容:

完成后,在终端窗口中按 CTRL-C 几次以停止 Flask 开发服务器。

创建 WSGI 入口点

接下来,我们将创建一个文件作为应用程序的入口点。 这将告诉我们的 Gunicorn 服务器如何与应用程序交互。

我们将调用文件 wsgi.py

nano ~/myproject/wsgi.py

该文件非常简单,我们可以简单地从我们的应用程序中导入 Flask 实例,然后运行它:

from myproject import application

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

完成后保存并关闭文件。

测试 Gunicorn 为项目服务的能力

在继续之前,我们应该检查 Gunicorn 是否正确。

我们可以通过简单地将入口点的名称传递给它来做到这一点。 我们还将指定要绑定的接口和端口,以便在公开可用的接口上启动它:

cd ~/myproject
gunicorn --bind 0.0.0.0:8000 wsgi

如果您在 Web 浏览器的末尾附加 :8000 访问服务器的域名或 IP 地址,您应该会看到如下所示的页面:

确认它运行正常后,在终端窗口中按 CTRL-C。

我们现在已经完成了我们的虚拟环境,所以我们可以停用它:

deactivate

现在任何操作都将在系统的 Python 环境中进行。

创建一个系统单元文件

我们需要处理的下一个部分是 Systemd 服务单元文件。 创建一个 Systemd 单元文件将允许 CentOS 的 init 系统在服务器启动时自动启动 Gunicorn 并为我们的 Flask 应用程序提供服务。

/etc/systemd/system 目录下创建一个以 .service 结尾的文件开始:

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

在内部,我们将从 [Unit] 部分开始,它用于指定元数据和依赖项。 我们将在此处描述我们的服务,并告诉 init 系统仅在达到网络目标后才启动它:

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

接下来,我们将打开 [Service] 部分。 我们将指定我们希望进程在其下运行的用户和组。 由于它拥有所有相关文件,因此我们将授予我们常规用户帐户对该过程的所有权。 我们将授予 Nginx 用户组所有权,以便它可以轻松地与 Gunicorn 进程通信。

然后我们将绘制工作目录并设置 PATH 环境变量,以便 init 系统知道我们的进程可执行文件的位置(在我们的虚拟环境中)。 然后我们将指定启动服务的命令。 Systemd 要求我们提供 Gunicorn 可执行文件的完整路径,该可执行文件安装在我们的虚拟环境中。

我们将告诉它启动 3 个工作进程(根据需要进行调整)。 我们还将告诉它在我们的项目目录中创建并绑定到一个名为 myproject.sock 的 Unix 套接字文件。 我们将设置一个 007 的 umask 值,以便创建套接字文件以授予所有者和组的访问权限,同时限制其他访问权限。 最后,我们需要传入 WSGI 入口点文件名:

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

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

我们需要添加到文件中的最后一部分是 [Install] 部分。 如果我们允许它在启动时启动,这将告诉 Systemd 将该服务链接到什么。 我们希望在常规多用户系统启动并运行时启动此服务:

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

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

[Install]
WantedBy=multi-user.target

这样,我们的 Systemd 服务文件就完成了。 现在保存并关闭它。

我们现在可以启动我们创建的 Gunicorn 服务并启用它,以便它在启动时启动:

sudo systemctl start myproject
sudo systemctl enable myproject

将 Nginx 配置为代理请求

我们的 Gunicorn 应用程序服务器现在应该启动并运行,等待项目目录中套接字文件的请求。 我们需要通过在其配置文件中添加一些小内容来配置 Nginx 以将 Web 请求传递到该套接字。

首先打开 Nginx 的默认配置文件:

sudo nano /etc/nginx/nginx.conf

在文件中已经存在的另一个 server {} 块上方打开一个服务器块:

http {
    . . .

    include /etc/nginx/conf.d/*.conf;

    server {
    }

    server {
        listen 80 default_server;

        . . .

我们将把 Flask 应用程序的所有配置放在这个新块中。 我们将首先指定此块应侦听默认端口 80,并应响应我们服务器的域名或 IP 地址:

server {
    listen 80;
    server_name server_domain_or_IP;
}

我们需要添加的唯一另一件事是匹配每个请求的位置块。 在这个块中,我们将设置一些标准的代理 HTTP 标头,以便 Gunicorn 可以获得有关远程客户端连接的一些信息。 然后我们将流量传递到我们在 Systemd 单元文件中指定的套接字:

server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://unix:/home/user/myproject/myproject.sock;
    }
}

完成后保存并关闭文件。

nginx 用户必须有权访问我们的应用程序目录才能访问那里的套接字文件。 默认情况下,CentOS 非常严格地锁定每个用户的主目录,因此我们会将 nginx 用户添加到我们的用户组,以便我们可以打开授予访问权限所需的最低权限。

您可以使用以下命令将 nginx 用户添加到您的用户组。 用您自己的用户名替换命令中的 user

sudo usermod -a -G user nginx

现在,我们可以授予用户组对主目录的执行权限。 这将允许 Nginx 进程输入和访问以下内容:

chmod 710 /home/user

设置好权限后,我们可以测试 Nginx 配置文件的语法错误:

sudo nginx -t

如果返回没有任何问题,我们可以启动并启用 Nginx 进程,以便它在启动时自动启动:

sudo systemctl start nginx
sudo systemctl enable nginx

您现在应该可以在 Web 浏览器中访问服务器的域名或 IP 地址并查看您的应用程序:

结论

在本指南中,我们在 Python 虚拟环境中创建了一个简单的 Flask 应用程序。 我们创建了一个 WSGI 入口点,以便任何支持 WSGI 的应用程序服务器都可以与之交互,然后配置 Gunicorn 应用程序服务器来提供此功能。 之后,我们创建了一个 Systemd 单元文件以在启动时自动启动应用程序服务器。 我们创建了一个 Nginx 服务器块,它将 Web 客户端流量传递到应用程序服务器,中继外部请求。

Flask 是一个非常简单但非常灵活的框架,旨在为您的应用程序提供功能,而不会对结构和设计进行过多限制。 您可以使用本指南中描述的通用堆栈来为您设计的烧瓶应用程序提供服务。