上一篇我们谈到了总的解决方案,一起探索了flask项目部署前的上传准备过程,以及分享了几个好用的软件和python模块,若有对上一篇文章感兴趣的朋友,可以跳过去看一下
传送门【https://blog.csdn.net/weixin_39212776/article/details/81318553】
这篇文章我们主要来解决的是flask项目云上正式部署的问题,所以,如果你只关注云上部署的部分,这篇文章也是值得借鉴的。下面我会按照我探索过得可行的思路来写,也会继续分享一些我们在部署过程中容易踩到的坑。
如果你想在一台网络服务器上配置多个web server,改文章一样适用,在最后关于Nginx的配置会详解
在上一篇文章完成后,我们的flask项目已经被打包并压缩为tar.bz2的格式发送到云主机中了,如若没有的可以查看我的上一篇文章,那里将为你详细讲解,这里我们不再赘述。
ssh root@云主机的公网ip地址
root@云主机的公网ip地址's password:#输入密码,隐藏了的,不要以为自己键盘坏掉了
# 出现以下说明登录成功了,也就是成功连接上我们自己的云主机了,
# 我们便可以通过命令行控制它了
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-117-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Welcome to Alibaba Cloud Elastic Compute Service !
Last login: Tue Jul 31 13:05:05 2018 from 101.207.0.179
根据项目的需求安装python2.x或python3.x
Ubuntu 的默认环境已经预装 python 2.7 ,所以如果我们的项目的运行环境只需要python2.7的版本就行了,我们就无需装python3了,此时只需要安装 python 的 pip 安装工具即可,推荐一篇好文章,快速安装:
【https://www.cnblogs.com/smail-bao/p/6483759.html】
那如果我们的项目是所依赖的环境是python3以上的版本,那么我们就有必要安装一个python3.几了,同样的推荐一篇简短的文章:
【https://blog.csdn.net/Qin605/article/details/77763541】
使用pip安装python项目部署的必备利器——virtualenv(虚拟环境)
在使用pip前先确定自己的pip是属于python2的还是python3的,因为不同的python版本的pip其所装的第三方包也是属于各自的主人python版本的,这一步不弄清楚在后面会吃很多亏的,我就是那因为在这样,导致我装的virtualenv是属于python2版本的,而我的flask项目是属于python3版本的,后面发现错了才后悔莫及啊!可以用如下命令检查pip的版本极其属于哪个python版本:
root@WeiLy:~# pip -V
pip 10.0.1 from /usr/local/lib/python2.7/dist-packages/pip (python 2.7)
看到了吧,我的pip是是属于python2的,那我们如果测试一下pip3呢,又会是什么样的呢?
root@WeiLy:~# pip3 -V
pip 10.0.1 from /usr/local/lib/python3.6/dist-packages/pip (python 3.6)
这下只到了吧,我们装的python3自带pip工具,但是改名为pip3了,你如果觉得这样不爽也可以给pip3重命名为pip嘛,so easy 啦,只需一个命令便可使pip软链接到pip3,但是要注意貌似过一段时间系统又会给重置回来哦,但是现改现用还是有效的嘛
提示(可以先跳过这个提示,若后面遇到这个问题再回来解决,没有则罢):
如若sudo时遇到提示“unable to resolve host xxxx(XXXX是主机名)”时,我们可以稍作更改就可以让这个提示消失了:
既然是host的问题,那么我们就进入/etc/hosts看看
输入指令: sudo vi /etc/hosts
cd /etc/hosts sudo vi /etc/hosts
显示
127.0.0.1 ubuntu # 改为我们的主机名XXX # The following lines are desirable for IPv6 capable hosts 。。。。。。。。。。。。。。省略
这里默认的主机名是ubuntu而没有我们的xxxx
我在这里发现了问题的源头:我改了主机名,而/etc/hosts这个文件的内容没有更改。把ubuntu改成xxxx就好了!
sudo alias pip='pip3'
搞清楚这些后,我们就可以安装我们需要的版本的virtualenv了,我这里安装python3.6版本的virtualenv
sudo pip install virtualenv
安装Nginx
[Nginx| http://nginx.com/ ]是轻量级、性能强、占用资源少,能很好的处理高并发的反向代理软件。起初我也不知道为什么要用Nginx,心里想难到不可以直接运行Flask项目,就像在自己的电脑上测试时也没有安装这个东西啊?一头雾水是吧!后面搜索了解一番后才渐渐开始明白:Flask ,Django 自带的web server的目的就是用于开发,而不是生产环境。他们俩本身是web framework而不是web server. 他们自带的server应该都只能开单进程,在自己测试时,我们的目的很单纯,请求程序的人也不多,我们的后台自然很安全,但是一旦服务器上线了那个就大不同了,用户的目的不像我们那样单纯,而且他们人多会疯狂发起请求,靠我们不专业处理请求的flask自带的web server怎么处理得过来呢,所以我们当然要靠牛掰的Nginx来帮忙咯。
sudo apt-get install nginx
安装好Nginx后,系统会默认创建一个目录“/var/www/html”,若通过公网ip地址能够看到一个大写的Nginx界面就说明成功了。
先装好,不用用管他,下面我们再谈配置的问题
解压从本地传到flask项目的压缩包文件到指定目录
将我们之前上传的压缩包解压到”/var/www/”下(我们一般使用Nginx默认的根目录),命令:
mv xxx.tar.bz2 /var/www # 将文件移动到目标目录下
tar -zxvpf xx.tar.gz # 再解压到当前目录
用“ll”便可看到压缩文件已经被解压了,此时压缩文件也没什么用了,可以删了!
将数据库sql文件导入云主机中的mysql数据库
如果你的云主机已经安装了mysql数据库
直接在包含sql文件的flask项目目录下执行命令:
mysql -u 用户名 -p 数据库名 < 数据库名.sql
输入数据库密码:
如果你的云主机没有安装mysql数据库
请安装后再导入数据库文件,安装很简单,方法自行百度。
在flask项目下创建虚拟环境
# 注明:我的项目名叫team_plus
root@WeiLy:~# cd /var/www/my_flask # 切换到flask项目的目录中
root@WeiLy:/var/www/team_plus# virtualenv venv # 创建虚拟环境,看到如下说明成功
>> New python executable in venv/bin/python
>> Installing setuptools, pip...done.
root@WeiLy:/var/www/team_plus# ls venv/bin/ # 查看虚拟环境所属的python版本
activate activate_this.py easy_install-3.6 pip3 python3 uwsgi
activate.csh chardetect flask pip3.6 python3.6 wheel
activate.fish easy_install pip python python-config
# 有看到3.6出现,说明刚创建的venv虚拟环境是依赖于python3.6的
# 如果不是你想要的python版本的虚拟环境,你可以按如下做:
root@WeiLy:/var/www/team_plus# virtualenv -p /usr/bin/python3.6 venv
# python3.6可改为其它python版本 venv是虚拟环境的名字
# 知道能确定这个venv是自己项目需要的python版本的虚拟环境这一步才算成功哦,不然后面都是白费
OK,此时的目录结构应该为:
www/
└── my_flask
│ ├── logs // logs装日志文件
│ └── venv //虚拟目录
│ │ ├── bin
│ │ │ ├── activate
│ │ │ ├── easy_install
│ │ │ ├── gunicorn
│ │ │ ├── pip
│ │ │ └── python
│ │ ├── include
│ │ │ └── python3.6 -> /usr/include/python3.6
│ │ ├── lib
│ │ │ └── python3.6
│ │ ├── local
│ │ │ ├── bin -> /home/shenye/shenyefuli/bin
│ │ │ ├── include -> /home/shenye/shenyefuli/include
│ │ │ └── lib -> /home/shenye/shenyefuli/lib
│ └── app //Flask 程序目录
│ │ └── __init__.py //这是程序包文件。这个目录下还有其它的文件此处略过
│ ├── manage.py
│ ├── requirements.txt
│ ├── my_flask.sql // 移植的SQL文件,如果没有SQL移植就没有这个文件
安装uwsgi包
我刚接触这个东西时,我也不知道这个东西时干嘛用的,据说是flask项目的生产环境,下面我们就一起来了解一下开发环境、生产环境的区别吧,这会然我们的思路更清晰呢!
生产环境、开发环境的区别
来自【https://blog.csdn.net/yangzaiqiu1986814/article/details/51658293】
项目部署环境一般可分为三种:生产环境,测试环境,开发环境
开发环境:开发环境时程序猿们专门用于开发的服务器,配置可以比较随意,为了开发调试方便,一般打开全部错误报告和测试工具,是最基础的环境。开发环境的分支,一般是feature分支。
测试环境:一般是克隆一份生产环境的配置,一个程序在测试环境工作不正常,那么肯定不能把它发布到生产服务器上,是开发环境到生产环境的过度环境。测试环境的分支一般是develop分支,部署到公司私有的服务器或者局域网服务器上,主要用于测试是否存在bug,一般会不让用户和其他人看到,并且测试环境会尽量与生产环境相似。
生产环境: 生产环境是指正式提供对外服务的,一般会关掉错误报告,打开错误日志,是最重要的环境。部署分支一般为master分支。
三个环境也可以说是系统开发的三个阶段:开发->测试->上线,其中生产环境也就是通说的真实的环境,最后交给用户的环境。
什么是uwsgi
那到底什么uwsgi呢?我们来看一段话:
WSGI
WSGI是一种WEB服务器==网关接口==。 是一个Web服务器(如nginx)与应用服务器(如uWSGI)通信的一种规范(协议)。
在生产环境中使用WSGI作为python web的服务器。Python Web服务器网关接口,是Python应用程序或框架和Web服务器之间的一种接口,被广泛接受。WSGI没有官方的实现, 因为WSGI更像一个协议,只要遵照这些协议,WSGI应用(Application)都可以在任何服务器(Server)上运行。
uWSGI
uWSGI实现了WSGI的所有接口,是一个快速、自我修复、开发人员和系统管理员友好的服务器。uWSGI代码完全用C编写,效率高、性能稳定。
uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信。uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型。
uWSGI 是一个全功能的 HTTP 服务器,他要做的就是把 HTTP 协议转化成语言支持的网络协议。比如把 HTTP 协议转化成 WSGI 协议,让 Python 可以直接使用。
uwsgi 是一种 uWSGI 的内部协议,使用二进制方式和其他应用程序进行通信。
来自【https://blog.csdn.net/mnszmlcd/article/details/78819237】
进入虚拟环境,这是下面的基础
root@WeiLy:/var/www/team_plus# source venv/bin/activate
(venv) root@WeiLy:/var/www/team_plus#
先安装依赖包,后面安装uwsgi才能成功!
我在多次在虚拟环境中安装uwsgi时都会报如下的错:
(venv) root@WeiLy:/var/www/team_plus# pip3 install uwsgi
对应的错误信息如下:
[thread 0][x86_64-linux-gnu-gcc -pthread] core/config_py.o
*** uWSGI compiling embedded plugins ***
[thread 0][x86_64-linux-gnu-gcc -pthread] plugins/python/python_plugin.o
[thread 1][x86_64-linux-gnu-gcc -pthread] plugins/python/pyutils.o
In file included from plugins/python/python_plugin.c:1:0:
plugins/python/uwsgi_python.h:2:20: fatal error: Python.h: 没有那个文件或目录
compilation terminated.
In file included from plugins/python/pyutils.c:1:0:
plugins/python/uwsgi_python.h:2:20: fatal error: Python.h: 没有那个文件或目录
compilation terminated.
----------------------------------------
Command "/home/windblow/Desktop/windcontrlenv/bin/python3.5 -u -c "import
_yknw2vb/uwsgi/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install
--record /tmp/pip-w10pyemd-record/install-record.txt --single-version-externally-managed --
compile --install-headers /home/windblow/Desktop/windcontrlenv/include/site/python3.5/uwsgi"
failed with error code 1 in /tmp/pip-build-_yknw2vb/uwsgi/
在几乎绝望的时候看到了这篇文章,才得以解决:
【https://blog.csdn.net/windblew/article/details/79613893】
其解决方式如下:
在安装之前应该先把 libpython3.x-dev 安装了(x对应你使用的是3点几版本。命令apt-get install libpython3.x-dev),才能够正常安装uwsgi。
(venv) root@WeiLy:/var/www/team_plus# sudo apt-get install libpython3.6-dev
安装依赖后:
# 再执行如下:
(venv) root@WeiLy:/var/www/team_plus# pip3 install uwsgi
# 下面说明成功安装:
Collecting uwsgi
Using cached uwsgi-2.0.17.tar.gz
Building wheels for collected packages: uwsgi
Running setup.py bdist_wheel for uwsgi ... done
Stored in directory: /home/windblow/.cache/pip/wheels/94/c9/63/e7aef2e745bb1231490847ee3785e3
d0b5f274e1f1653f89c5
Successfully built uwsgi
Installing collected packages: uwsgi
Successfully installed uwsgi-2.0.17
为了我们安装的uwsgi是属于我们项目所需的python x.x版本的,我们一定要用如下命令检查
(venv) root@WeiLy:/var/www/team_plus# uwsgi --python-version
如果不是,先退出虚拟环境再更改系统默认的python版本,再卸载掉之前装的uwsgi,再重装
(venv) root@WeiLy:/var/www/team_plus# deactivate
更改系统默认的python版本
root@WeiLy:/var/www/team_plus# cd /user/bin
root@WeiLy:/var/www/team_plus# rm python
root@WeiLy:/var/www/team_plus# ln -s python3.6 python
卸载掉之前装的uwsgi,再重装
root@WeiLy:/var/www/team_plus# pip3 uninstall uwsgi
root@WeiLy:/var/www/team_plus# pip3 install uwsgi
再检查,如若还是不符合,那只能靠自己去寻找解决方案了…
利用之前导出的requestments.txt文件批量安装依赖包
切记两点:
(venv) root@WeiLy:/var/www/team_plus# pip install -r requirements.txt
第一波测试
在虚拟环境中执行:
(venv) root@WeiLy:/var/www/team_plus# python manage.py runserver --host='0.0.0.0' --port='8001'
* Serving Flask app "app" (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:8002/ (Press CTRL+C to quit)
可以看到项目已经被执行起来了,说明依赖库安装成功,但这里要说明几点:
配置uwsgi文件并运行
好了,项目的准备工作已经做完了,是时候回过头去配置 uwsgi 了,它的具体指令可以去看它的官方文档,我们在这里采用其中的一种指令方式:配置起动。我采用 .ini文件作为配置,在项目目录下创建一个 config.ini
(venv) root@WeiLy:/var/www/team_plus# touch config.ini
编辑config.ini文件
(venv) root@WeiLy:/var/www/team_plus# vim config.ini
[uwsgi]
# uwsgi 启动时所使用的地址与端口
socket = 127.0.0.1:8001 # 可以使用其他端口
# 指向网站目录
chdir = /var/www/team_plus
# python 启动程序文件
wsgi-file = manage.py
# python 程序内用以启动的 application 变量名
callable = app
# 处理器数
processes = 4
# 线程数
threads = 2
#状态检测地址
stats = 127.0.0.1:5000 # 使用flask项目默认的端口,可以换但必须是flask运行时使用的端口
注意 : callable=app 这个 app 是 manage.py 程序文件内的一个变量,这个变量的类型是 Flask的 application 类 。
运行 uwsgi
(venv)root@WeiLy:/var/www/team_plus# uwsgi config.ini
[uWSGI] getting INI configuration from config.ini
*** Starting uWSGI 2.0.8 (64bit) on [Fri Dec 19 14:34:11 2014]
// 此处略去那些无用的启动信息
Stats server enabled on 127.0.0.1:5000 fd: 15
OK, 此时已经正常启动 uwsgi 并将 Flask 项目载入其中了
最后,配置Nginx即可
简单的配置,只需编辑Nginx默认的配置文件即可达到要求,想要了解更多可以参考Nginx的官方文档(自行百度)如果你是要在主机中配置多个web server,这招同样适用,只需要添加一个server即可并使其监听的端口为uwsgi运行的监听的端口,下面分别从server_name为ip地址和server_name为域名两方面来讲:
(venv) root@WeiLy:/var/www/team_plus# vim /etc/nginx/sites-available/default
server_name为ip地址
server {
listen 8001; # nginx监听的端口(默认为80,可以改为其它端口号,也允许不同的nginx server监听不同的端口)
server_name 云主机的公网IP地址;
#charset koi8-r;
#access_log logs/host.access.log main;
root /var/www/team_plus/app/static; # 改为自己的flask项目中的静态文件所在的目录路径
index html/index.html; # 改为自己的首页在静态目录中的路径
location / { # location是用以指定请求要转发到的目标服务器运行的地址
#try_files $uri $uri/ =404;
include uwsgi_params; # 是uwsgi默认的配置参数名
uwsgi_pass 127.0.0.1:8000; # 指向uwsgi 所应用的内部地址,所有请求将转发给uwsgi 处理
uwsgi_param UWSGI_PYHOME /var/www/team_plus/venv; # 指向虚拟环境
目录
uwsgi_param UWSGI_CHDIR /var/www/team_plus; # 指向网站根目录
uwsgi_param UWSGI_SCRIPT manage:app; # 指定启动程序
}
}
server {
listen 80; # nginx监听的端口(默认为80,可以改为其它端口号,也允许不同的nginx server监听不同的端口)
server_name 请求的中的域名名称;
#charset koi8-r;
#access_log logs/host.access.log main;
root /var/www/team_plus/app/static; # 改为自己的flask项目中的静态文件所在的目录路径
index html/index.html; # 改为自己的首页在静态目录中的路径
location / { # location是用以指定请求要转发到的目标服务器运行的地址
#try_files $uri $uri/ =404;
include uwsgi_params; # 是uwsgi默认的配置参数名
uwsgi_pass 127.0.0.1:8000; # 指向uwsgi 所应用的内部地址,所有请求将转发给uwsgi 处理
uwsgi_param UWSGI_PYHOME /var/www/team_plus/venv; # 指向虚拟环境
目录
uwsgi_param UWSGI_CHDIR /var/www/team_plus; # 指向网站根目录
uwsgi_param UWSGI_SCRIPT manage:app; # 指定启动程序
}
}
配置完后重新启动Nginx服务:
(venv) root@WeiLy:/var/www/team_plus# sudo service nginx restart
(venv) root@WeiLy:/var/www/team_plus# vim config.ini
[uwsgi]
# uwsgi 启动时所使用的地址与端口
socket = 127.0.0.1:8001 # 可以使用其他端口
# 指向网站目录
chdir = /var/www/team_plus
# python 启动程序文件
wsgi-file = manage.py
# python 程序内用以启动的 application 变量名
callable = app
# 处理器数
processes = 4
# 线程数
threads = 2
#状态检测地址
stats = 127.0.0.1:5000 # 使用flask项目默认的端口,可以换但必须是flask运行时使用的端口
# 添加它,使uwsgi后台运行
daemonize = /var/www/team_plus/logs/uwsgi.log
在虚拟环境中运行uwsgi,如果报错说地址冲突,可先执行:
killall -9 uwsgi # kill正在运行的uwsgi程序
最后,如下执行:
(venv) root@WeiLy:/var/www/team_plus# uwsgi config.ini
至此,如不出意外,恭喜你的flask项目就部署成功了,你可以通过在浏览器输入你的域名或ip地址:端口号的方式进行访问了!最后,感谢您能耐心看到这里!
参考文章链接:【https://www.tuicool.com/articles/zUvqMr】