一条啰啰嗦嗦战战兢兢呕心沥血的flask部署历程 ——gunicorn+Nginx+Ubuntu16环境下的flask部署

本文完完整整记录了部署小白博主在部署学习和实际部署中遇到的各种error报错和真正可行的部署方案,希望可以让像我一样的部署小白们可以顺利完成部署,我啰啰嗦嗦絮絮叨叨都是怕遗漏了部署中的每一个小bug啊,希望真正记录每一个部署步骤,坚决不让大家弯路部署!

啰啰嗦嗦的心路历程

必须要说下我这一路的心路历程...简直悲壮到想给自己拍纪录片...

我之前自学磕磕绊绊用flask框架做了一个户外平台网站,尚未竣工的时候就背着笔记本(为了工作...并不是为了建站...)跑到了澳洲游玩...然后两周前我人还在霍巴特的时候,突然来了一个宣传推广的好机会,需要快速上线网站,于是为了抓住这次机会,一个对服务器和部署一无所知我就赶紧火急火燎的先买了服务器,然后就开始了我最终为期两周历经艰难险阻头疼脑热各种自我怀疑自信摧毁之后!今天终于部署成功了!激动的心颤动的手呀!

这两周里面我看了3本flask的书上的部署部分,翻了nginxnginxflask的官方英文文档,百度谷歌了无数部署页面,一开始我完全看不懂这些部署命令和配置,被一堆服务器搞得云里雾里,连Linux系统居然有这嘛多版本我该选哪一个我都毫无头绪...随着翻阅资料的增多,我终于慢慢有一点摸到了头绪,结果!又每每在我以为看到曙光差一点点就部署成功的路上...一次次跌倒重来!重来!重来.....比我之前看完《head first python》就啃《Flask Web开发》的感受还墙裂...

我几年前学ASP.NET的时候还是3.5版...等我重拾编程的时候发现ASP.NET都7了,于是我果断放弃了C#,投奔了Python,以前写代码的时候我连听都没听过virtualenvgit,ASP.NET也是很好部署,所以我在学flask的过程中,就直接没用虚拟环境和git,这2工具也是这次部署的时候现学现卖的...

在部署后期,我用了好多百度到的命令,结果把系统搞得一团糟...guincornnginx都启动不了也卸载不了,我把默认的/usr/lib/python也删了...感觉最好系统已经奄奄一息了...最后的最后还是同学介绍了一个大神,然后我让技术重新装了系统,在全新出发的部署中,我每执行一步...都问问大神下一步...最后终于成功了!

啊~部署中还遇到了一些可爱的具有“中国特色”部署问题。因为我一开始是在澳洲部署,回国重装系统部署后才发现...原来国内git 和pip慢成这个鬼样子呀!特别是git,我git了一整天都Fatal了...不要紧哒,解决方案都在下面~
先贴一张飞机晚点, 我凌晨还坐在朗赛斯顿机场地板上部署的图片...


凌晨苦逼兮兮机场地板上部署...

絮絮叨叨的部署前交代

我最终部署的环境是

系统:Ubuntu16

数据库:mysql5.7

WEB服务器:Nginx

WSGI服务器:Guincorn

Python多版本的交代:3.5和2.7,ubuntu16的默认Python版本是3.5。一定要用whereis python先看一下服务器上有几个Python版本,哪个是默认的。

(下面是关于多版本的絮叨....哎~没办法,谁让Python多版本真的真的很绊脚石)之前开发自己电脑上只有一个Python版本,完全没想到多版本Python居然在部署中这嘛麻烦...特别是我第一次部署用的ubuntu12,有2.7,3.2,3.6三个版本,三个一起简直多灾多难的开始!因为12默认Python版本是2.7,python3又默认的是3.2,而我本来想用的3.6...就完完全全没被用到,如果是有好几个版本,运行Python要用python3.6,Python多了相应的还有pip的问题,同样用whereis pip和Pip3看一下对应的Python版本,就是你用pip安装包就会安装到这个Python下。

