Ubuntu+uwsgi+Nginx部署Flask应用

由于是第一次在Linux部署Python应用,过程中遇到很多坑,也找了很多部署博客的分享。再一次体会到好文章带你上天堂,坏文章带你瞎逼忙的道理。索性就记录这次部署的全过程,供以后参考。

介绍

首先先介绍下各个技术的功能,以及他们组合的大致流程。部署的是一个web应用,从用户打开浏览器访问网页开始,到浏览到网页内容,这个过程就是各个技术实现功能的过程。

整体结构

  • 用户浏览器(客户端)打开网页,向服务器发起请求;
  • 请求传给Nginx服务器,Nginx将请求发给uWSGI;
  • uWSGI服务器发来的请求翻译为应用程序理解的形式,发给应用;
  • Flask应用接收请求并处理,将响应结果发给uWSGI;
  • uWSGI与Nginx服务器通信,将结果传给他;
  • Nginx服务器收到响应结果,将其传给客户端;
  • 浏览器显示响应结果,并进行下一个请求。

安装Python环境

阿里云Ubuntu服务器自带的Python2.7Python3.4,所以尽管我的应用是Python3程序,也不必重新装Python3

更新apt-get

sudo apt-get update

获取应用源码

由于我的代码放在github仓库,直接通过git来安装。首先安装git:

sudo apt-get install git

安装完成后,在用户目录中新建project目录mkdir project,存放我们的应用程序。不知道是不是在用户目录可以输入指令pwd查看。我们转到project文件夹下,使用git克隆项目源码:

git clone https://github.com/Blackyukun/YuBlog.git

转到项目目录cd YuBlog

安装pip和virtualenv

sudo apt-get install python-pip

sudo apt-get install python-virtualenv

创建虚拟环境

这里需要注意的是,如果直接virtualenv venv命令,创建的将会是Python2的虚拟环境。如果想要创建Python3的环境,需要指定Python3的目录:

virtualenv -p /usr/bin/python3 venv

如果成功,项目目录下会生成一个venv目录,那里就是我们的python3虚拟环境了。接下来激活虚拟环境:

source venv/bin/activate

退出虚拟环境命令是:deactivate

安装依赖包

如果项目实在虚拟环境中完成的,那么通常我们会使用pip freeze >requirements.txt命令列出项目所有依赖。然后当我们安装这些依赖的时候只需要使用命令:

pip install -i http://pypi.douban.com/simple/ -r requirements.txt

如果全部安装完成,那么我们的程序依赖环境全都准备好了。

安装Mysql数据库

我的程序是使用Mysql数据库做存储的,安装它也很简单,但是这里会有一个阿里云服务器的大坑。

sudo apt-get install mysql-server mysql-client

sudo apt-get install libmysqlclient-dev

安装过程中会需要你输入用户以及密码,暂且就使用rootpassword吧。

sudo netstat -tap | grep mysql命令检查Mysql是否安装成功,如果mysqlsocket处于listen状态则表示安装成功。

登录mysql数据库命令:mysql -u root -p这里的root就是之前安装是设置的用户名,接着输入密码password。在Linux上,我们需要修改mysql的默认编码为utf-8,以便正确地处理中文。

这里需要编辑MySQL的配置文件,把数据库默认的编码全部改为UTF-8MySQL的配置文件默认存放在/etc/my.cnf或者/etc/mysql/my.cnf

vim /etc/mysql/my.cnf 

linux使用的是vim编辑器,不了解vim的可以自行了解。我们按i进去插入模式,将下面的指令粘贴到对应位置:

[client]
default-character-set = utf8

[mysqld]
default-storage-engine = INNODB
character-set-server = utf8
collation-server = utf8_general_ci

把队应指令放在对应地方就好了。配置完成后,在vim编辑器下,按ESC进入普通模式,键入:wq进行保存并退出。show variables like '%char%';指令查看编码是否设置正确。如果看到utf8就表示正确。

mysql

接着重启数据库:

service mysql restart

重新登录mysql -u root -p创建我们的数据库,使用:create database mydb;创建名为mydb的库名(注意后面封号)。

中文乱码

这里我们会遇到一个坑,就是在后面程序启动保存数据的时候会出现中文乱码,但是我们明明已经编辑过默认编码了呀。这里我发现是阿里云服务器本身没有安装中文包,我们需要进行安装。

安装中文语言包

sudo apt-get -y install language-pack-zh-hans

修改语言环境设置

echo "LC_ALL=zh_CN.utf8" >> /etc/profile

