前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在Ubuntu 18.04上使用Gunicorn和Nginx为Flask应用程序提供服务

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

原创
作者头像
物花无语
修改2018-10-22 11:38:21
3.1K0
修改2018-10-22 11:38:21
举报

介绍

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

准备

在开始本指南之前,您应该:

  • 一台已经设置好可以使用sudo命令的非root账号的Ubuntu服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器
  • 安装Nginx
  • 配置为指向您的服务器的域名。如果你没有域名,建议您先去这里注册一个域名,您需要将域名解析到您的服务器,您可以使用腾讯云云解析进行快速设置。请务必创建以下DNS记录:
    • 指向服务器的公共IP地址的带有your_domain的A记录。
    • 指向服务器的公共IP地址的带有www.your_domain的A记录。
  • 熟悉WSGI规范,Gunicorn服务器将使用该规范与Flask应用程序进行通信。

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

我们的第一步是从Ubuntu存储库安装我们需要的所有部分。这包括pipPython包管理器,它将管理我们的Python组件。我们还将获得构建一些Gunicorn组件所必需的Python开发文件。

首先,让我们更新本地包索引并安装允许我们构建Python环境的包。这些将包括python3-pip一些强大的编程环境所需的一些软件包和开发工具:

代码语言:javascript
复制
sudo apt update
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

有了这些软件包,让我们继续为我们的项目创建一个虚拟环境。

第2步 - 创建Python虚拟环境

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

首先安装python3-venv软件包,安装venv模块:

代码语言:javascript
复制
sudo apt install python3-venv

接下来,让我们为Flask项目创建一个父目录。创建后移动到目录:

代码语言:javascript
复制
mkdir ~/myproject
cd ~/myproject

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

代码语言:javascript
复制
python3.6 -m venv myprojectenv

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

在虚拟环境中安装应用程序之前,需要将其激活。输入以下命令:

代码语言:javascript
复制
source myprojectenv/bin/activate

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

第3步 - 设置Flask应用程序

现在您已进入虚拟环境,可以安装Flask和Gunicorn并开始设计应用程序。

首先,让我们使用本地实例pip安装wheel,以确保我们的软件包即使丢失了轮存档也会安装:

代码语言:javascript
复制
pip install wheel

注意

无论您使用的是哪个版本的Python,在激活虚拟环境时,都应该使用pip命令(不是pip3)。

接下来,让我们安装Flask和Gunicorn:

代码语言:javascript
复制
pip install gunicorn flask

创建示例应用程序

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

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

代码语言:javascript
复制
nano ~/myproject/myproject.py

应用程序代码将存在于此文件中。它将导入Flask并实例化Flask对象。您可以使用它来定义在请求特定路由时应运行的函数:

代码语言:javascript
复制
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')

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

如果您按照初始服务器设置指南进行操作,则应启用UFW防火墙。要测试应用程序,您需要允许访问端口5000

代码语言:javascript
复制
sudo ufw allow 5000

现在,您可以键入以下内容来测试Flask应用:

代码语言:javascript
复制
python myproject.py

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

代码语言:javascript
复制
* Serving Flask app "myproject" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

访问以:5000结尾服务器的IP地址,然后在Web浏览器中:

代码语言:javascript
复制
http://your_server_ip:5000

你应该看到这样的东西:

完成后,点击终端窗口的CTRL-C以停止Flask开发服务器。

创建WSGI入口点

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

我们来调用这个文件wsgi.py

代码语言:javascript
复制
nano ~/myproject/wsgi.py

在这个文件中,让我们从我们的应用程序导入Flask实例,然后运行它:

代码语言:javascript
复制
from myproject import app
​
if __name__ == "__main__":
    app.run()

完成后保存并关闭文件。

第4步 - 配置Gunicorn

您的应用程序现在已经建立了入口点。我们现在可以继续配置Gunicorn了。

在继续之前,我们应该检查Gunicorn是否可以正确地提供应用程序。

我们可以通过简单地传递入口点的名称来实现这一点。这被构造为模块的名称(减去.py扩展名),以及应用程序中可调用的名称。在我们的例子中,这是wsgi:app

