flask在heroku部署成功了,记录一下过程

参照《FlaskWeb开发:基于Python的Web应用开发实战》,也就所谓的“狗书”,比利牛斯獒犬。绕了不少弯。

17.3 云部署

整个项目要用本地的git进行版本控制(个别文件除外)

注册heroku账户,不能用qq邮箱,推荐用google的gmail

安装heroku toolbelt(命令行工具,就像前面的manager一样,安装tookbelt以后才能使用各种heroku命令)

书上说toolbelt由两个程序组成 heroku + foreman,但foreman现在已经被官方弃用,用heroku local替代了(https://devcenter.heroku.com/changelog-items/692
Heroku Local has replaced Foreman in the Heroku Toolbelt

所以实际上toolbelt包含heroku + heroku local.

下载安装完,就可以在根目录用cmd或者git bash使用heroku的命令。

登陆heroku:不能用书上的 $ heroku login ,否则国内上不去,挂代理会显示 IP address mismatch。

$ heroku login -i

输入heroku的账号密码登陆。ssh公钥如果后面出现问题,就按书上的方法重新上传就好了。

创建程序

$ heroku create <appname>

配置数据库 $ heroku addons:add heroku-postgresql:dev ,把后面的:dev去掉,这里是用来设定数据库类型的,默认我们是hobby-dev,兴趣使然的开发者。

$ heroku addons:add heroku-postgresql

书上说的什么棕色不用管他,查看官方说明就知道,颜色类似1234是编号而已,因为可能会有多数据库。颜色没有高低级别的区分。数据库地位提升,意思是把哪个数据库设置为主数据库,仅此而已。没有什么地位啥的。

由于目前只有一个数据库,所以下面的$ heroku pg:promote HEROKU_POSTGRESQL_BROWN_URL 可以不用管。

配置好数据库以后,heroku会把这个数据库的地址放在heroku的环境变量DATABASE_URL里.(heroku的环境变量不在本地,可以用 $ heroku config 查看heroku的当前所有环境变量)DATABASE_URL在config.py里,之前已经有的。

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

配置日志

heroku启动manage.py时,要执行app = create_app(os.getenv('FLASK_CONFIG') or 'default')

要以生产模式来create,所以要设定FLASK_CONFIG。以下就是在heroku手动设置环境变量的方法。

$ heroku config:set FLASK_CONFIG=heroku

书上给的不够全,同时还要改config.py里的

config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig,
    'heroku': HerokuConfig    #加上这行
}

配置电子邮件,之前我们的邮件账户密码是在venv里用set设的,或者干脆直接放到代码里。但在生产环境里不可以放代码里,

同样设置到heroku的环境变量里。qq邮箱可用,gmail没试过。参照书本。

web服务器

书上提供gunicorn,和uWSGI。不知道书上为什么提供gunicorn,查了一下,不能在windows用,uWSGI没试过。查资料(https://dormousehole.readthedocs.io/en/latest/tutorial/deploy.html)发现了waitress,那就用waitress来做web服务器。(venv) $ pip install gunicorn

(venv) $ pip install waitress

运行不用(venv) $ gunicorn manage:app ,waitress的运行方法是这样的

(venv) $ waitress-serve manage:app

waitress运行使用的端口不是5000而是8080,执行时可能会报错 OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。(解决方法:https://blog.csdn.net/gsls200808/article/details/52456136)是因为8080口被占用了,找出来,终止掉就好了。命令行里删不掉可以直接开任务管理器删。

添加需求文件。

-r requirements/prod.txt
waitress==1.4.4
psycopg2==2.8.6

注意除了重新创建这个文件,还要把原来的requirements/common.txt更新一下。导出当前venv里所有扩展包的方法,之前书上有讲。对照着修改

(venv) $ pip freeze >起个名.txt

Procfile文件。不用gunicorn当然web: gunicorn manage:app ,内容改为。(https://docs.pylonsproject.org/projects/waitress/en/latest/usage.html  这一页最底下有一堆,先不用那些附加命令)

web: waitress-serve manage:app

(后面正式push的时候还要改,现在先这样)

foreman不能用了,就用heroku local测试,目的就是让你正式push到heroku之前,先在本地像heroku那样运行一下。heroku local和foreman其实很像,同样需要在.env里找环境变量。直接改名可能改不出.env,可以先随便起个名,再cmd里用

rename 你起的名字.env .env

不用foreman所以下面的(venv) $ foreman run python manage.py deploy ,改为

(venv) $ heroku local:run manage.py deploy

执行后可能会报错,说 没有 table user,或者 表的属性 重复之类的。问题可能出在manage.py的deploy()上

解决方法:可以把upgrade()加个#,或者加一行db.create_all()。重复deploy

启动 (venv) $ foreman start

(venv) $ heroku local

因为web服务器是waitress,占用8080,可能再次出现OSError: [WinError 10013]

使用Flask-SSLify启用安全HTTP,要$ pip install Flask-SSLify

处理代理服务器首部,from werkzeug.contrib.fixers import ProxyFix (参考:https://werkzeug.palletsprojects.com/en/1.0.x/middleware/proxy_fix/?highlight=proxyfix#werkzeug.middleware.proxy_fix.ProxyFix)

from werkzeug.middleware.proxy_fix import ProxyFix

正式部署git push heroku master,第一次时间可能长一点,那边要安装各种包。后面小修改再push就快了。

同样要deploy, $ heroku run python manage.py deploy,要在python后面加个3.

$ heroku run python3 manage.py deploy

重启

$ heroku restart

打开,很可能是出错的。

$ heroku open

出错就用 $ heroku logs --tail 查看日志(建议用cmd执行,这里cmd是彩色,git bash反而是全白的)

我遇到的错误:

日志里有一行Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

(查阅了:https://ruby-china.org/topics/11010

刚才配置Procfile时,那一堆代码里有一句--listen "*:$PORT" \ ,我们改一下Procfile

web: waitress-serve --listen=*:$PORT  manage:app

重新git add,git commit,push,restart解决问题。网页可以用访问了

添加了listen以后,再用heroku local是打不开的,显示: socket.gaierror: [Errno 10109] getaddrinfo failed
ValueError: Invalid host/port specified

 

 

 

 

 

上一篇:Spark学习笔记


下一篇:URL 栏调整大小