Ubuntu 18.04 LTS 上的python web 环境搭建
教程中采用的是AWS的 Lightsail Ubuntu 18.04 LTS服务器作为实例。
STEP1 – 安装Python开发组件
首先,我们先更新软件包,并且安装所需要的组件
sudo apt-get update && sudo apt-get upgrade
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
STEP2 - 创建Python虚拟环境
接下来我们将设置一个为flask应用准备的虚拟环境,使得应用与其他python程序隔离开来。
首先我们创建一个应用目录mewtea,创建目录后切换到对应目录下。
mkdir ~/mewtea
cd ~/mewtea
然后我们安装python3-venv软件包以实现虚拟环境功能
sudo apt install python3-venv
为mewtea项目创建虚拟环境,在mewtea目录下执行:
python3 -m venv mewtea-env
激活虚拟环境
source mewtea-env/bin/activate
执行后命令行将会显示当前所在的虚拟环境,命令行前显示像这样 :
(mewtea-env ) user @ host :~/ mewtea $
STEP3 – 安装和配置Flask应用
首先,我们先安装wheel
pip install wheel
注意,由于前面我们将python3指定到了这个环境下,因此这里使用的是pip而不是pip3,如果在执行pip时提示有更新,也可执行更新的命令,但是该更新仅针对本项目,全局、其他项目下的pip版本依然是原始版本。
接下来,让我们安装Flask和uWSGI:
pip install uwsgi flask
配置环境
现在我们简单地创建一个python的web服务,来进行环境的配置。我们先简单地创建一个index文件,来作为程序主文件。
nano ~/mewtea/index.py
将以下内容复制到文件中,并保存。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1 style='color:#f78da7'>Hello Mewtea!</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
注意缩进,如果缩进有误将会报错。文件定义了访问页面时将会显示的内容,编写完成后,按下ctrl+X,再输入y 保存文件。
AWS的服务器可在服务器管理页很轻松的针对防火墙的规则进行设置,我们添加一个5000端口的访问允许,像下图这样。
使用azure,aliyun等也有类似的页面设置,如果,在您的服务器提供商没有提供防火墙设置页时,你也可以采用以下命令进行允许访问:
sudo ufw allow 5000
现在我们运行该python程序,试试访问结果:
python index.py
注意:这里使用的是也是python而不是python3,原因同前
运行后,你可能会发现如下输出,提示我们不要在生产环境下使用,我们先不管它,接下来再配置这个。
* Serving Flask app "mewtea" (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://您的服务器ip地址:5000 看看是否有正确的输出了呢。
如果出现其他报错,如语法错误,请检查index.py的文件缩进是否正确。
看到正确输出后,我们按CTRL+C关掉该服务,接下来配置WSGI入口点
创建WSGI入口点
接下来我们创建一个wsgi.py文件,来作为我们应用程序的入口。
nano ~/myproject/wsgi.py
将以下内容复制至文件中,同样的,请注意缩进。
from index import app
if __name__ == "__main__":
app.run()
文件中我们引入了mewtea应用的index文件,编写完成后,按下ctrl+X,再输入y 保存文件。
STEP4 – 配置uWSGI
现在,我们已经为python应用程序创建了入口文件,接下来我们对uWSGI进行配置。
测试uWSGI服务
我们通过一个简单的指令,来测试我们创建的服务是否正常工作,通过usgi 引用我们创建的wsgi文件(省略扩展名.py),调用文件中的app来实现的。
我们还指定了它的协议为HTTP,以及端口号为5000.
uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app
同样的,我们访问 http://您的服务器ip地址:5000 ,看看是否有正确的输出。
看到正确输出后,我们按CTRL+C关掉该服务。
我们已经完成了整个虚拟环境的搭建,现在我们退出虚拟环境。
deactivate
配置uWSGI
前面我们已经测试了uWSGI服务是可用的,但是实际使用上我们将采用一个更合理的方法以便更轻松的对应用进行管理。
我们在项目的目录中创建一个配置文件usgi_conf.ini :
nano ~/myproject/myproject.ini
[uwsgi]
module = wsgi:app
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true
die-on-term = true
保存并退出。
在该文件中,其中:
[uwsgi]
module = wsgi:app
指的是 uWSGI应用设置所应用的模块,即我们先前创建的 wsgi.py
,去掉了拓展名。
master = true
processes = 5
指的是 uWSGI将以主模式启动,并生成五个工作进程来提供实际请求。
socket = mewtea.sock
chmod-socket = 660
vacuum = true
在之后,我们将配置Nginx传递请求,而不是在网络端口直接暴露uWSGI,因此我们将创建mewtea.sock来与Nginx进行通信,chmod-socket = 660则是修改sock文件的权限以便于于Nginx进行通信。vacuum = true :同时我们还将在服务停止时删除sock文件。
STEP 5 – 创建systemd文件
为了更方便的操作应用程序服务,我们创建一个systemd单件将允许Ubuntu的init系统自动启动uWSGI,并在服务器启动时为Flask应用程序提供服务。
首先,我们需要在/etc/systemd/system目录中创建以.service结尾的文件。
sudo nano /etc/systemd/system/mewtea.service
将下列内容复制到文件中:
[Unit]
Description=uWSGI instance to serve mewtea
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/mewtea
Environment="PATH=/home/ubuntu/mewtea/mewtea-env/bin"
ExecStart=/home/ubuntu/mewtea/mewtea-env/bin/uwsgi --ini wsgi_conf.ini
[Install]
WantedBy=multi-user.target
保存并关闭,在上面的配置中,
我们将从[Unit]
部分开始,该部分用于指定元数据和依赖关系。 在Description中添加服务描述,并告诉init系统只在达到网络目标后启动它,
然后[Service]
中,指定了运行进程的用户与用户组,并指定了项目的路径。
这样,我们使用指令,就可以对我们的应用进行开启了:
sudo systemctl start mewtea
sudo systemctl enable mewtea
我们看看应用状态:
sudo systemctl status mewtea
显示如下内容
● mewtea.service - uWSGI instance to serve mewtea
Loaded: loaded (/etc/systemd/system/mewtea.service; disabled; vendor preset: enabled)
Active: active (running) since Sun 2019-04-21 19:33:42 UTC; 3 days ago
Main PID: 31575 (uwsgi)
Tasks: 6
Memory: 23.7M
CPU: 13.874s
CGroup: /system.slice/mewtea.service
├─31575 /home/ubuntu/mewtea/mewtea/bin/uwsgi --ini wsgi_conf.ini
├─31580 /home/ubuntu/mewtea/mewtea/bin/uwsgi --ini wsgi_conf.ini
├─31581 /home/ubuntu/mewtea/mewtea/bin/uwsgi --ini wsgi_conf.ini
├─31582 /home/ubuntu/mewtea/mewtea/bin/uwsgi --ini wsgi_conf.ini
├─31583 /home/ubuntu/mewtea/mewtea/bin/uwsgi --ini wsgi_conf.ini
└─31584 /home/ubuntu/mewtea/mewtea/bin/uwsgi --ini wsgi_conf.ini
如果运行时报错了,请务必先解决错误,在进行之后的操作。
STEP 6 – 配置 Nginx 代理应用
我们应该让应用程序保持运行,以确保mewtea.sock正常存在,使得应用程序的连接能正常地传递给Nginx。
首先在我们在 Nginx 的 sites-available 目录中创建一个新的服务器块配置文件。 同样地,我们命名为mewtea,当然你也可以使用其他名称。
sudo nano /etc/nginx/sites-available/mewtea
配置服务,设置Nginx监听默认端口80 。同时设置一个访问的域名,如mewtea.org,并指定sock位置。您可以直接复制一下内容:
server {
listen 80;
server_name your_domain mewtea.org;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/sammy/myproject/mewtea.sock;
}
}
编写完成后保存并关闭文件。
接下来我们启用刚刚编写的配置文件,将配置文件链接到sites-enabled 目录:
sudo ln -s /etc/nginx/sites-available/mewtea /etc/nginx/sites-enabled
编写完成后保存并关闭文件。
接下来我们启用刚刚编写的配置文件,将配置文件链接到sites-enabled 目录:
sudo ln -s /etc/nginx/sites-available/mewtea /etc/nginx/sites-enabled
然后我们使用以下命令,来检查一下配置文件是否存在语法错误:
sudo nginx -t
如果没有问题,我们重新启动 Nginx 以读取新的配置。
sudo systemctl restart nginx
允许Nginx通过防火墙:
sudo ufw allow 'Nginx Full'
此时,我们输入域名,看看是否能正常访问了 如:http://mewtea.org
大功告成。
现在,我们可以取消之前设置的 5000 端口的允许访问了,在AWS的控制面板中删掉之前允许的5000端口,azure,aliyun等服务提供商的控制面板中也有类似的设置,当然如果没有的话,可以使用以下命令:
sudo ufw delete allow 5000
如果在出现报错,请检查以下内容
如果您遇到任何错误,请尝试检查以下内容:
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日志。
STEP 7 – 配置更安全的https
施工中
参考资料
本文多数内容引用自 https://www.howtoing.com/how-to-serve-flask-applications-with-uswgi-and-nginx-on-ubuntu-18-04
同时参考了以下资料:
https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/ThingsToKnow.html
https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/Upstart.html
https://stackoverflow.com/questions/49836676/error-after-upgrading-pip-cannot-import-name-main