部署中使用到的工具:

Git代码克隆和更新

Virtualenv 创建代码运行的虚拟环境,我第一次没用virtualenv,差点被Python多版本搞死...

几个部署中常用到的ubuntu命令:

如果和我一样的Linux纯菜鸟...一定要先了解一些常用命令...不然一个黑框框真的不太友好

sudo 以超级管理员运行命令,如果在root用户下,就每个命令都不需要加sudo(这个我居然不知道...一路按着书本和网页上的命令写了一路sudo)

apt-get install xxx 安装软件包,这个和pip差不多,都是包管理器,apt-get是装到系统的,Pip是装到Python里面的

rm -rf dir_name 删除有内容的目录

cp aaa bbb 复制aaa到bbb

ln aaa bbb 在bbb创建一个链接,指向aaa

vim xxx打开文件并编辑,移动光标点insert修改文件,按esc:q直接退出,esc:wq保存并退出

http http://localhost需要先apt install httpie,之后使用http命令在服务器端测试网页是否可访问。

export var_name=value 添加系统环境变量

echo $var_name 查看变量值

mkdir dir_name创建目录

cd /dir切换目录

最后正式部署前还要说下,我之前看《深入FLASK》这本书,里面讲了好多个WSGI容器,还讲到fabricsupervisor,于是整的我有点迷茫,前期在完全不了解这2工具的情况下用了fabric和supervisor....嗯!也很惨烈,新手不要直接用这俩,就老老实实手动敲命令,一步一步部署,简单说下这2,这个fabric有很多Linux命令管理器,就是可以把需要在server上手动一步步执行的命令归集在一起,然后在server上一条命令就完成环境搭建,听起来十分诱人了!但是!新手千万不要用这个....特别是这本书里的命令好几个都会运行出错,一出错...整个命令集合都凉凉了,所以我们要自己手动慢慢整。然后这个supervisor在部署中的角色是可以一次开启好几个服务,也可以不用,我们手动启动服务,启动的明明白白!就像我刚开始以为supervisor是启动uwsgi的方式,结果supervisor自己是运行了,但是后面的uwsgi运行出错...连报都没给我报...

一本正经的开始部署!

部署大致分以下几个步骤,先列一下步骤,然后我们一步一步慢慢来~不要急

  • 备案

  • 重审本地代码

  • 登录远程server

  • 将代码复制到server

  • 创建虚拟环境并安装项目依赖扩展

  • Mysql设置

  • 创建项目数据库和基本数据

  • 安装并运行guincorn

  • 安装并运行Nginx

展开了来慢慢说

域名备案

域名备案一定要趁早!现在已经快3周过去了...我的备案信息还杳无音信,只有备案了的域名才能进行微信登录、支付等第三方平台的开发。之前我的域名供应商说他们帮我备案1周就好,实际上...然后他们先把一个备案好的二级域名绑定了IP给我测试用,我域名和服务器在一家买的,技术说只能只能通过域名访问网站,通过IP访问不到,服务器系统可以选,也可以让技术帮你装一些软件,我的服务器刚开是Ubuntu12的,后来让技术重装了16的,并装了MySQL。

重审本地代码

如果和我一样严格按照《Flask Web开发》或者《深入理解Flask》一样做的架构,那你现在应该有3个config类,把ProductConfig类中的数据库连接改一下。

pip freeze > requirements.txt 生成依赖包文件

在manage.py里面添加个createdb命令,方便之后在server上直接创建数据库和基础数据和管理员等,以下是我的代码供参考

@manager.command 
  def createdb():
  db.create_all() 
  #create admin
  admin = User()
  admin.username ='admin'
  admin.email = 'xxx@163.com'
  admin.password = 'xxx'
  admin.is_admin = True
  db.session.add(admin)
  db.session.commit() 

在项目根目录下创建一个nginx.conf配置文件,至于里面内容...我放到最后一个part写吧~哈哈哈哈

登录远程server

下载putty,这个是用来远程登录server的。

