如何在 Ubuntu 18.04 上使用 uWSGI 和 Nginx 服务 Flask 应用程序

介绍

在本指南中,您将使用 Ubuntu 18.04 上的 Flask 微框架构建一个 Python 应用程序。本文的大部分内容将是如何设置 uWSGI 应用程序服务器以及如何启动应用程序并配置 Nginx作为前端反向代理。

前提条件

要完成本教程,您将需要:

步骤 1 – 从 Ubuntu 存储库中安装组件

第一步是从Ubuntu存储库中安装您所需的所有部件,您将安装Python包管理器pip,以管理您的Python组件,您还将获得构建uWSGI所需的Python开发文件。

首先,更新本地包索引:

1sudo apt update

然后安装可用于构建 Python 环境的包,这些包将包括python3-pip,以及为强大的编程环境所需的其他一些包和开发工具:

1sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

有了这些包,您可以继续为您的项目创建虚拟环境。

第2步:创建一个Python虚拟环境

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

开始安装python3-venv包,该包将安装venv模块:

1sudo apt install python3-venv

接下来,为您的 Flask 项目创建一个家长目录:

1mkdir ~/myproject

然后在您创建后进入目录:

1cd ~/myproject

创建一个虚拟环境来存储您的 Flask 项目的 Python 要求,运行以下操作:

1python3.6 -m venv myprojectenv

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

在在虚拟环境中安装应用之前,您需要激活它:

1source myprojectenv/bin/activate

您的提示将更改,以表示您现在正在虚拟环境中运行,它将读取如下: (myprojectenv) user@host:~/myproject$

步骤 3 – 设置一个Flask应用程序

现在你已经在你的虚拟环境中,你可以安装Flask和uWSGI,并开始设计你的应用程序。

首先,使用本地实例pip安装轮子,以确保您的软件包会安装,即使它们缺少轮子档案:

1pip install wheel

<$>[注] :无论您正在使用哪个版本的Python,当虚拟环境被激活时,您应该使用pip命令(而不是pip3)。

接下来,安装 Flask 和 uWSGI:

1pip install uwsgi flask

安装完成后,您可以开始使用 Flask。

创建样本应用程序

现在你有Flask可用,你可以创建一个简单的应用程序. 正如你可能记得的那样,Flask是一个微框架,不包括更多的功能框架可能的许多工具。

虽然你的应用程序可能更复杂,但你将创建你的Flask应用程序在一个文件中. 你可以使用你最喜欢的文本编辑器创建该文件. 对于这个例子,我们将使用nano并命名它为myproject.py:

1nano ~/myproject/myproject.py

应用程序代码将生活在这个文件中. 它将导入Flask并实例化Flask对象. 您可以使用此功能来定义需要执行特定路径时的函数:

 1[label ~/myproject/myproject.py]
 2from flask import Flask
 3app = Flask(__name__)
 4
 5@app.route("/")
 6def hello():
 7    return "<h1 style='color:blue'>Hello There!</h1>"
 8
 9if __name__ == "__main__":
10    app.run(host='0.0.0.0')

这定义了在访问根域时要呈现的内容。在完成时,保存并关闭文件。如果您使用nano,则可以按CTRL + X,然后按YENTER

如果您遵循初始服务器设置指南,则应启用 UFW 防火墙. 要测试该应用程序,您需要允许访问端口 5000:

1sudo ufw allow 5000

现在测试您的 Flask 应用程序:

1python myproject.py

您将收到如下输出,包括一个有用的警告,提醒您不要在生产中使用此服务器设置:

1[secondary_label Output]
2* Serving Flask app "myproject" (lazy loading)
3 * Environment: production
4   WARNING: Do not use the development server in a production environment.
5   Use a production WSGI server instead.
6 * Debug mode: off
7 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

请访问您的服务器的 IP 地址,然后在您的 Web 浏览器中:5000:

1http://your_server_ip:5000

你应该看到一些如下:

Flask sample app

当你完成时,在终端窗口中按CTRL + C,停止Flask开发服务器。