echo "export LC_ALL" >> /etc/profile

查看语言

source /etc/profile

locale

看到zh_CN.UTF-8就成功了。接着需要重启服务器。

根本原因

虽然中文包安装成功了,但是这样就表示ok了吗?并没有,后来启动中网页中文显示依然乱码。我发现是保存数据库里的数据才会乱码,那么根本原因还是数据库编码问题。

我们需要在创建数据库时要同时定义他的默认编码:

删除数据库:mysql>delete database mydb;

创建数据库:mysql>create database mydb default character set utf8;

安装Nginx服务器

Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件IMAP/POP3代理服务器。其特点是占有内存少,并发能力强。用于接收HTTP请求并返回响应。安装:

sudo apt-get install nginx

启动:sudo /etc/init.d/nginx start

看到OK表示成功。接着需要配置NginxNginx的配置文件在/etc/nginx/sites-available目录的default文件中,将其删除rm default。新的default创建并打开vim default,在里面写入:

server { 
  listen 80; # 80端口需要打开
  server_name X.X.X.X; #阿里云公网ip
  location / { 
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:5000; # 指向uwsgi 所应用的内部地址
  uwsgi_param UWSGI_PYHOME /home/root/project/YuBlog/venv; # 虚拟环境目录
  uwsgi_param UWSGI_CHDIR /home/root/project/YuBlog; # 应用根目录
  uwsgi_param UWSGI_SCRIPT manage:app; # 启动程序
  uwsgi_read_timeout 100; 
 }  
}

重启Nginx:sudo service nginx restart

看到OK表示成功。如果失败,可以输入指令sudo nginx -t查找错误,进行处理。

安装uWSGI

uWSGI虽然也可以起到Web服务器的作用,那么为什么有了uWSGI还需要Nginx呢。具体的优势大家自行了解。在Nginx+uWSGI的结构中,它充当中间件的程序,是Web的通信协议。

安装:sudo pip install uwsgi

注意实在虚拟环境。安装成功后需要配置。我们在项目的根目录下也就是/home/root/project/YuBlog下,创建配置文件config.ini,添加内容:

[uwsgi]
master = true
home = venv
wsgi-file = manage.py
callable = app
socket = :5000
processes = 4
threads = 2

配置完成后,就可以启动uWSGI了。但在这之前,我们先启动应用程序,并添加程序必须的环境变量。

添加linux系统环境变量:export CONFIG=production

...

先创建迁移仓库:python manage.py db init

创建迁移脚本,migrate子命令用来自动创建:python manage.py db migrate -m "v1.0"

更新数据库操作:python manage.py db upgrade

创建管理员信息:python manage.py addAdmin

ctrl+c终止程序。

启动uWSGI: uwsgi config.ini

会看到很多信息,只要没有报错,就表明启动成功。

部署成功

如果NginxuWSGI全部启动成功,就说明部署已经成功了。打开外部浏览器,访问公网ip地址,就可以看到我们的程序已经跑起来了。

本文作者:俞坤

本文链接:http://www.yukunweb.com/2017/12/ubuntu-nginx-uwsgi-flask-app

版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0许可协议。转载请注明出处!