打开Putty,输入serverIPload进入黑框框...

通过putty登陆server

输入用户名和密码~我们就登录server啦

将代码复制到server

为了方便后续开发中程序更新啥的,用git推拉代码吧~
如果和我一样是个git小白,先用半天时间打开廖雪峰老师的git教程,学习下git,教程写的超棒,很好读。
按照这个廖雪峰老师的git教程一步步下载安装、注册git,添加公钥,创建仓库
简单说下本地用到的git操作
在项目根目录,
git init创建git仓库

git add app添加要放到git的项目,还要创建一个.gitignore保存不需要同步的文件和目录

git commit –m “message” 提交变动

git remote add origin git@github.com:username/project_name.git关联到github上的远程库

git push –u origin master将本地仓库推送到github

之后每次修改代码,都需要先在本地运行git add /commit,然后git push origin master不需要-u
远程server上git 的操作:
cd到需要放仓库的目录
git clone [https://github.com/username/project_name
之后每次更新呢代码都直接cd到项目目录内,然后git pull命令即可。
理论上到这里就已经代码克隆到server了,我之前在澳洲的时候就很顺利,可是昨天这样做…就先是每秒几k的速度,后来直接fatal报错,我查了百度,有说不要用http用git@github.com+公钥的方式,还有什么设置proxy的,我全试了…完全不行依然fatal,最后还是大神告诉我git被墙了,网速非常慢,给我推荐了国内的git仓库,码云。所以如果你也git clone不了,咱们接着码云走起!
https://gitee.com/
注册登陆,界面和git一样一样的,选择+从github项目导入,授权github,选择要同步的项目

在码云上导入github

每次更新代码上传到github之后,在码云点一下刷新,就同步了


同步github仓库

处理完码云,我们接着回到server
还是原来的git clone,只不过把地址换成码云上的Url
git clone https://gitee.com/username/project_name
之后每次更新也是git pull即可。
哦啦项目代码的迁移就搞定啦

创建虚拟环境并安装项目依赖扩展

cd 到项目的上级目录

我之前看书和官方文档,虚拟环境都是建在项目里面,其实建在哪里都可以,创建在项目里面比较方便,如果之后还git clone会覆盖掉虚拟环境,用git pull不会,不过我还是感觉虚拟环境和项目分开比较舒服…

安装virtualenv:

pip install virtualenv –i https://pypi.mirrors.ustc.edu.cn/simple/

这里要说一下pip超慢的,特别是后面需要安装requirements里面的依赖的时候…更是慢到可以去睡觉,而且不止慢,还会报timeout的错,所以这里有2选择。一是使用参数 pip install –default-timeout=100 xxx,这个虽然慢但是不会报错了,第二种是换源(哈哈哈!也是大神教我的,我自己百度到的是第一个方法),直接把pip包的下载地址换了,后面Pip依赖的时候你会感受到快如风的安装体验~镜像有好多个,我一开始用阿里云的,但是后面pip依赖的时候会保存,然后用了中科大的这个源就很圆满啦

创建虚拟环境
virtualenv –p usr/bin/python3.5 venv
创建的时候一定一定要指定python版本!!!我就是看系统默认python是3.5的,我就以为直接virtualenv venv就会创建基于3.5的环境,结果…是2.7的

进入虚拟环境
source venv/bin/activate
进入虚拟环境之后,先感觉Python下看一下Python版本….
确认python版本没有问题后,开始安装依赖

pip install –r requirements.txt –i https://pypi.mirrors.ustc.edu.cn/simple/

搞定进入下一步~

Mysql设置

mysql –u root –p输入密码进入MySQL

数据库这里如果没有设置好,后面数据库数据会出现问题,我的出现了所有数据库中的中文变成了问号…这里是数据库字符集的问题。

show variables like '%char%';

查看哪些字符集不是utf8

将不是UTF8的设置为set xxx=utf8

set character_set_database=utf8;

set character_set_server=utf8;

创建项目数据库和基本数据

设置好MySQL字符集问题之后,接下来就可以创建数据库 啦~

CREATE DATABASE XXX;

如果create_app中根据环境变量配置创建flask实例的,这个时候要导入环境变量啦~,我的是

export FLASK_CONFIG=production

创建数据库和初始数据库数据

python manage.py createdb

OK,到这里已经把项目完全准备好了~我们配置服务器去

安装并运行guincorn

FLASK内置的WSGI服务器不能用于生产环境,在生产环境中需要一台反向代理web服务器+WSGI容器,我一开始也是不太懂服务器就服务器嘛~做嘛还需要2服务器…盗个外网的图给大家解释一下。


Nginx和Gunicorn的关系

这个反向代理服务器(我选择的是Nginx)监听的是HTTP请求的80端口,然后它接收到请求之后,如果是请求静态文件,直接发,如果请求动态内容,就通过WSGI接口转发给WSGI容器(这里选择guincorn)的端口(配置文件里会写),然后gunicorn处理后返回Nginx,Nginx再转发回浏览器。总结一下就是Nginx监听的是80端口的HTTP协议,Gunicorn处理的是800X端口的WSGI协议。

常见的WSGI容器还有uWSGI,这个还需要整一个专门的配置文件,比较麻烦,我使用这个配置失败了,后来大神用的gunicorn,我就转到gunicorn了…

安装gunicorn

我们现在应该还在虚拟环境中~这个要在虚拟环境中安装
pip install gunicorn

开启服务
gunicorn –w 3 –b 0.0.0.0:8080 manage:app

里面的Manage是含有flask实例的py文件,app是我的FLASK实例名。这里有一点要特别注意下,必须先cd到这个manage.py所在的目录再输入以上命令,我之前在这个目录外面用app.manage:app就…开启失败了,至于为什么,我就不知道啦…


gunicorn在manage目录外运行报错,无法导入app

然后我们测试下网页
http http://localhost:8080
这个时候如果显示了你主页的HTML,那么恭喜你!成功了,我们进行最后一步!

安装并运行Nginx

我们deactivate虚拟环境先~

安装Nginx服务器

apt-get install nginx

服务器安装成功,服务就自动开启了,现在如果输入http http://localhost

就会出行nginx的欢迎页

这里说一下之前第一步里面让创建的nginx.conf配置文件的内容,我的代码如下:

server {

 listen 80;

 server_name xxx.xx.xx.xx;//你的域名
 server_name  localhost; 

//所有动态的都转发给监听8080端口的gunicorn处理 
location / {

 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 proxy_set_header Host $Host;

 proxy_set_header X-Real-IP $remote_addr;

 proxy_set_header X-Scheme $scheme;

 proxy_redirect off;

 proxy_pass [http:// 127.0.0.1 :8080](http://127.0.0.1:8080);

 }

//所有静态文件都自己处理 
location /static {

 alias /home/deploy/catyy/app/app/static;

 }

}

这里需要特别说一下里面2个比较特殊的语句,

server_name localhost;

这里不写域名,开启服务后服务器可以访问,外网不能访问…后来加上server_name domain_name再就开启服务就报错,大神说换成Localhost,就可以正常开启了

proxy_pass http://**127.0.0.1**:8080

这里我一开始写的0.0.0.0,也是基于外网无法访问的问题,大神让我改成了127.0.0.1,我也不懂原理,反正这个配置我现在已经可以正常访问了…
在最后一步开启服务前,还需要把现在在你项目根目录下的这个配置文件替换Nginx默认的配置文件
cp your/path/to/config/nginx.conf /etc/nginx/sites-available/default
这里《深入理解Flask》里面写的是cp到/sites-available/[your_domain],我试了...不行,并不能让nginx指向你的网站,还是直接替换default吧

最后一步开启服务!

service nginx restart

现在服务器上测试一下

http http://localhost出行主页HTML就成功啦!

完美!

以上!希望大家都可以部署成功哦~

推荐阅读更多精彩内容