创建 WSGI 入口点

接下来,您将创建一个文件,它将作为您的应用程序的入口点,这将告诉您的 uWSGI 服务器如何与其进行交互。

首先创建并命名文件 wsgi.py:

1nano ~/myproject/wsgi.py

在此文件中,从应用程序中导入 Flask 实例,然后运行它:

1[label ~/myproject/wsgi.py]
2from myproject import app
3
4if __name__ == "__main__":
5    app.run()

保存并关闭文件,当你完成。

步骤 4 – 配置 uWSGI

您的应用程序现在已经创建了一个入口点,您现在可以继续配置 uWSGI。

试用UWSGI

在做出更多更改之前,测试 uWSGI 是否能为您的应用提供服务可能是有帮助的。

您可以通过将您的入口点的名称传递给 uWSGI 来做到这一点,这是由模块名称(减为 .py 扩展)以及应用程序内可调用的名称构建的。

您还将指定接口,以便它将在公共可用的接口上启动,以及协议,以便它将使用HTTP而不是uwsgi二进制协议。

1uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

再次访问您的服务器的 IP 地址,在您的 Web 浏览器的末端附加:5000:

1http://your_server_ip:5000

您应该再次收到您的申请的输出:

Flask sample app

当您确认它正常工作时,请在终端窗口中按CTRL + C

现在你已经完成了你的虚拟环境,你可以禁用它:

1deactivate

任何 Python 命令现在都将再次使用系统的 Python 环境。

创建 uWSGI 配置文件

您已经测试并验证了 uWSGI 能够为您的应用提供服务,但最终您将需要更强大的东西,可用于长期使用。

将该文件放入您的项目目录,并将其命名为myproject.ini:

1nano ~/myproject/myproject.ini

在内部,您将开始使用[uwsgi]标题,以便 uWSGI 知道如何应用设置. 您将指定两件事:模块本身,引用wsgi.py文件减去扩展,并在文件中可调用的app:

1[label ~/myproject/myproject.ini]
2[uwsgi]
3module = wsgi:app

接下来,告诉 uWSGI 在主模式下启动并生成五个工人流程,以满足实际请求:

1[label ~/myproject/myproject.ini]
2[uwsgi]
3module = wsgi:app
4
5master = true
6processes = 5

当你在测试时,你在网络端口上暴露了uWSGI,但是,你会使用nginx来处理实际的客户端连接,然后将请求传递给uWSGI。

这会让 Nginx 群组更晚地拥有 uWSGI 流程,所以请确保群组所有者能够从插槽中读取信息并写入它。

 1[label ~/myproject/myproject.ini]
 2[uwsgi]
 3module = wsgi:app
 4
 5master = true
 6processes = 5
 7
 8socket = myproject.sock
 9chmod-socket = 660
10vacuum = true

你要做的最后一件事是设置死于期限选项,这可以帮助确保 init 系统和 uWSGI 对每个过程信号的含义有相同的假设。

 1[label ~/myproject/myproject.ini]
 2[uwsgi]
 3module = wsgi:app
 4
 5master = true
 6processes = 5
 7
 8socket = myproject.sock
 9chmod-socket = 660
10vacuum = true
11
12die-on-term = true

你可能已经注意到,你没有从命令行中指定一个协议,因为默认情况下,uWSGI使用uwsgi协议进行交谈,这是一个快速的二进制协议,旨在与其他服务器进行通信。

完成后,保存并关闭文件。

步骤 5 — 创建一个 systemd 单元文件

创建一个 systemd 单元文件将允许 Ubuntu 的 init 系统自动启动 uWSGI 并在服务器启动时为 Flask 应用程序提供服务。

/etc/systemd/system目录中创建一个终止在.service的单元文件,开始:

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

在文件内部,请从[单位]部分开始,该部分用于指定元数据和依赖性,在这里描述您的服务,并告诉 init 系统在实现网络目标后才启动:

1[label /etc/systemd/system/myproject.service]
2[Unit]
3Description=uWSGI instance to serve myproject
4After=network.target