我们还将指定要绑定的接口和端口,以便应用程序将在公共可用的界面上启动:

代码语言:javascript
复制
cd ~/myproject
gunicorn --bind 0.0.0.0:5000 wsgi:app

您应该看到如下输出:

代码语言:javascript
复制
[2018-07-13 19:35:13 +0000] [28217] [INFO] Starting gunicorn 19.9.0
[2018-07-13 19:35:13 +0000] [28217] [INFO] Listening at: http://0.0.0.0:5000 (28217)
[2018-07-13 19:35:13 +0000] [28217] [INFO] Using worker: sync
[2018-07-13 19:35:13 +0000] [28220] [INFO] Booting worker with pid: 28220

访问服务器的IP地址,并:5000再次附加到Web浏览器的末尾:

代码语言:javascript
复制
http://your_server_ip:5000

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

确认其功能正常后,请按终端窗口的CTRL-C

我们现在已经完成了虚拟环境,因此我们可以将其停用:

代码语言:javascript
复制
deactivate

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

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

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

代码语言:javascript
复制
sudo nano /etc/systemd/system/myproject.service

在里面,我们将从该[Unit]部分开始,该部分用于指定元数据和依赖关系。让我们在这里描述一下我们的服务,并告诉init系统只在达到网络目标后启动它:

代码语言:javascript
复制
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

接下来,让我们打开这个[Service]部分。这将指定我们希望在其下运行进程的用户和组。让我们为该流程提供常规用户帐户所有权,因为它拥有所有相关文件。让我们给www-data团队所有权,以便Nginx可以轻松地与Gunicorn流程进行沟通。请务必使用您的用户名替换此处的用户名:

代码语言:javascript
复制
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
​
[Service]
User=sammy
Group=www-data

