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

介绍

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

前提条件

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

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

第一步是从默认的Ubuntu存储库中安装所有必要的包,其中包括Python包管理器pip,它将管理您的Python组件,您还将获得构建一些Gunicorn组件所需的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

您的提示将更改,表示您现在在虚拟环境中运作,读取如下:

1(myprojectenv)\ssammy@host:~/myproject$

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

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

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

1pip install wheel

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

接下来,安装Flask和Gunicorn:

1pip install gunicorn flask

现在你已经有了Flask,你可以在下一步创建一个基本的应用程序。

创建样本应用程序

由于Flask是一个微框架,它不包括更多功能框架可能的许多工具,Flask主要是作为一个模块,您可以导入您的项目,以帮助初始化Web应用程序。

虽然您的应用程序可能更复杂,但我们将创建我们的Flask应用程序在一个单一的文件中,名为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: This is a development server. Do not use it in a production deployment.
5   Use a production WSGI server instead.
6 * Debug mode: off
7 * Running on all addresses.
8   WARNING: This is a development server. Do not use it in a production deployment.
9 * Running on http://your_server_ip:5000/ (Press CTRL+C to quit)

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

1http://your_server_ip:5000

你应该得到一些如下的东西:

Flask sample app

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

创建 WSGI 入口点

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

使用您喜爱的文本编辑器创建一个新的文件,并命名它. 在这里,我们将命名该文件 wsgi.py:

1nano ~/myproject/wsgi.py

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

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

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

步骤 4 – 配置 Gunicorn

你的应用程序现在是用一个入口点创建写的,你可以继续配置Gunicorn。

但首先,更改到适当的目录:

1cd ~/myproject

接下来,您可以检查Gunicorn能否正确地服务应用程序,通过将您的入口点的名称传递给它,这是构建为模块的名称(减去.py扩展),加上应用程序内可调用的名称。

您还将指定接口和端口,以便应用程序在公开可用的接口上启动:

1gunicorn --bind 0.0.0.0:5000 wsgi:app

您将收到如下的输出:

1[secondary_label Output]
2[2021-11-19 23:07:57 +0000] [8760] [INFO] Starting gunicorn 20.1.0
3[2021-11-19 23:07:57 +0000] [8760] [INFO] Listening at: http://0.0.0.0:5000 (8760)
4[2021-11-19 23:07:57 +0000] [8760] [INFO] Using worker: sync
5[2021-11-19 23:07:57 +0000] [8763] [INFO] Booting worker with pid: 8763
6[2021-11-19 23:08:11 +0000] [8760] [INFO] Handling signal: int
7[2021-11-19 23:08:11 +0000] [8760] [INFO] Shutting down: Master

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

1http://your_server_ip:5000

您的应用程序的输出将产生如下:

Flask sample app

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

从现在开始,你已经完成了你的虚拟环境,关闭它:

1deactivate

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

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

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

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

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

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

接下来,创建一个[服务]部分。这将指定您希望该过程运行的用户和组。 提供您的常规用户帐户所有权,因为它拥有所有相关文件。 另外,给组所有权给 www-data组,以便 Nginx 能够与 Gunicorn 流程进行通信。 请记住,在这里用您的用户名更换用户名:

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

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

  • 启动 3 个工人进程(虽然你应该根据需要调整)
  • 在项目目录中创建并绑定一个 Unix 接口文件, myproject.sock.
  • 设置一个 umask 值为 007,以便接口文件被创建以提供访问给所有者和组,同时限制其他访问
  • 指定 WSGI 入口点文件名,以及该文件中的 Python 可调用(wsgi:app)

Systemd 要求您为 Gunicorn 执行程序提供完整的路径,该路径安装在您的虚拟环境中。

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

 1[label /etc/systemd/system/myproject.service]
 2[Unit]
 3Description=Gunicorn 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/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

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

 1[label /etc/systemd/system/myproject.service]
 2[Unit]
 3Description=Gunicorn 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/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
12
13[Install]
14WantedBy=multi-user.target

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

现在开始您创建的 Gunicorn 服务:

1sudo systemctl start myproject

然后启用它以便在 boot 上启动:

1sudo systemctl enable myproject

查看状态:

1sudo systemctl status myproject

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

 1[secondary_label Output]
 2 myproject.service - Gunicorn instance to serve myproject
 3   Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset
 4   Active: active (running) since Fri 2021-11-19 23:08:44 UTC; 6s ago
 5 Main PID: 8770 (gunicorn)
 6    Tasks: 4 (limit: 1151)
 7   CGroup: /system.slice/myproject.service
 8       	├─9291 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
 9       	├─9309 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
10       	├─9310 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
11       	└─9311 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
12

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

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

您的 Gunicorn 应用程序服务器现在应该运行,等待项目目录中的插槽文件上的请求。

首先,在 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}

接下来,添加一个与每个请求匹配的位置块。在这个块中,包括指定一些需要设置的一般代理参数的 proxy_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 proxy_params;
 8        proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
 9    }
10}

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

要启用您创建的 Nginx 服务器块配置,请将文件链接到网站启用目录. 您可以通过运行ln命令和-s旗来创建一个象征性的或 soft 链接,而不是一个 hard link:

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 应用程序的 Gunicorn 日志.

步骤 6 – 确保应用程序

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

首先,使用snap安装Certbot:

1sudo snap install --classic certbot

您的输出将显示当前版本的 Certbot,并表示成功安装:

1[secondary_label Output]
2certbot 1.21.0 from Certbot Project (certbot-eff✓) installed

接下来,创建一个符号链接到新安装的 /snap/bin/certbot 可执行从 /usr/bin/ 目录. 这将确保 certbot 命令可以在您的服务器上正确运行:

1sudo ln -s /snap/bin/certbot /usr/bin/certbot

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

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

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

如果这是您第一次运行certbot,您将被要求输入电子邮件地址并同意服务条款。这样做后,certbot将与 Let’s Encrypt 服务器进行通信,以要求您的域名获得证书。

 1[secondary_label Output]
 2Successfully received certificate.
 3Certificate is saved at: /etc/letsencrypt/live/jeanellehorcasitasphd.com/fullchain.pem
 4Key is saved at:         /etc/letsencrypt/live/jeanellehorcasitasphd.com/privkey.pem
 5This certificate expires on 2022-03-03.
 6These files will be updated when the certificate renews.
 7Certbot has set up a scheduled task to automatically renew this certificate in the background.
 8
 9Deploying certificate
10Successfully deployed certificate foryour_domain to /etc/nginx/sites-enabled/myproject
11Successfully deployed certificate for your_domain to /etc/nginx/sites-enabled/myproject
12Congratulations! You have successfully enabled HTTPS on https://your_domain and https://your_domain
13
14- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
15If you like Certbot, please consider supporting our work by:
16 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
17 * Donating to EFF:                    https://eff.org/donate-le

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

1sudo ufw delete allow 'Nginx HTTP'

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

1https://your_domain

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

结论

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

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

Published At
Categories with 技术
comments powered by Disqus