接下来,打开[服务]部分,这将指定您希望该进程运行的用户和组。 让您的常规用户帐户拥有该进程,因为它拥有所有相关文件。 还将群组所有权授予www-data组,以便 Nginx 可以轻松与 uWSGI 进程进行通信。 请记住,在这里用您的用户名更换用户名:

1[label /etc/systemd/system/myproject.service]
2[Unit]
3Description=uWSGI instance to serve myproject
4After=network.target
5
6[Service]
7User=sammy
8Group=www-data

接下来,绘制工作目录并设置PATH环境变量,以便 init 系统知道该过程的可执行文件位于您的虚拟环境中。 此外,指定启动服务的命令。

请记住用自己的信息替换用户名和项目路径:

 1[label /etc/systemd/system/myproject.service]
 2[Unit]
 3Description=uWSGI instance to serve myproject
 4After=network.target
 5
 6[Service]
 7User=sammy
 8Group=www-data
 9WorkingDirectory=/home/sammy/myproject
10Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
11ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

然后添加一个[安装]部分,这将告诉系统d如果您允许该服务在启动时启动,该服务将连接到什么。

 1[label /etc/systemd/system/myproject.service]
 2[Unit]
 3Description=uWSGI instance to serve myproject
 4After=network.target
 5
 6[Service]
 7User=sammy
 8Group=www-data
 9WorkingDirectory=/home/sammy/myproject
10Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
11ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
12
13[Install]
14WantedBy=multi-user.target

这样,你的 systemd 服务文件就完成了. 现在保存并关闭它。

现在您可以启动您创建的 uWSGI 服务,并启用它以便在启动时启动:

1sudo systemctl start myproject
2sudo systemctl enable myproject

查看状态:

1sudo systemctl status myproject

您应该获得如下类型的输出:

 1[secondary_label Output]
 2 myproject.service - uWSGI instance to serve myproject
 3   Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset
 4   Active: active (running) since Mon 2021-10-25 22:34:52 UTC; 14s ago
 5 Main PID: 9391 (uwsgi)
 6    Tasks: 6 (limit: 1151)
 7   CGroup: /system.slice/myproject.service
 8           ├─9391 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.i
 9           ├─9410 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.i
10           ├─9411 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.i
11           ├─9412 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.i
12           ├─9413 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.i
13           └─9414 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.i

如果您收到任何错误,请确保在继续使用教程之前解决它们。

步骤 6 — 将 Nginx 配置为代理请求

您的 uWSGI 应用程序服务器现在应该运行,等待项目目录中的插件文件上的请求,现在您可以配置 Nginx 以使用uwsgi协议将 Web 请求传输到该插件。

首先,在 Nginx 的可用站点目录中创建一个新的服务器封锁配置文件,并将其命名为myproject,以保持与其他指南相一致:

1sudo nano /etc/nginx/sites-available/myproject

