本文记录一次 Flask 应用阿里云ECS部署实践过程,环境为 Ubuntu 16.04 ,工具集 Nginx + Gunicorn + Supervisor + Flask。
Linux 环境准备
因为阿里云安装的 Ubuntu 系统默认带 python 环境,所以只需要安装 python 虚拟环境 virtualenv 包
然后安装 nignx:
1
| sudo apt-get install nginx
|
创建项目目录,阿里云 root 用户登陆后默认当前目录为 /root
目录,你可以将程序放在任何目录下,推荐 /var/www/
下,本例中程序目录为:/var/www/MyFlaskApp
。
当然通常是实用 scp
命令将程序包从本机传到服务器目录:
1
| scp -r MyFlaskApp root@example.com:/var/www/MyFlaskApp
|
安装 supervisor:
1
| sudo apt-get install supervisor
|
gunicorn
进入程序目录,在虚拟环境下安装 gunicorn
1
| (venv) $ pip install gunicorn
|
运行 gunicorn
1
| (venv) $ gunicorn -w 4 -b 127.0.0.1:8080 wsgi:app
|
其中 -w
指定工作进程数量,-b
指定 Flask 服务地址,wsgi:app 实为 [MODULE_NAME:VARIABLE_NAME],通常在程序目录下单独创建一个文件(如:wsgi.py)将 Flask 实例暴露出来:
1 2 3 4 5 6 7 8 9 10 11 12
| from flask import Flask def create_app(): app = Flask(__name__) return app app = create_app() if __name__ == '__main__': app.run()
|
命令执行完后可在服务器端通过 127.0.0.1:8080 访问服务。
nginx 配置
直接修改配置文件 /etc/nginx/site-available/default
。(可先备份再修改)
1 2 3 4 5 6 7 8 9 10 11 12
| server { listen 80 default_server; listen [::]:80 default_server; server_name example.com location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
|
完成修改后重启 nginx: sudo service nginx restart
supervisor
supervisor 安装后,在配置目录下 /etc/supervisor/conf.d/
增加控制程序配置 MyFlaskApp.conf
1 2 3
| [program:MyFlaskApp] command=/var/www/MyFlaskApp/venv/bin/gunicorn -w 4 -b 127.0.0.1:8080 wsgi:app directory=/var/www/MyFlaskApp/
|
command 启动 gunicorn 的命令,应该指向程序虚拟环境下的 gunicorn。
directory 为程序所在目录。
重启 supervisor
1 2
| supervisorctl reload supervisorctl restart
|
现在就可以通过服务器外网访问 flask 服务了。
其他
安装 MySQL :
1 2 3
| sudo apt-get install mysql-server sudo apt-get install mysql-client sudo apt-get install libmysqlclient-dev
|
确保 MySQL 字符编码都是 utf8 格式(如果要支持emoji表情,格式为:utf8mb4):
1 2 3 4 5 6 7 8 9 10 11 12
| # /etc/mysql/my.cnf [client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] character-set-client-handshake = FALSE character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect='SET NAMES utf8mb4'
|
1 2 3
| mysql> status mysql> set character_set_server=utf8 mysql> set character_set_database=utf8
|
阿里云外网访问
阿里云默认的安全组规则只包含:ICMP访问、SSH(TCP 22)、远程桌面(UDP 3389),并不包含 Web (HTTP(s) 80(443))访问
HTTPS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| # /etc/nginx/ server { server_name example.com; listen 80 default_server; listen [::]:80 default_server; # SSL configuration listen 443 ssl default_server; listen [::]:443 ssl default_server; ssl_certificate cert/cert.pem; ssl_certificate_key cert/key.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; fastcgi_intercept_errors on; error_page 404 /404.html; location / { root /var/www/html; index index.html; } location ~ /(admin|api) { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
|
HTTP 跳转 HTTPS:
1 2 3 4 5 6
| server { server_name example.com; listen 80 default_server; listen [::]:80 default_server; return 301 https://$host$request_uri; }
|