如何将Flask项目部署在Ubuntu系统的阿里云主机中(详细完整版:下)

如何将Flask项目部署在Ubuntu系统的阿里云主机中(详细完整版:下)


问题重述

上一篇我们谈到了总的解决方案,一起探索了flask项目部署前的上传准备过程,以及分享了几个好用的软件和python模块,若有对上一篇文章感兴趣的朋友,可以跳过去看一下
传送门【https://blog.csdn.net/weixin_39212776/article/details/81318553】
这篇文章我们主要来解决的是flask项目云上正式部署的问题,所以,如果你只关注云上部署的部分,这篇文章也是值得借鉴的。下面我会按照我探索过得可行的思路来写,也会继续分享一些我们在部署过程中容易踩到的坑。
如果你想在一台网络服务器上配置多个web server,改文章一样适用,在最后关于Nginx的配置会详解

解决的思路与方案

在上一篇文章完成后,我们的flask项目已经被打包并压缩为tar.bz2的格式发送到云主机中了,如若没有的可以查看我的上一篇文章,那里将为你详细讲解,这里我们不再赘述。

第二步,flask项目的正式部署

  • 连接到我们的云主机
    这一步相信大家都会,固定的模式:打开cmd;输入如下:
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文件批量安装依赖包
    切记两点:

    1. 文件中需要被依赖的包要把位置调到前面
    2. 在安装时一定要确定是在该项目的虚拟环境中的,否则会直接安装到全局去的!
    (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)

    可以看到项目已经被执行起来了,说明依赖库安装成功,但这里要说明几点:

    1. 规定host=’0.0.0.0’
    2. 规定端口号,一般为8000之后的值
    3. runserver是Manager实例后的manage.py 文件自带的运行命令
  • 配置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_name为域名地址
    server_name为域名地址与server_name为ip地址的Nginx的配置区别并不大,只是为域名时,我们监听的端口可以使用默认的80端口,因为Nginx是靠listen 的端口号与server_name 一起区分要转发到哪个web server 的,所以当server_name为域名时我们可以靠域名的不同来区分要转发的web server,所以监听的端口号可以默认为80
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
  • 让uwsgi在后台默默耕耘
    往uwsgi的配置文件中添加 daemonize = /var/www/team_plus/logs/uwsgi.log (你的flask项目的log文件所在的地址)
    这样uwsgi服务就会把日志打印到uwsgi.log中。
    通过查 nginx 的access_log 和 error_log 进行调试错误。
(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】

你可能感兴趣的:(Linux)