可视化分钱的概率模拟算法
22 条评论
  1. author
    2018-06-19
    藕丝空间

    非常棒的网站,very good.学习了。

  2. author
    2018-05-11
    天宝

    (venv) root@vultr:~/project/movie_project# uwsgi config.ini
    [uWSGI] getting INI configuration from config.ini
    *** Starting uWSGI 2.0.17 (64bit) on [Fri May 11 09:37:48 2018] ***
    compiled with version: 4.8.4 on 11 May 2018 09:06:15
    os: Linux-3.13.0-125-generic #174-Ubuntu SMP Mon Jul 10 18:51:24 UTC 2017
    nodename: vultr.guest
    machine: x86_64
    clock source: unix
    detected number of CPU cores: 1
    current working directory: /root/project/movie_project
    detected binary path: /usr/local/bin/uwsgi
    !!! no internal routing support, rebuild with pcre support !!!
    uWSGI running as root, you can use --uid/--gid/--chroot options
    *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
    chdir() to /root/project/movie_project
    your processes number limit is 3743
    your memory page size is 4096 bytes
    detected max file descriptor number: 1024
    lock engine: pthread robust mutexes
    thunder lock: disabled (you can enable it with --thunder-lock)
    uwsgi socket 0 bound to TCP address :6666 fd 3
    uWSGI running as root, you can use --uid/--gid/--chroot options
    *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
    Python version: 2.7.6 (default, Nov 23 2017, 15:53:45)  [GCC 4.8.4]
    Set PythonHome to venv
    ImportError: No module named site
    (venv) root@vultr:~/project/movie_project# 
    

    已经在config.ini添加pythonHome = venv 但还是这样,会是什么问题呢?

    [uwsgi]
    master = true
    PythonHome = venv
    home = venv
    chdir = /root/project/movie_project
    wsgi-file = manage.py
    callable = app
    socket = :6666
    processes = 4
    threads = 2
    

    博主有时间了帮忙解答一下

    • 2018-05-11 23:06:37
      yukun

      @ 天宝:是代码依赖导入问题吗:

      No module named site
      

      你有site.py文件吗?

    • 2018-05-12 16:08:43
      天宝

      @ yukun:怀疑是我server的配置问题,访问相关端口出现502 Bad Gateway,uwsgi是启动成功的,我的server信息中

      uwsgi_param UWSGI_PYHOME /home/root/project/movie_project/venv; 
      uwsgi_param UWSGI_CHDIR /home/root/project/movie_project; 
      

      应该去掉/home吗? 我是直接用的root超级用户进行布置的,而不是创建一个root用户,ls查看home下并没有root用户,项目和虚拟环境都是在/home/root/project/movie_project/中,然而我把/home去掉了还是502的错误,愁死。

    • 2018-05-12 17:56:33
      天宝

      @ yukun:感谢博主,已经成功了,是我nginx的default配置后没有发送到/etc/nginx/sites-enabled目录下,一台服务器部署4个网站真心累。

  3. author
    2018-03-05
    shylin

    博主,中午又弄了一遍,这次是创建了project目录,还是会报错,麻烦你看下: ```Traceback (most recent call last): File "/root/project/YuBlog/manage.py", line 4, in from app import create_app, db File "/root/project/YuBlog/app/init.py", line 1, in from flask import Flask ImportError: No module named flask unable to load app 0 (mountpoint='') (callable not found or import error) --- no python application found, check your startup logs for errors --- [pid: 6838|app: -1|req: -1/1] 183.233.89.222 () {48 vars in 841 bytes} [Mon Mar 5 01:38:42 2018] GET / => generated 21 bytes in 4 msecs (HTTP/1.1 500) 2 headers in 83 bytes (0 switches on core 0)

    uwsgi配置 ```[uwsgi]

    uwsgi 启动时所使用的地址与端口

    socket = 127.0.0.1:5000

    指向网站目录

    chdir = /root/project/YuBlog

    python 启动程序文件

    wsgi-file = manage.py

    python 程序内用以启动的 application 变量名

    callable = app

    处理器数

    processes = 4

    线程数

    threads = 2

    状态检测地址

    stats = 127.0.0.1:9191 njinx配置

    server {
      listen 80; # 80端口需要打开
      server_name 95.163.107.66; #公网ip
      location / {
      include uwsgi_params;
      uwsgi_pass 127.0.0.1:5000; # 指向uwsgi 所应用的内部地址
      uwsgi_param UWSGI_PYHOME /root/project/YuBlog/venv; # 虚拟环境目录
      uwsgi_param UWSGI_CHDIR /root/project/YuBlog; # 应用根目录
      uwsgi_param UWSGI_SCRIPT manage:app; # 启动程序
      uwsgi_read_timeout 100;
     }
    }
    
    文件路径
    

    root@ubuntu:~/project/YuBlog# pwd /root/project/YuBlog

    • 2018-03-05 15:07:23
      yukun

      @ shylin:你把python的虚拟环境添加到uwsgi的配置中去:

      pythonpath = venv
      
    • 2018-03-05 15:30:44
      shylin

      @ yukun:中午做的那个,添加 pythonpath = venv 后还是会报一样的错误。

    • 2018-03-05 15:51:45
      shylin

      @ yukun:博主,情况是这样的,我已经有vps和域名且两者都已绑定好,就是不知道怎么把你写的博客部署上去,参数配置不是很清楚。

    • 2018-03-05 17:29:52
      yukun

      @ shylin:这个错误就是因为没有 python 应用,你自己谷歌看看吧QAQ~

    • 2018-03-06 08:17:20
      shylin

      @ yukun:‘’我们先启动应用程序,并添加程序必须的环境变量‘’,博主,环境变量除了设置邮箱的环境,还要设置其他的吗?那个问题在谷歌上找了下,目前还没找到方法。

    • 2018-03-06 10:02:39
      shylin

      @ yukun:博主,能不能发下你的配置文件,我这找了好久还是没找到解决方法。。。项目软件是使用的依赖文件,uwsgi和nginx是sudo安装的。。。麻烦你看下

    • 2018-03-06 13:01:42
      yukun

      @ shylin:我的配置:

      master = true

      socket = 127.0.0.1:9001

      chdir = /root/project/YuBlog

      wsgi-file = manage.py

      callable = app

      processes = 4

      threads = 2

    • 2018-03-06 13:07:09
      yukun

      @ shylin:如果你使用uwsgi启动不了,可以试试用

      gunicorn -b 0.0.0.0:80 manage:app

      来启动,记住在项目路径下。

  4. author
    2018-03-04
    shylin

    博主,最后一步部署成功,但是启动UWSGI后访问网站会报错“Internal Server Error” *** uWSGI is running in multiple interpreter mode *** spawned uWSGI master process (pid: 3494) spawned uWSGI worker 1 (pid: 3495, cores: 2) spawned uWSGI worker 2 (pid: 3496, cores: 2) spawned uWSGI worker 3 (pid: 3497, cores: 2) spawned uWSGI worker 4 (pid: 3498, cores: 2) *** Stats server enabled on 127.0.0.1:9191 fd: 15 *** 错误: ImportError: No module named flask unable to load app 0 (mountpoint='') (callable not found or import error) --- no python application found, check your startup logs for errors --- [pid: 3495|app: -1|req: -1/1] 95.163.207.89 () {46 vars in 804 bytes} [Sun Mar 4 03:39:51 2018] GET / => generated 21 bytes in 8 msecs (HTTP/1.1 500) 2 headers in 83 bytes (0 switches on core 0)

    • 2018-03-04 22:06:32
      yukun

      @ shylin:仔细看报错,应该是你的uwsgi的配置有问题,找不到对应的python程序,如果我们的服务器不是同一个版本,可能程序的路径是不一样的,你好好看看应用的路径。

      pwd
      
  5. author
    2018-03-04
    shylin

    忽略上个问题,已解决。

    • 2018-03-05 08:10:04
      shylin

      @ shylin:``` root@ubuntu:~/YuBlog# pwd /root/YuBlog

      配置如下,你看下有啥错误不,代码没有新建project存放,但是改了路径,路径含有的project都删了 ```[uwsgi]

      uwsgi 启动时所使用的地址与端口

      socket = 127.0.0.1:5000

      指向网站目录

      chdir = /root/YuBlog

      python 启动程序文件

      wsgi-file = manage.py

      python 程序内用以启动的 application 变量名

      callable = app

      处理器数

      processes = 4

      线程数

      threads = 2

      状态检测地址

      stats = 127.0.0.1:9191

    • 2018-03-05 14:10:58
      yukun

      @ shylin:``` master = true

      socket = 127.0.0.1:9001

      chdir = /root/YuBlog

      wsgi-file = manage.py

      callable = app

      processes = 4

      threads = 2 ```

    • 2018-03-05 14:12:13
      yukun

      @ shylin:你改这个配置,无语了,评论markdown解析有问题了...

  6. author
    2018-03-04
    shylin

    博主,“Nginx的配置文件在/etc/nginx/sites-available目录的default文件中,将其删除rm default。新的default创建并打开vim default,在里面写入xxx“,在这一步时出错了,能麻烦你看下怎么回事吗?

    nginx.serviceJob for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
    

    (venv) root@ubuntu:~# systemctl status nginx.service ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Sun 2018-03-04 01:36:51 EST; 4min 27s ago Process: 1449 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)

    Mar 04 01:36:51 ubuntu systemd[1]: Starting A high performance web server and a reverse proxy server... Mar 04 01:36:51 ubuntu nginx[1449]: nginx: [emerg] unknown directive "erver" in /etc/nginx/sites-enabled/default:1 Mar 04 01:36:51 ubuntu nginx[1449]: nginx: configuration file /etc/nginx/nginx.conf test failed Mar 04 01:36:51 ubuntu systemd[1]: nginx.service: Control process exited, code=exited status=1 Mar 04 01:36:51 ubuntu systemd[1]: Failed to start A high performance web server and a reverse proxy server. Mar 04 01:36:51 ubuntu systemd[1]: nginx.service: Unit entered failed state. Mar 04 01:36:51 ubuntu systemd[1]: nginx.service: Failed with result 'exit-code'

  7. author
    2018-02-12
    pdf-lib.org

    不错,学习了。

已登录,注销 取消