The Flask Mega-Tutorial 之 Chapter 17:Deployment on Linux (部署)

创建 Ubuntu Server

申请了ali_ECS,系统配置 Ubuntu 16.04。

替代方案: 自己安装 Vagrant 或 Virtualbox


使用 SSH Client

  • Linux:内置 openssh
  • Win:可以使用 Xshell (Cygwin, Git, and the Windows Subsystem for Linux,都提供 openssh)

利用 openssh 登录 virtual server 的 公网 IP

$ ssh root@<server-ip-address>

键入密码,登录 root 账号。


Password-less Logins

创建专门用于部署的用户账号,配置成无密码登录,以后登录更便捷且安全。

1、创建新用户,用于 deployment

利用 ssh 登录 virtual server 的 root 账号,创建新用户 ubunutu,并赋予 sudo 权限

$ adduser --gecos "" ubuntu
$ usermod -aG sudo ubuntu
$ su ubuntu
  • --gecos"",表示创建时省略常规信息(地址、号码等);adduserscript,会自动创建 /home 下的用户目录并提升输入密码,而useradd 是 command,仅创建用户,须自己用 passwd <username> 来赋密码。
  • usermod,改变用户权限,-aG 等同 -G,修改用户所属的附加群组; -g,修改所属群组。
  • su ubuntu,切换用户。su -l ubuntu,切换用户的同时,切换环境变量。


2、创建密钥对,并将公钥添加到 virtual server 的 authorized_keys

  • 本地检查 ~/.ssh/ 下,是否存在 keypair id_rsa 、 id_rsa.pub。若无,则自己创建 (如无 dir,亦自己创建)
  • $ ssh-keygen 创建 keypair(创建时,可自我命名):ali_ECS + ali_ECS.pub
  • 查看公钥内容,并复制
$ cat ~/.ssh/id_rsa.pub
  • 粘贴到 virtual server 的 authorized_keys(如无,则自我创建)
$ echo <paste-ssh-pub-key> >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

chmod 修改权限为 user: rw-, group+others: —

SSH 原理:
1.USER 发起 SSH 请求
2.服务器生成随机数 R1 发给 USER,USER 用私钥加密生成 R2。
3.USER 把 R2 回发给服务器,服务器用公钥解密并对比 R1,相同则成功连接。

  • 退出 virtual server 的 session,并退出 root,重新登录
$ ssh ubuntu@<server-ip-address>

Securing Your Server

1、为强化 virtual server 的安全性,对 virtual serverssh 进行:

  • Disable root logins

    因为已有 password-less login 的账号 ubuntu,并且其具有 sudo 权限,故无需暴露 root account。

    /etc/ssh/sshd_config

# sudo vim /etc/ssh/sshd_config
PermitRootLogin no
  • Disable password logins

    ubuntu 账号已可以 password-less login,故无需暴露 password logins(可以防止黑客暴力破解)。

# sudo vim /etc/ssh/sshd_config
PasswordAuthentication no


2、重启 virtual server 的 SSH

$ sudo service ssh restart


3、安装防火墙 ufw (optional for ali_ECS)

$ sudo apt-get install -y ufw
$ sudo ufw allow ssh
$ sudo ufw allow http
$ sudo ufw allow 443/tcp
$ sudo ufw --force enable
$ sudo ufw status
  • ufw --force enable, By default, ufw will prompt when enabling the firewall while running under ssh. This can be disabled by using ‘ufw –force enable’.
  • 对外开放的端口: 22 (ssh), 80 (http) and 443 (https)
    sudo ufw status

Installing Base Dependencies

1、 预装 packagesPython 3.5.2(ali_ECS Ubuntu 16.04)

2、 待装 packagesMySQLsupervisornginxgit

  • MySQL 替换 development 的 SQLite
  • supervisor 监视 Flask server 的 process,并在其崩溃或重启时,自动拉起
  • nginx,接收所有的外部 request,并 forward 给 application(将 80 端口的请求,全部转到 443,并动态地转发给 virtual server 的 localhost: 8000)
  • git,从 github 下载 application,并用于以后的更新(git pull)
$ sudo apt-get -y update
$ sudo apt-get -y install python3 python3-venv python3-dev
$ sudo apt-get -y install mysql-server postfix supervisor nginx git


- posftfix,MTA(mailtransfer agent),由于配置需要 real domain name,故未安装,仍按照 development 的配置,使用 googlemail 的 smtp。
- Elasticsearch,由于 ECS 的内存为 1G,低于 Elasticsearch 的最低要求 2G,故此功能不予部署。


Installing the Application

1、从 git repo 克隆最新版的 application

/home/ubuntu 下:

$ git clone https://github.com/Kungreye/Flask_microblog
$ cd Flask_microblog


