用Nginx 和 Gunicorn 在ubuntu上发布 Flask 服务应用

本文介绍用Nginx 和 Gunicorn 在ubuntu上发布 Flask 服务应用,Ubuntu 的版本原文是18,我的测试环境是20。

学习链接:https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-18-04

前提条件

本文内容不包含nginx 的安装,可以参考:Nginx 在Ubuntu 上的安装,测试

本文需要你有一个非root 的用户,但属于sudo组,如果没有,在根用户下如下操作:

  1. adduser sammy

  2. usermod -aG sudo sammy

安装

执行下面操作:

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

建立一个python虚拟环境

安装虚拟环境程序

sudo apt install python3-venv

建立一个工作目录: 

mkdir ~/myproject
cd ~/myproject

在目录里建立一个虚拟环境:

python3.6 -m venv myprojectenv

 上面是原文的操作,可能原文是ubuntu18的原因,python3的版本是3.6, ubuntu20 的版本是3.8,所以我的操作是:

python3.8 -m venv myprojectenv

我估计直接python3 -m venv myprojectenv 应该也是可以的,否则还要查看自己python3的版本。 

在安装其他应用之前,激活虚拟环境:

source myprojectenv/bin/activate

在虚拟环境安装 gunicorn flask,在虚拟环境里不要用pip3,而是pip

pip install gunicorn flask

建立简单样例应用

建立一个非常简单的Flask 应用:

nano ~/myproject/myproject.py

文件内容为:

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')

如果有防火墙,需要设置:

sudo ufw allow 5000

 现在启动我们的应用:

python myproject.py

应该可以看到:

Output
* 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)

在浏览器里输入:

http://your_server_ip:5000

这里一定要用你主机的ip地址替代上面的your_server_ip。 

你应该可以看到

 说明我们的简单Flask 应用是成功的。

建立WSGI入口点

建立一个wsgi 入口点文件:

nano ~/myproject/wsgi.py

文件内容为:

from myproject import app

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

配置Gunicorn

首先,我们测试 Gunicorn 应用:

cd ~/myproject
gunicorn --bind 0.0.0.0:5000 wsgi:app

应该可以看到输出:

Output
[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

与上面的测试flask 应用一样,在浏览器里输入ip地址和端口号:

http://your_server_ip:5000

输出的结果和上面应该一样:

退出环境:

deactivate

下面建立一个看守程序:

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

 文件内容为:

[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

 这里假定用户名是sammy,还有环境目录是否一致,都需要你看情况做更改。

这里对ExecStart 行做个说明:

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

现在我们启动服务,并使能启动时自动执行。

sudo systemctl start myproject
sudo systemctl enable myproject

我们检查运行状态 :

sudo systemctl status myproject

应该有如下类似输出:

Output
● 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

 配置Nginx

建立一个Nginx 的站点配置文件

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

文件内容为:

server {
    listen 80;
    server_name your_domain www.your_domain;

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
    }
}

特别注意:your_domain 应该用你实际的域名代替,sammy/myprojecct/project 这部分也要修改成你的一致

对于我的理解来说,sammy/project 指工作目录 WorkingDirectory, myproject.sock 指Unix套接字文件 unix:myproject.sock,对应/etc/systemd/system/myproject.service 里面的内容。

使能Nginx站点配置块(server block configuration):

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

使能之后,可以测试nginx 的配置:

sudo nginx -t

如果有错误,可以检查上面配置块文件的语法等,也要检查/etc/nginx/sites-enabled 目录下还有除default外还有的文件,删除不必要的文件。因为每个文件都加入到配置中。

如果没有错误,就可以重新启动nginx:

sudo systemctl restart nginx

因为我们不再需要防火墙5000端口号了,可以修改防火墙如下:

sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'

在浏览器地址里输入你的域名:

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 日志.

介绍到此。在原文中还介绍了应用安全,我没弄懂,有需要可以看看原文。

猜你喜欢

转载自blog.csdn.net/leon_zeng0/article/details/108837619