介绍
在本指南中,您将使用 Ubuntu 18.04 上的 Flask 微框架构建一个 Python 应用程序。本文的大部分内容将是如何设置 Gunicorn 应用程序服务器以及如何启动应用程序并配置 Nginx作为前端反向代理。
前提条件
要完成本教程,您将需要:
- 安装了 Ubuntu 18.04 的服务器,具有 sudo 特权的非 root 用户,并启用了防火墙。 遵循我们的 初始服务器设置指南以获取指导。
- Nginx 已安装,遵循 How To Install Nginx on Ubuntu 18.04 的 步骤 1 和 2。
- 配置域名以指向您的服务器。 您可以在 Namecheap上购买一个或在 Freenom上免费获得一个。 您可以学习如何指向域名到 DigitalOcean 通过遵循相关的 域名和 DNS 的文档。 请确保创建以下 DNS 记录:
步骤 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
然后按Y
和ENTER
来做到这一点。
如果您在前提条件中遵循了初始服务器设置指南,则应启用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
你应该得到一些如下的东西:
当你完成时,在终端窗口中按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
您的应用程序的输出将产生如下:
当您确认它正常工作时,请在终端窗口中按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
您的应用程序的输出将出现在您的浏览器中:
如果您遇到任何错误,请尝试检查以下情况:
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 是一个非常灵活的框架,旨在为您的应用提供功能,而不会过于限制结构和设计。