2、在 app root dir 中,创建 venv

/home/ubuntu/Flask_microblog 下:

$ python3 -m venv venv
$ source venv/bin/activate


3、激活虚拟环境 venv,安装所有的 package dependencies
(venv) $ pip install -r requirements.txt

注: 未用 pipenv ,降低 virtual server 的消耗,并提高 ECS 的速度(pipenv 还须自己更改source,ECS 已默认配置 pip 为 mirror.aliyun)。
若使用 pipenv,则可以通过 pipfile 安装 dependencies $ pip install -p


4、安装 gunicornpymysql (for deployment)

适用于 production deployment,不在 requirements.txt

(venv) $ pip install gunicorn pymysql
  • gunicorn,支持wsgi协议的 http server,用于解决 Flask 自带 wsgi server 性能低下的问题。
  • pymsql,数据库驱动,使SQLAlchemy 能够与 MySQL 协同


5、创建 .env 文件

/home/ubuntu/microblog/.env: environment configuration.

SECRET_KEY=d2e12f0be72e428f8d00d179935ac2b7

DATABASE_URI=mysql+pymysql://<user>:<passwd>@localhost:3306/Flask_microblog
#'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'

MAIL_SERVER=smtp.googlemail.com
MAIL_PORT=587
MAIL_USE_TLS=1 
MAIL_USERNAME=.... 
MAIL_PASSWORD=....

MS_TRANSLATOR_KEY=<Microsoft Translator API Authentication Key>
  • SECRET_KEY 生成方式:python3 -c "import uuid; print(uuid.uuid4().hex)"
  • DATABASE_URI‘数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名’ (MySQL 配置见下)
  • MAIL_SERVER,因为无 domain name,无法使用 postfix,故仍按照 development 使用谷歌的 SMTP
  • MS_TRANSLATOR_KEY,保留 MS 的翻译API。

注: Elasticsearch 因内存不予部署,故 .env 中相应部分为空。


6、 设置 FLASK_APP 环境变量

.env 是在 config.py 中载入(load_dotenv(os.path.join(basedir, ‘.env’)))。为使 flask 的相关命令可用,必须在.env被解析之前,完成 FLASK_APP 环境变量的设置:

$ echo "export FLASK_APP=microblog.py" >> ~/.profile


注:

  • Bourne-style shell (sh, ksh, bash),写入~/.profile.
  • Zsh,写入 ~/.zprofile
  • Csh and tcsh,~/.login


此时,可以验证 flask --helpflask translate --help
flask --help

flask translate --help


7、 flask translate compile

因为 .po 文件对应的译文文件 .mo 没有加入 source control,故 git clone 的时候,只克隆了 .po, 对应的 .mo 未克隆下来。

利用 xshell 的 lrzsz,将 本地的 .mo 传到 ECS 下的对应文件夹下 ~/Flask_microblog/app/translations/<lang>/LC_MESSAGES/

运行如下命令,做

(venv) $ flask translate compile



Setting Up MySQL

1、更改 MySQL 的字符设置

/etc/mysql/my.cnf

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
skip-character-set-client-handshake

这里写图片描述

2、创建新用户、新数据库
mysql> create database Flask_microblog;
mysql> create user 'kungreye'@'localhost' identified by '<db-password>';
mysql> grant all privileges on Flask_microblog.* to 'kungreye'@'localhost';
mysql> flush privileges;
mysql> quit;


  • 信息须与 .env 中的 DATABASE_URI 保持一致:
DATABASE_URI=mysql+pymysql://<user>:<passwd>@localhost:3306/Flask_microblog
  • <db-pasword> 勿与 ubuntu 或 root 用户的登录密码相同。

3、生成 db tables
(venv) $ flask db upgrade

flask db upgrade

可以看到,生成了三个 tables : users posts followers

tables


Setting Up Gunicorn and Supervisor


1、gunicorn

gunicorn,支持 wsgi 协议的 http server,用于解决 Flask 自带 wsgi server 性能低下的问题。

gunicorn wsgi server

如图示, gunicorn 即担当 WSGI server,而 Web server,则由后面谈及的 nginx 担当。


利用 gunicorn 启动 Flask_microblog:

(venv) $ gunicorn -b localhost:8000 -w 4 microblog:app
  • -b,gunicorn 监听 request 的端口设置

    It is usually a good idea to run Python web applications without external access, and then have a very fast web server that is optimized to serve static files accepting all requests from clients

  • -w, how many workers gunicorn will run for handling concurrent clients

  • microblog, the module containing the application
  • app,the name of the application

这里写图片描述


2、配置 supervisor
  • 直接从命令行启动 application server 的方式不够理想
  • 希望 application server 于后台运行,并被实时监控
  • application server 崩溃或退出时,希望能被自动开启新的 application server
  • virtual machine 重启时,希望 application server 能无需人工登录而自动启动

