• Flask自带的开发服务器不适合用作生产环境。

部署流程

不论哪种托管方案,应用安装到生产服务器上之后都要执行一系列的任务,其中包括创建和更新数据库表。如果每次都手动操作会很麻烦,因此编写py程序来做这些工作。

from flask_migrate import  upgrade
from app.models import User, Follow, Role, Permission, Post, Comment
from app import create_app, db

app = create_app()

@app.cli.command()
def deploy():
    """Run deployment tasks."""
    # migrate database to latest revision
    upgrade()

    # create or update user roles
    Role.insert_roles()		# 初始化角色表中的角色

    # ensure all users are following themselves
    User.add_self_follows()	# 关注模块:确保个体关注了自身

由于命令执行可能出错,所以在实现上面的函数的时候要考虑多次执行的情况,由于本身已经考虑了,所以这里如果deploy执行失败,多次执行不会有影响。


把生产环境中的错误写入日志

在dev环境下时Werkzeug是直接在shell里输出err_log和在网页显示错误信息。Prod环境不能对外展示错误,否则容易被黑客利用。这时候我们一般是进行错误重定向和写日志。应用启动时会创建logging.Logger的实例并附加在应用实例上通过app.logger访问。同时我们可以让错误日志发送到管理员的邮箱。

class ProductionConfig(Config):
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'data.sqlite')

    @classmethod
    def init_app(cls, app):
        Config.init_app(app)

        # email errors to the administrators
        import logging
        from logging.handlers import SMTPHandler
        credentials = None
        secure = None
        if getattr(cls, 'MAIL_USERNAME', None) is not None:
            credentials = (cls.MAIL_USERNAME, cls.MAIL_PASSWORD)
            if getattr(cls, 'MAIL_USE_TLS', None):
                secure = ()
        mail_handler = SMTPHandler(
            mailhost=(cls.MAIL_SERVER, cls.MAIL_PORT),
            fromaddr=cls.FLASKY_MAIL_SENDER,
            toaddrs=[cls.FLASKY_ADMIN],
            subject=cls.FLASKY_MAIL_SUBJECT_PREFIX + ' Application Error',
            credentials=credentials,
            secure=secure)
        mail_handler.setLevel(logging.ERROR)
        app.logger.addHandler(mail_handler)

部署方式有三种:

  1. 云部署
  2. 容器部署
  3. PaaS部署:上传代码到git服务器,git服务器自动出发安装、升级、配置和部署操作。

云部署

云托管:把应用部署到一台或堕胎虚拟服务器上(如Amazon的EC2)
方法与专用服务器部署一致,只是云服务器是虚拟服务器。

容器部署

容器把应用隔离在镜像(image)中,包含应用即其全部依赖。

PaaS部署(Heroku)

Heroku是一个PaaS平台,使用dyno计算单元衡量用量并据此收费。如:Web dyno、Worker dyno。

安装Git、heroku CLI (1)将代码托管到Git仓库:Github、Bitbucket等

heroku create <appname> # 全局独一无二的name
git remote show heroku  # 查看heroku为app提供的git url
heroku config:set FLASK_APP=depoly.py
  • 配置日志
    heroku把应用写入stdout、stderr的输出当作日志,我们需要添加相应的日志处理程序。使用heroku logs可以查看日志。
import logging
from logging import StreamHandler
file_handler = StreamHandler()
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
  • 生成密钥
    python -c "import uuid; print(uuid.uuid4().hex把输出可以当作SECURITY_KEY
heroku config:set SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
  • heroku安装插件举例:
heroku addons:create heroku-postgresql:hobby-dev

Reference

  1. Flask 应用如何部署
  2. 《Flask Web开发:基于Python的web开发应用实践》