阿里云ecs(ubuntu16.04)使用nginx、gunicorn和supervisor部署flask应用

1.更新软件源

阿里ecs主机应该都已经事先设置好了阿里的源,但是拿到手第一件事就是先执行一下update
sudo apt-get update
否则后续安装软件时可能会报软件报找不到的错误。

2.安全组设置

我们后面部署Nginx时使用的是80端口,flask的web服务放在8080端口,但是这两个端口在阿里云的ecs是默认关闭的,需要在安全组中打开,打开方法比较简单,就不细说了。


安全组.png

3.部署nginx

sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install nginx

如果“add-apt-repository”命令在你的ubuntu版本中不存在的话,你需要安装“software-properties-common”包:
sudo apt-get install software-properties-common

安装完成后可以查看版本

root@ecs2core4g:~# nginx -v
nginx version: nginx/1.12.2

运行nginx:

root@ecs2core4g:/etc/init.d# sudo /etc/init.d/nginx start
[ ok ] Starting nginx (via systemctl): nginx.service.

第一个里程碑,使用外网IP访问,比如http://10.10.10.10,可以看到下面的效果


nginx.jpg

4.Flask应用

我们部署的应用时经典的“Hello world!”,只有一个页面。应用的目录准备放在/var/www/demoapp中,并且使用virtualenv来部署我们的flask应用。我们应用的用户假设使用www这个用户。

使用virtualenv来部署flask应用还是有意义的,因为ecs自带的默认python是2.7,而很多时候我们希望使用python 3.x来开发我们的应用。

创建用户和组:

root@ecs2core4g:~# useradd www
root@ecs2core4g:~# passwd www
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
root@ecs2core4g:~# id www
uid=1000(www) gid=1000(www) groups=1000(www)
root@ecs2core4g:~# 

这样用户和组就都添加好了。

下面创建项目目录:

sudo mkdir /var/www
sudo mkdir /var/www/demoapp

由于我们使用root权限创建了这个文件夹,它目前归root用户所有,让我们更改它的所有权给你登录的用户(我的例子中是www)
sudo chown -R www:www /var/www/demoapp/
创建一个python3.5的虚拟环境,并安装flask:

pip install virtualenv
cd /var/www/demoapp
virtualenv -p /usr/bin/python3 py3env
. py3env/bin/activate
pip install flask

使用下面的代码创建hello.py文件:

from flask import Flask
app = Flask(__name__)
 
@app.route("/")
def hello():
    return "Hello World!"
 
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)

在虚拟环境中执行我们的flask应用:

(py3env) root@ecs2core4g:/var/www/demoapp# python hello.py 

现在你可以通过浏览器访问你服务器的8080端口,比如http://10.10.10.10:8080,可以看到应用已经生效了:


8080.jpg

虽然我们已经见到Hello World!字样了,但是此时实际连接的时flask的调试服务器,不能应用在正式工作场合。我们需要使用nginx做反向代理,使用gunicorn作为WSGI。

5.修改nginx配置

查看nginx版本:

root@ecs2core4g:~# nginx -v
nginx version: nginx/1.12.2
root@ecs2core4g:~# 

1.12.2版本的默认配置文件在/etc/nginx/conf.d文件夹下,但是为了方便管理,我们把配置文件还是放在/var/www/demoapp目录下,然后在/etc/nginx/conf.d下做个链接。
创建一个我们应用使用的新配置文件/var/www/demoapp/demoapp_nginx.conf:

server {
    listen      80;
    server_name localhost;
    charset     utf-8;
    client_max_body_size 75M;
 
    location / {
        proxy_set_header X-Fforwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8080;
    }
}

注意:这里地址填的是127.0.0.1,那么,flask绑定的ip也必须是127.0.0.1,而不是外网地址或内网地址。
将刚建立的配置文件使用符号链接到Nginx配置文件文件夹中,重启Nginx:

sudo ln -s /var/www/demoapp/demoapp_nginx.conf /etc/nginx/conf.d/
root@ecs2core4g:~# sudo /etc/init.d/nginx start
[ ok ] Starting nginx (via systemctl): nginx.service.
root@ecs2core4g:~# 

6.安装gunicorn