打开服务器块,并告诉 Nginx 倾听默认端口 `80。

1[label /etc/nginx/sites-available/myproject]
2server {
3    listen 80;
4    server_name your_domain www.your_domain;
5}

接下来,添加一个与每个请求匹配的位置块。在这个块中,你将包含指定一些需要设置的一般 uWSGI 参数的 uwsgi_params 文件。

 1[label /etc/nginx/sites-available/myproject]
 2server {
 3    listen 80;
 4    server_name your_domain www.your_domain;
 5
 6    location / {
 7        include uwsgi_params;
 8        uwsgi_pass unix:/home/sammy/myproject/myproject.sock;
 9    }
10}

保存并关闭文件,当你完成。

要启用您刚刚创建的 Nginx 服务器封锁配置,请将文件链接到网站启用目录:

1sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

使用该目录中的文件,您可以通过执行以下操作来测试语法错误:

1sudo nginx -t

如果返回不表示任何问题,请重新启动 Nginx 流程以阅读新配置:

1sudo systemctl restart nginx

现在重新调整防火墙,您不再需要通过端口5000访问,因此您可以删除该规则:

1sudo ufw delete allow 5000

之后,您将允许访问 Nginx 服务器:

1sudo ufw allow 'Nginx Full'

您现在应该能够在您的 Web 浏览器中导航到您的服务器的域名:

1http://your_domain

您应该看到您的应用程序输出:

Flask sample app

如果您遇到任何错误,请尝试检查以下情况:

  • sudo less /var/log/nginx/error.log:检查 Nginx 错误日志
  • sudo less /var/log/nginx/access.log:检查 Nginx 访问日志
  • sudo journalctl -u nginx:检查 Nginx 流程日志
  • sudo journalctl -u myproject:检查您的 Flask 应用程序的 uWSGI 日志

步骤7 – 确保应用程序

要确保到您的服务器的流量保持安全,您应该为您的域获得 SSL 证书。有许多方法可以做到这一点,包括从 Let's Encrypt获得免费证书, 生成自签证书,或 从其他提供商购买一个并配置 Nginx 使用它,通过遵循 如何在 Ubuntu 18.04 中创建自签 SSL 证书的步骤2到6)。

首先,添加 Ubuntu Certbot 存储库:

1sudo add-apt-repository ppa:certbot/certbot

您将需要按进入来接受。

接下来,安装 Certbot 的 Nginx 包,使用apt:

1sudo apt install python-certbot-nginx

Certbot 提供了通过插件获取 SSL 证书的各种方式。 Nginx 插件将负责重新配置 Nginx 并在必要时重新加载配置。

1sudo certbot --nginx -d your_domain -d www.your_domain

这将运行certbot--nginx插件,使用-d来指定您希望证书有效的名称。

如果这是你第一次运行certbot,你将被要求输入电子邮件地址并同意服务条款. 这样做后,certbot将与 Let’s Encrypt 服务器进行通信,然后运行一个挑战,以验证你控制的域,你正在请求证书。

如果成功,certbot 会问你想如何配置你的 HTTPS 设置:

1[secondary_label Output]
2Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
3-------------------------------------------------------------------------------
41: No redirect - Make no further changes to the webserver configuration.
52: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
6new sites, or if you're confident your site works on HTTPS. You can undo this
7change by editing your web server's configuration.
8-------------------------------------------------------------------------------
9Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

选择你的选择,然后点击ENTER。配置将被更新,Nginx将重新加载以获取新的设置。

 1[secondary_label Output]
 2IMPORTANT NOTES:
 3 - Congratulations! Your certificate and chain have been saved at:
 4   /etc/letsencrypt/live/your_domain/fullchain.pem
 5   Your key file has been saved at:
 6   /etc/letsencrypt/live/your_domain/privkey.pem
 7   Your cert will expire on 2022-01-24. To obtain a new or tweaked
 8   version of this certificate in the future, simply run certbot again
 9   with the "certonly" option. To non-interactively renew *all* of
10   your certificates, run "certbot renew"
11 - Your account credentials have been saved in your Certbot
12   configuration directory at /etc/letsencrypt. You should make a
13   secure backup of this folder now. This configuration directory will
14   also contain certificates and private keys obtained by Certbot so
15   making regular backups of this folder is ideal.
16 - If you like Certbot, please consider supporting our work by:
17
18   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
19   Donating to EFF:                    https://eff.org/donate-le

如果您在前提条件中遵循了 Nginx 安装说明,您将不再需要多余的 HTTP 配置文件许可:

1sudo ufw delete allow 'Nginx HTTP'

要验证配置,请再次导航到您的域名,使用 https://:

1https://your_domain

您应该再次看到您的应用程序输出,以及浏览器的安全指标,这应该表明该网站是安全的。

结论

在本指南中,您创建并在Python虚拟环境中保护了一个简单的Flask应用程序。您创建了一个WSGI入口点,以便任何具有WSGI能力的应用程序服务器可以与其进行交互,然后配置了uWSGI应用程序服务器以提供此功能。

Flask 是一个非常灵活的框架,旨在为您的应用提供功能,而不会过于限制结构和设计。

Published At
Categories with 技术
comments powered by Disqus