接下来,让我们绘制工作目录并设置PATH环境变量,以便init系统知道进程的可执行文件位于我们的虚拟环境中。我们还指定启动服务的命令。此命令将执行以下操作:

  • 启动3个工作进程(尽管您应该根据需要进行调整)
  • 在我们的项目目录中创建并绑定到Unix套接字文件myproject.sock。我们将设置一个umask值,007以便创建套接字文件,从而允许访问所有者和组,同时限制其他访问
  • 指定WSGI入口点文件名以及该文件中的Python可调用项(wsgi:app

Systemd要求我们提供Gunicorn可执行文件的完整路径,该文件安装在我们的虚拟环境中。

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

代码语言:javascript
复制
[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将此服务链接到什么。我们希望在常规多用户系统启动并运行时启动此服务:

代码语言:javascript
复制
[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服务文件就完成了。立即保存并关闭它。

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

代码语言:javascript
复制
sudo systemctl start myproject
sudo systemctl enable myproject

我们来看看状态:

代码语言:javascript
复制
sudo systemctl status myproject

你应该看到这样的输出:

代码语言:javascript
复制
● myproject.service - Gunicorn instance to serve myproject
   Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2018-07-13 14:28:39 UTC; 46s ago
 Main PID: 28232 (gunicorn)
    Tasks: 4 (limit: 1153)
   CGroup: /system.slice/myproject.service
           ├─28232 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
           ├─28250 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
           ├─28251 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
           └─28252 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007

如果您发现任何错误,请务必在继续本教程之前解决它们。

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

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

首先在Nginx的sites-available目录中创建一个新的服务器块配置文件。让我们称之为myproject确保其与指南的其余部分保持一致:

代码语言:javascript
复制
sudo nano /etc/nginx/sites-available/myproject

打开服务器块并告诉Nginx监听默认端口80。我们还告诉它使用此块来请求我们服务器的域名:

代码语言:javascript
复制
server {
    listen 80;
    server_name your_domain www.your_domain;
}

接下来,让我们添加一个匹配每个请求的位置块。在此块中,我们将包含指定需要设置的一些常规代理参数的文件proxy_params。然后我们将请求传递给我们使用该proxy_pass指令定义的套接字:

代码语言:javascript
复制
server {
    listen 80;
    server_name your_domain www.your_domain;
​
    location / {
        include proxy_params;
        proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
    }
}

完成后保存并关闭文件。

要启用刚刚创建的Nginx服务器块配置,请将文件链接到sites-enabled目录:

代码语言:javascript
复制
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

使用该目录中的文件,您可以测试语法错误:

代码语言:javascript
复制
sudo nginx -t

如果返回但未指示任何问题,请重新启动Nginx进程以读取新配置:

代码语言:javascript
复制
sudo systemctl restart nginx

最后,让我们再次调整防火墙。我们不再需要通过端口访问5000,因此我们可以删除该规则。然后我们可以允许完全访问Nginx服务器:

代码语言:javascript
复制
sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'

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

代码语言:javascript
复制
http://your_domain

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

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

  • 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证书。如果你有域名,保护你网站的最简单方法是使用腾讯云SSL证书服务,它提供免费的可信证书。腾讯云SSL证书安装操作指南进行设置。如果你没有域名,建议您先去这里注册一个域名,如果你只是使用此配置进行测试或个人使用,则可以使用自签名证书,不需要购买域名。自签名证书提供了相同类型的加密,但没有域名验证公告。关于自签名证书,你可以参考为Apache创建自签名SSL证书如何为Nginx创建自签名SSL证书这两篇文章。

首先,添加Certbot Ubuntu存储库:

代码语言:javascript
复制
sudo add-apt-repository ppa:certbot/certbot

你需要按下ENTER接受。

apt安装Certbot的Nginx软件包:

代码语言:javascript
复制
sudo apt install python-certbot-nginx

Certbot提供了多种通过插件获取SSL证书的方法。Nginx插件将负责重新配置Nginx并在必要时重新加载配置。要使用此插件,请键入以下内容:

代码语言:javascript
复制
sudo certbot --nginx -d your_domain -d www.your_domain

certbot--nginx插件一起运行,-d用于指定我们希望证书有效的名称。

如果这是您第一次运行certbot,系统将提示您输入电子邮件地址并同意服务条款。执行此操作后,certbot将与Let的加密服务器通信,然后运行质询以验证您是否控制了您要为其申请证书的域。

如果成功,certbot将询问您要如何配置HTTPS设置:

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

选择你的选择然后点击ENTER。配置将更新,Nginx将重新加载以获取新设置。certbot将结束一条消息,告诉您进程是否成功以及您的证书存储位置:

代码语言:javascript
复制
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/your_domain/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/your_domain/privkey.pem
   Your cert will expire on 2018-07-23. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

如果您遵循先决条件中的Nginx安装说明,则不再需要冗余HTTP配置文件容量:

代码语言:javascript
复制
sudo ufw delete allow 'Nginx HTTP'

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

代码语言:javascript
复制
https://your_domain

您应该再次看到您的应用程序输出,以及浏览器的安全指示器,该指示符应指示该站点是安全的。

结论

在本指南中,您在Python虚拟环境中创建并保护了一个简单的Flask应用程序。您创建了一个WSGI入口点,以便任何支持WSGI的应用程序服务器都可以与它进行交互,然后配置Gunicorn应用程序服务器以提供此功能。之后,您创建了一个systemd服务文件,以便在引导时自动启动应用程序服务器。您还创建了一个Nginx服务器块,它将Web客户端流量传递到应用程序服务器,通过Let's Encrypt将外部请求转发到服务器并保护流量。

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

更多Ubuntu教程请前往腾讯云+社区学习更多知识。


参考文献:《How To Serve Flask Applications with Gunicorn and Nginx on Ubuntu 18.04》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
    • 准备
      • 步骤1 - 从Ubuntu存储库安装组件
        • 第2步 - 创建Python虚拟环境
          • 第3步 - 设置Flask应用程序
            • 创建示例应用程序
            • 创建WSGI入口点
          • 第4步 - 配置Gunicorn
            • 步骤5 - 将Nginx配置为代理请求
              • 第6步 - 保护应用程序
                • 结论
                相关产品与服务
                SSL 证书
                腾讯云 SSL 证书(SSL Certificates)为您提供 SSL 证书的申请、管理、部署等服务,为您提供一站式 HTTPS 解决方案。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档