Web框架(Flask)致力于如何生成HTML代码,而Web服务器(nginx)用于处理和响应HTTP请求。Web框架和Web服务器之间的通信,需要一套双方都遵守的接口协议。WSGI协议就是用来统一这两者的接口的。
常用的WSGI容器有Gunicorn和uWSGI,但Gunicorn直接用命令启动,不需要编写配置文件,相对uWSGI要容易很多,所以这里我也选择用Gunicorn作为容器。
在虚拟环境中安装gunicorn

. ./py3env/bin/activate
pip install gunicorn

启动gunicorn,-w表示启动几个worker进程,-b表示绑定的ip端口

(py3env) root@ecs2core4g:/var/www/demoapp# /var/www/demoapp/py3env/bin/gunicorn -w2 hello:app -b 0.0.0.0:8080   
[2018-02-12 00:17:03 +0800] [18826] [INFO] Starting gunicorn 19.7.1
[2018-02-12 00:17:03 +0800] [18826] [INFO] Listening at: http://0.0.0.0:8080 (18826)
[2018-02-12 00:17:03 +0800] [18826] [INFO] Using worker: sync
[2018-02-12 00:17:03 +0800] [18829] [INFO] Booting worker with pid: 18829
[2018-02-12 00:17:03 +0800] [18830] [INFO] Booting worker with pid: 18830

7.使用supervisor守护gunicorn

虽然8080端口已经在工作中了,但是我们是手动启动的gunicorn,

sudo apt-get install supervisor
echo_supervisord_conf > /etc/supervisor/supervisord.conf

修改/etc/supervisor/supervisord.conf,在结尾增加

[include]
files = /var/www/demoapp/demoapp_supervisor.conf

注意,一定要删掉[include]前面的分号,否则没用哦
修改/var/www/demoapp/demoapp_supervisor.conf的内容,全部内容如下:

[program:demoapp]
command=/var/www/demoapp/py3env/bin/gunicorn -w 2 hello:app -b 0.0.0.0:8080           ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1                    ; number of processes copies to start (def 1)
directory=/var/www/demoapp     ; directory to cwd to before exec (def no cwd)
;umask=022                     ; umask for process (default None)
;priority=999                  ; the relative start priority (default 999)
autostart=true                 ; start at supervisord start (default: true)
startsecs=10                   ; # of secs prog must stay up to be running (def. 1)
startretries=10                ; max # of serial start failures when starting (default 3)
;autorestart=unexpected        ; when to restart if exited after running (def: unexpected)
;exitcodes=0,2                 ; 'expected' exit codes used with autorestart (default 0,2)
;stopsignal=QUIT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false             ; send stop signal to the UNIX process group (default false)
;killasgroup=false             ; SIGKILL the UNIX process group (def false)
user=www                       ; setuid to this UNIX account to run the program
;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
stdout_logfile=/var/log/supervisor/supervisor.log        ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=50MB   ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false   ; emit events on stdout writes (default false)
stderr_logfile=/var/log/supervisor/supervisor_err.log        ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=50MB   ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
;stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false   ; emit events on stderr writes (default false)
;environment=A="1",B="2"       ; process environment additions (def no adds)
;serverurl=AUTO                ; override serverurl computation (childutils)

杀掉supervisord,重新启动:

root@ecs2core4g:~# pgrep -ax supervisord
748 /usr/bin/python /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
root@ecs2core4g:~# kill 748
root@ecs2core4g:~# supervisord  -c /etc/supervisor/supervisord.conf
root@ecs2core4g:~# supervisorctl  -c /etc/supervisor/supervisord.conf status 
demoapp                          RUNNING   pid 1153, uptime 0:00:11
root@ecs2core4g:~# 

重启linux,查看80端口(nginx的端口),应该还是可以看到hello world。

注意,supervisor查找配置文件的顺序如下,我们使用的是/etc/supervisor/supervisord.conf,如果/etc/supervisord.conf也存在,请手动删除。
$CWD/supervisord.conf
$CWD/etc/supervisord.conf
/etc/supervisord.conf
/etc/supervisor/supervisord.conf (since Supervisor 3.3.0)
../etc/supervisord.conf (Relative to the executable)
../supervisord.conf (Relative to the executable)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容