/etc/supervisor/conf.d/Flask_microblog.conf: supervisor configuration.

# ubuntu@UbuntuServer16:/etc/supervisor/conf.d$ cat Flask_microblog.conf 
[program:Flask_microblog]
command=/home/ubuntu/Flask_microblog/venv/bin/gunicorn -b localhost:8000 -w 4 microblog:app
directory=/home/ubuntu/Flask_microblog
user=ubuntu
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true


注:
- [program:Flask_microblog],指定服务名为 Flask_microblog
- command,指定启动 gunicorn 来监视 microblog.py 中的 app
- autostart、autorestart,计算机启动或奔溃时,自动重启
- killasgroup、 stopasgroup,当 supervisor 需要停止 application 以便重启时,会涉及到 gunicorn 的子进程。

when supervisor needs to stop the application to restart it, it also reaches the child processes of the top-level gunicorn process.


重新载入 supervisor

$ sudo supervisorctl reload

supervisor status


Setting Up Nginx

Nginx 担当 Web server,利用对外开放的端口(80/443)接收请求。
如果是静态请求,则直接返回相应资源;
如果是动态请求,则缓存请求后,转发到 WSGI server(本项目为 gunicorn)。

Nginx 与 gunicorn 的关系

gunicorn 可以单独提供服务,但生产环境一般不这样做。
首先静态资源(jscssimg)会占用不少的请求资源,而对于 gunicorn 来讲它本身更应该关注实际业务的请求与处理而不应该把资源浪费在静态资源请求上;此外,单独运行 gunicorn 是没有办法起多个进程多个端口来负载均衡的。
nginx 的作用就是弥补以上问题,首先作为前端服务器它可以处理一切静态文件请求,此时 gunicorn 作为后端服务器,nginx 将会把动态请求转发给后端服务器,因此我们可以起多个 gunicorn 进程,然后让 nginx 作均衡负载转发请求给多个 gunicorn 进程从而提升服务器处理效率与处理能力。最后,nginx 还可以配置很多安全相关、认证相关等很多处理,可以让你的网站更专注业务的编写,把一些转发规则等其它业务无关的事情交给 nginx 做。

web server: nginx

1、self-signed certificate

为保证部署安全,将 80 端口接收的所有请求转到 443(ssl),为此须生成 自签名SSL验证:

~/Flask_microblog/ 下:

$ mkdir certs
$ openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
  -keyout certs/key.pem -out certs/cert.pem
  • key.pem,store the private key in a file called key.pem
  • cert.pem,store the certificate request in a file called cert.pem

参见 how 2 ssl


2、配置 nginx
  • / etc / nginx/ sites-available 下: 建立 Flask_microblog
server {
    # listen on port 80 (http)
    listen 80;
    server_name _;
    location / {
        # redirect any requests to the same URL but on https
        # 301: Moved Permanently
        return 301 https://$host$request_uri;
    }
}
server {
    # listen on port 443 (https)
    listen 443 ssl;
    server_name _;

    # location of the self-signed SSL certificate
    ssl_certificate /home/ubuntu/Flask_microblog/certs/cert.pem;
    ssl_certificate_key /home/ubuntu/Flask_microblog/certs/key.pem;

    # write access and error logs to /var/log
    access_log /var/log/Flask_microblog_access.log;
    error_log /var/log/Flask_microblog_error.log;

    location / {
        # forward application requests to the gunicorn server
        proxy_pass http://localhost:8000;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /static {
        # handle static files directly, without forwarding to the application
        alias /home/ubuntu/Flask_microblog/app/static;
        expires 30d;
    }
}


3、建立软链接到 /etc / nginx / sites-enabled

格式: ln -s source_point target_point

# /etc/nginx/sites-enabled/ 下
sudo ln -s /etc/nginx/sites-available/Flask_microblog .

或者

sudo ln -s /etc/nginx/sites-available/Flask_microblog /etc/nginx/sites-enabled/Flask_microblog


4、重载 nginx
$ sudo service nginx reload

通过sudo service nginx status 查看状态:

nginx status

至此,部署结束,可以打开本地浏览器,键入 virtual-server-IP,验证部署:
这里写图片描述

部署成功~


Deploying Application Updates

application 更新后,git pull 后并不能直接更新已部署的 app,因为旧的 code 仍在 memory 中存储执行。

按以下步骤,进行更新部署:

(venv) $ git pull                              # download the new version
(venv) $ sudo supervisorctl stop microblog     # stop the current server
(venv) $ flask db upgrade                      # upgrade the database
(venv) $ flask translate compile               # upgrade the translations
(venv) $ sudo supervisorctl start microblog    # start a new server
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值