Heroku平臺
Heroku
平臺的靈活性極高且支持多種編程語言。若想把程序部署到Heroku
上,開發(fā)者要使用Git
把程序推送到Heroku
的Git
服務(wù)器上。在服務(wù)器上,git push
命令會自動觸發(fā)安裝、配置和部署程序。
Heroku
使用名為Dyno
的計(jì)算單元衡量用量,并以此為依據(jù)收取服務(wù)費(fèi)用。最常用的Dyno
類型是Web Dyno
,表示一個Web
服務(wù)器實(shí)例。程序可以通過使用更多的Web Dyno
以增強(qiáng)其請求處理能力。另一種Dyno
類型是Worker Dyno
,用來執(zhí)行后臺作業(yè)或其他輔助任務(wù)。
Heroku
提供了大量的插件和擴(kuò)展,可用于數(shù)據(jù)庫、電子郵件支持和其他很多服務(wù)。
準(zhǔn)備程序
若想使用 Heroku,程序必須托管在 Git 倉庫中。如果你的程序托管在像 GitHub 或 BitBucket 這樣的遠(yuǎn)程 Git 服務(wù)器上,那么在本地 clone 程序后會創(chuàng)建一個本地 Git 倉庫,可無縫用于 Heroku。如果你的程序沒有托管在 Git 倉庫中,那么必須在開發(fā)電腦上創(chuàng)建一個倉庫。
注冊Heroku賬戶
安裝Heroku Toolbelt
Heroku Toolbelt
是用于創(chuàng)建、管理Heroku
上apps
的命令行工具
heroku 的命令行客戶端將被安裝到/usr/local/heroku
,同時(shí),/usr/local/heroku/bin
將被添加到你的PATH
環(huán)境變量
下載并安裝完成后,在 shell 中輸入heroku login
,用創(chuàng)建heroku
賬號的email
和密碼
登陸
$ heroku login
Enter your Heroku credentials.
Email: adam@example.com
Password (typing will be hidden):
Authentication successful.
把你的 SSH 公鑰上傳到 Heroku,這一點(diǎn)很重要,上傳后才能使用 git push 命令。正常情況下,login 命令會自動創(chuàng)建并上傳 SSH 公鑰。
創(chuàng)建程序
首先要確保程序在 Git 源碼控制系統(tǒng)中,然后在程序的頂級目錄下運(yùn)行創(chuàng)建命令
在 Heroku 創(chuàng)建一個 app, 以便 Heroku 準(zhǔn)備好接收你的代碼
當(dāng)你創(chuàng)建一個 app, 將創(chuàng)建并關(guān)聯(lián)一個名為
heroku
的遠(yuǎn)端到你的本地倉庫
apps:create [NAME] # create a new app
名稱必須以字母開始,只能包含小寫字母,數(shù)字和連字符, 而且名稱在 heroku 的所有程序中必須是唯一的
? flask_blog git:(rest) ? heroku apps:create flask-blog-chaonet
Creating flask-blog-chaonet... done, stack is cedar-14
https://flask-blog-chaonet.herokuapp.com/ | https://git.heroku.com/flask-blog-chaonet.git
Git remote heroku added
查看已創(chuàng)建的 app
? flask_blog git:(rest) ? heroku apps
=== My Apps
flask-blog-chaonet
默認(rèn) Heroku 會為你的 app 生成一個隨機(jī)的名字, 或者 你可以通過可選參數(shù)指定你的 app名。
現(xiàn)在,你可以向 Heroku 部署你的代碼了
$ git push heroku master
# 必須將 本地 的 master push 到 heroku 的 master
應(yīng)用現(xiàn)在已經(jīng)部署了,確保至少一個 app 的實(shí)例正在運(yùn)行:
$ heroku ps:scale web=1
現(xiàn)在,可以用創(chuàng)建的包含 app 名稱的 URL 訪問 app. 有一個便捷的方法, 你可以像這樣打開web站點(diǎn):
$ heroku open
配置數(shù)據(jù)庫
Heroku 以擴(kuò)展形式支持 Postgres 數(shù)據(jù)庫。少于 1 萬條記錄、同時(shí)連接數(shù) 20 、沒有緩存 、不允許fork/follow、沒有 Postgres 日志 的小型數(shù)據(jù)庫無需付費(fèi)即可添加 到程序中。
添加 Postgres 到 Heroku 應(yīng)用
通過命令行,將 Heroku Postgres 添加到一個 Heroku 應(yīng)用:
? flask_blog git:(rest) ? heroku addons:create heroku-postgresql:hobby-dev
Creating postgresql-sinuous-8326... done, (free)
Adding postgresql-sinuous-8326 to flask-blog-chaonet... done
Setting DATABASE_URL and restarting flask-blog-chaonet... done, v3
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pg:copy
Use `heroku addons:docs heroku-postgresql` to view documentation.
最低等級的業(yè)余版本有兩種方案 hobby-dev 和 hobby-basic
一旦 Heroku Postgres 被添加,一個 DATABASE_URL 設(shè)置將在 app 配置中生效,并包含用于訪問新提供的 Heroku Postgres 服務(wù)的 URL 。
這可以使用 heroku config 命令確認(rèn):
? flask_blog git:(rest) ? heroku config -s | grep DATABASE_URL
DATABASE_URL=postgres://bjtrukgnhvnban:T0_N_OWYVz6NnasUwOf0FxVscO@ec2-54-83-52-71.compute-1.amazonaws.com:5432/d44ph8k76dl0h0
amazonaws ?
- 建立主數(shù)據(jù)庫
Heroku 中的每個程序都支持多個數(shù)據(jù)庫。Heroku 建議使用 DATABASE_URL 變量保存主用數(shù)據(jù)庫信息。在單個數(shù)據(jù)庫的情況下,新的數(shù)據(jù)庫已經(jīng)被指定到 DATABASE_URL 。
對于多個數(shù)據(jù)庫的情況,可以設(shè)置主用數(shù)據(jù)庫:
$ heroku pg:promote HEROKU_POSTGRESQL_RED
Promoting HEROKU_POSTGRESQL_RED_URL to DATABASE_URL... done
DATABASE_URL 環(huán)境變量的格式正是 SQLAlchemy 所需的。回想一下 config.py 腳本的內(nèi)容,如果 設(shè)定了 DATABASE_URL,就使用其中保存的值,所以現(xiàn)在程序可以自動連接到 Postgres 數(shù)據(jù)庫。
- 查看數(shù)據(jù)庫使用信息
? flask_blog git:(rest) ? heroku pg:info
=== DATABASE_URL
Plan: Hobby-dev
Status: Available
Connections: 0/20
PG Version: 9.4.5
Created: 2016-01-09 02:57 UTC
Data Size: 6.7 MB
Tables: 0
Rows: 0/10000 (In compliance)
Fork/Follow: Unsupported
Rollback: Unsupported
Add-on: postgresql-sinuous-8326
在 MAC 中安裝 Postgres
推薦在本地開發(fā)環(huán)境與生產(chǎn)環(huán)境運(yùn)行相同的數(shù)據(jù)庫
使用Postgres.app
,是在 Mac 下使用PostgreSQL
的最簡單的方法
在postgresapp下載Postgres.app
解壓后將Postgres
移到應(yīng)用程序
文件夾
雙擊,然后你的 MAC 中就有一個PostgreSQL
服務(wù)器在運(yùn)行了
- 使用 Postgres.app 的命令行工具
配置$PATH
變量
? psycopg2-2.6.1 which psql
psql not found
? psycopg2-2.6.1 export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/latest/bin
? psycopg2-2.6.1 which psql
/Applications/Postgres.app/Contents/Versions/latest/bin/psql
通過命令psql
連接你的數(shù)據(jù)庫
? psycopg2-2.6.1 psql -h localhost
psql (9.5.0)
Type "help" for help.
chao-# \q
? psycopg2-2.6.1
Using Command Line Tools with Postgres.app
與 Python 對接
? psycopg2-2.6.1 pip install psycopg2
Collecting psycopg2
Using cached psycopg2-2.6.1.tar.gz
Building wheels for collected packages: psycopg2
Running setup.py bdist_wheel for psycopg2
Stored in directory: /Users/chao/Library/Caches/pip/wheels/e2/9a/5e/7b620848bbc7cfb9084aafea077be11618c2b5067bd532f329
Successfully built psycopg2
Installing collected packages: psycopg2
Successfully installed psycopg2-2.6.1
遇到的問題:
沒有通過 postgres.app 安裝 Postgres,就安裝 psycopg2 ,結(jié)果報(bào)錯
- pip 安裝
? flask_blog git:(rest) ? pip install psycopg2
Collecting psycopg2
Using cached psycopg2-2.6.1.tar.gz
Complete output from command python setup.py egg_info:
running egg_info
creating pip-egg-info/psycopg2.egg-info
writing pip-egg-info/psycopg2.egg-info/PKG-INFO
writing top-level names to pip-egg-info/psycopg2.egg-info/top_level.txt
writing dependency_links to pip-egg-info/psycopg2.egg-info/dependency_links.txt
writing manifest file 'pip-egg-info/psycopg2.egg-info/SOURCES.txt'
warning: manifest_maker: standard file '-c' not found
Error: pg_config executable not found.
Please add the directory containing pg_config to the PATH
or specify the full executable path with the option:
python setup.py build_ext --pg-config /path/to/pg_config build ...
or with the pg_config option in 'setup.cfg'.
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /private/var/folders/36/tdbs35wx1sx4d6nm4hrmwy0h0000gn/T/pip-build-XR5kDF/psycopg2
- 下載安裝包安裝
? psycopg2-2.6.1 ls
AUTHORS LICENSE MANIFEST.in NEWS README.rst examples psycopg setup.cfg tests
INSTALL MANIFEST Makefile PKG-INFO doc lib scripts setup.py
? psycopg2-2.6.1 python setup.py build
running build
running build_py
creating build
creating build/lib.macosx-10.6-intel-2.7
creating build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/__init__.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/_json.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/_range.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/errorcodes.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/extensions.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/extras.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/pool.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/psycopg1.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/tz.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
creating build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/__init__.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/dbapi20.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/dbapi20_tpc.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_async.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_bug_gc.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_bugX000.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_cancel.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_connection.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_copy.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_cursor.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_dates.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_extras_dictcursor.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_green.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_lobject.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_module.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_notify.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_psycopg2_dbapi20.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_quote.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_transaction.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_types_basic.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_types_extras.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_with.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/testconfig.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/testutils.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
running build_ext
Error: pg_config executable not found.
Please add the directory containing pg_config to the PATH
or specify the full executable path with the option:
python setup.py build_ext --pg-config /path/to/pg_config build ...
or with the pg_config option in 'setup.cfg'.
? psycopg2-2.6.1
配置 Python 用于 Postgres.app
在 Flask 中使用 Flask-SQLAlchemy 擴(kuò)展時(shí),可以直接在配置中定義,并由 app 讀取。
配置日志
任何寫到 標(biāo)準(zhǔn)輸出(stdout) 或標(biāo)準(zhǔn)錯誤(stderr) 的信息才會被 Heroku 抓取到日志,并在 Heroku 客戶端通過heroku logs
命令查看。
config.py
# 輸出到 stderr,以便被 Heroku 抓取到 logs
import logging
from logging import StreamHandler
file_handler = StreamHandler()
file_handler.setLevel(logging.WARNING)
app.logger.addHandler(file_handler)
定義配置變量
Heroku 可以讓你在程序外部配置變量 —— 存儲類似加密密鑰
或外部資源地址
的數(shù)據(jù)。
在運(yùn)行時(shí), 配置的變量被當(dāng)做環(huán)境變量暴露給應(yīng)用。
變量可以用Heroku
的命令行工具配置,也可以在應(yīng)用的Dashboard
頁面的settings
頁簽下配置。
配置電子郵件
Heroku 沒有提供 SMTP 服務(wù)器,所以我們要配置一個外部服務(wù)器。很多第三方擴(kuò)展能把 適用于生產(chǎn)環(huán)境的郵件發(fā)送服務(wù)集成到 Heroku 中,但對于測試和評估而言,使用繼承自 Config 基類的 mail 配置已經(jīng)足夠了。
由于直接把安全密令寫入腳本存在安全隱患,所以我們把訪問 mail SMTP服務(wù)器的用戶 名和密碼保存在環(huán)境變量中。
運(yùn)行生產(chǎn) Web 服務(wù)器
Heroku 沒有為托管程序提供 Web 服務(wù)器,相反,它希望程序啟動自己的服務(wù)器并監(jiān)聽環(huán) 境變量 PORT 中設(shè)定的端口。
Flask 自帶的開發(fā) Web 服務(wù)器表現(xiàn)很差,因?yàn)樗皇菫樯a(chǎn)環(huán)境設(shè)計(jì)的服務(wù)器。有兩個 可以在生產(chǎn)環(huán)境中使用、性能良好且支持 Flask 程序的服務(wù)器,分別是Gunicorn和uWSGI。
若想在本地測試 Heroku 配置,我們最好在虛擬環(huán)境中安裝 Web 服務(wù)器。例如,可通過如下命令安裝 Gunicorn:
(venv) $ pip install gunicorn
若要使用 Gunicorn 運(yùn)行程序,可執(zhí)行下面的命令:
(venv) $ gunicorn manage:app
2013-12-03 09:52:10 [14363] [INFO] Starting gunicorn 18.0
2013-12-03 09:52:10 [14363] [INFO] Listening at: http://127.0.0.1:8000 (14363)
2013-12-03 09:52:10 [14363] [INFO] Using worker: sync
2013-12-03 09:52:10 [14368] [INFO] Booting worker with pid: 14368
manage:app 參數(shù)冒號左邊的部分表示定義程序的包或者模塊
,冒號右邊的部分表示包中程序?qū)嵗拿?/code>。注意,Gunicor 默認(rèn)使用端口 8000,而 Flask 默認(rèn)使用 5000。
添加依賴需求文件
Heroku 從程序頂級文件夾下的 requirements.txt 文件中加載包依賴。這個文件中的所有依賴都會在部署過程中導(dǎo)入 Heroku 創(chuàng)建的虛擬環(huán)境。
Heroku 的需求文件必須包含程序在生產(chǎn)環(huán)境中使用的所有通用依賴,以及支持 Postgres 數(shù)據(jù)庫的 psycopg2 包和 Gunicorn Web 服務(wù)器。
可以在需求文件中導(dǎo)入需求文件。
requirements.txt
-r requirements/prod.txt
gunicorn==18.0
psycopg2==2.5.1
添加Procfile文件
Heroku 需要知道使用哪個命令啟動程序。命令在一個名為Procfile
(沒有后綴)的特殊文件中指定。這個文件必須放在程序的頂級文件夾中。
web: gunicorn manage:app
Procfile
文件內(nèi)容的格式很簡單:在每一行中指定一個任務(wù)名,后跟一個冒號,然后是執(zhí)行這個任務(wù)的命令。名為web
的任務(wù)比較特殊任務(wù),Heroku 使用這個任務(wù)啟動 Web 服務(wù)器。
Heroku 會為這個任務(wù)提供一個PORT
環(huán)境變量,用于設(shè)定程序監(jiān)聽請求的端口。如果設(shè)定了PORT
變量, Gunicorn
默認(rèn)就會使用其中保存的值,因此無需將其包含在啟動命令中。
部署程序后,Heroku 會運(yùn)行 Procfile 中列出的所有任務(wù)。
程序可在 Procfile 中使用 web 之外的名字聲明其他任務(wù),例如程序所需的其他服務(wù)。
使用 Heroku Local 進(jìn)行本地測試
Heroku Local
作為Heroku Toolbelt
的一部分, 自動被安裝。
- 在本地啟動所有在你的
Profile
中定義的任務(wù)
$ heroku local
heroku local
是heroku local:start
的簡寫,作用相同
? flask_blog git:(rest) ? heroku local
Downloading forego-0.16.1 to /Users/chao/.heroku... done
forego | starting web.1 on port 5000
web.1 | [2016-01-10 00:11:00 +0800] [17093] [INFO] Starting gunicorn 19.4.5
web.1 | [2016-01-10 00:11:00 +0800] [17093] [INFO] Listening at: http://0.0.0.0:5000 (17093)
web.1 | [2016-01-10 00:11:00 +0800] [17093] [INFO] Using worker: sync
web.1 | [2016-01-10 00:11:00 +0800] [17096] [INFO] Booting worker with pid: 17096
指定運(yùn)行的端口
? flask_blog git:(rest) ? heroku local -p 8000
forego | starting web.1 on port 8000
web.1 | [2016-01-10 00:20:22 +0800] [17237] [INFO] Starting gunicorn 19.4.5
web.1 | [2016-01-10 00:20:22 +0800] [17237] [INFO] Listening at: http://0.0.0.0:8000 (17237)
web.1 | [2016-01-10 00:20:22 +0800] [17237] [INFO] Using worker: sync
web.1 | [2016-01-10 00:20:22 +0800] [17240] [INFO] Booting worker with pid: 17240
web.1 | [2016-01-10 00:21:11 +0800] [17237] [CRITICAL] WORKER TIMEOUT (pid:17240)
web.1 | [2016-01-10 00:21:11 +0800] [17240] [INFO] Worker exiting (pid: 17240)
web.1 | [2016-01-10 00:21:11 +0800] [17244] [INFO] Booting worker with pid: 17244
可以在本地指定運(yùn)行一個特定的進(jìn)程類型,例如web
或worker
$ heroku local web
然后,你就可以在本地測試 app。使用Ctrl+C
停止
- 設(shè)置本地環(huán)境變量
在本地運(yùn)行 APP,同樣需要輸入一系列 配置變量 作為 app 的配置。.env
文件讓你可以收集 app 在本地運(yùn)行所需要的配置變量。當(dāng)使用heroku local
命令運(yùn)行 APP,將會讀取.env
文件,并且,每一個 名稱/值 對會被插入環(huán)境中,模仿實(shí)際的配置變量。
增加一個配置變量到你的.env
文件:編輯.env
文件,并在新的一行增加一個新name=value
對。
由于.env
文件中包含密碼和其他敏感的賬戶信息, 所以決不能將其添加到 Git 倉庫中,這個文件應(yīng)該只在存在于本地配置中。使用:echo .env >> .gitignore
, 將.env
文件列入 git 的忽略文件列表。
需要注意,你部署的生產(chǎn) app 可能使用到與本地開發(fā) app 不同的服務(wù)。例如,部署的生產(chǎn) app 可能有一個引用
Heroku Postgres
數(shù)據(jù)庫的DATABASE_URL
配置變量,但你的本地 app可能在.env
文件中有一個引用本地安裝的Postgres
的DATABASE_URL
變量。
有時(shí)你可能想要在本地使用和 Heroku 環(huán)境相同的配置變量。對于每一個你想要添加到.env
文件的配置變量,使用如下命令:
$ heroku config:get CONFIG-VAR-NAME -s >> .env
- 查看環(huán)境變量
使用heroku config
查看 app 的所有配置變量。使用cat .env
查看.env
文件的內(nèi)容
- 另一個本地測試工具 Foreman
除了heroku local
,原本的foreman
也可以使用,但不再提供官方的支持,需要另外安裝。
Heroku Local has replaced Foreman in the Heroku Toolbelt
執(zhí)行 git push 命令部署
部署過程的最后一步是把程序上傳到 Heroku 服務(wù)器。在此之前,你要確保所有改動都已經(jīng)提交到本地Git倉庫,然后執(zhí)行git push heroku master
把程序上傳到遠(yuǎn)程倉庫heroku
。
上傳代碼,中間遇到一個坑,一開始從本地的rest
分支向heroku
的master
推送,報(bào)錯
? flask_blog git:(rest) git push heroku master
Counting objects: 315, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (309/309), done.
Writing objects: 100% (315/315), 82.51 KiB | 0 bytes/s, done.
Total 315 (delta 190), reused 3 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote:
remote: ! Push rejected, no Cedar-supported app detected
remote: HINT: This occurs when Heroku cannot detect the buildpack
remote: to use for this application automatically.
remote: See https://devcenter.heroku.com/articles/buildpacks
remote:
remote: Verifying deploy....
remote:
remote: ! Push rejected to flask-blog-chaonet.
remote:
To https://git.heroku.com/flask-blog-chaonet.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/flask-blog-chaonet.git'
? flask_blog git:(rest) heroku buildpacks:set heroku/python
Buildpack set. Next release on flask-blog-chaonet will use heroku/python.
Run git push heroku master to create a new release using this buildpack.
? flask_blog git:(rest) git push heroku master
Counting objects: 315, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (309/309), done.
Writing objects: 100% (315/315), 82.56 KiB | 0 bytes/s, done.
Total 315 (delta 190), reused 3 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Using set buildpack heroku/python
remote:
remote: ! Push rejected, failed to detect set buildpack heroku/python
remote: More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
remote:
remote: Verifying deploy....
remote:
remote: ! Push rejected to flask-blog-chaonet.
remote:
To https://git.heroku.com/flask-blog-chaonet.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/flask-blog-chaonet.git'
感覺可能是 分支名稱的問題,嘗試切換到 master,合并分支后再試
? flask_blog git:(rest) git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
? flask_blog git:(master) ? git merge rest
Updating 40d4e6e..90872cd
Fast-forward
.gitignore | 2 +
Procfile | 1 +
app.db | Bin 76800 -> 83968 bytes
app/__init__.py | 67 +++++----
app/api_1_0/__init__.py | 5 +
app/api_1_0/authentication.py | 59 ++++++++
app/api_1_0/comments.py | 79 +++++++++++
app/api_1_0/decorators.py | 21 +++
app/api_1_0/errors.py | 21 +++
app/api_1_0/posts.py | 74 ++++++++++
app/api_1_0/users.py | 75 ++++++++++
app/auth/__init__.py | 5 +
app/auth/forms.py | 65 +++++++++
app/auth/views.py | 196 ++++++++++++++++++++++++++
app/email.py | 11 ++
app/exceptions.py | 4 +
app/main/__init__.py | 13 ++
app/main/error.py | 12 ++
app/main/forms.py | 69 ++++++++++
app/main/views.py | 401 +++++++++++++++++++++++++++++++++++++++++++++++++++++
app/models.py | 71 +++++++++-
app/templates/_comments.html | 10 +-
app/templates/_posts.html | 12 +-
app/templates/{ => auth/email}/confirm.html | 2 +-
app/templates/auth/email/confirm.txt | 6 +
app/templates/{ => auth/email}/confirmmail.html | 2 +-
app/templates/{ => auth/email}/confirmmail.txt | 2 +-
app/templates/{ => auth}/login.html | 4 +-
app/templates/{ => auth}/register.html | 0
app/templates/{ => auth}/renew.html | 0
app/templates/{ => auth}/unconfirmed.html | 2 +-
app/templates/base.html | 14 +-
app/templates/changepassword.html | 2 +-
app/templates/changepassword.txt | 2 +-
app/templates/confirm.txt | 6 -
app/templates/followers.html | 2 +-
app/templates/{ => main}/index.html | 6 +-
app/templates/main/moderate.html | 16 +++
app/templates/user.html | 14 +-
app/views.py | 1 -
app_pro.db | 0
app_test.db | Bin 0 -> 24576 bytes
config.py | 130 +++++++++++++----
requirements.txt | 43 ++++++
run.py | 114 ++++++++++++++-
test/test_api.py | 71 ++++++++++
test/test_basics.py | 24 ++++
test/test_client.py | 86 ++++++++++++
test/test_selenium.py | 90 ++++++++++++
test/test_user_model.py | 45 +++++-
tmp/coverage/app___init___py.html | 195 ++++++++++++++++++++++++++
tmp/coverage/app_api_1_0_authentication_py.html | 209 ++++++++++++++++++++++++++++
tmp/coverage/app_api_1_0_comments_py.html | 249 +++++++++++++++++++++++++++++++++
tmp/coverage/app_api_1_0_decorators_py.html | 133 ++++++++++++++++++
tmp/coverage/app_api_1_0_errors_py.html | 133 ++++++++++++++++++
tmp/coverage/app_api_1_0_posts_py.html | 239 ++++++++++++++++++++++++++++++++
tmp/coverage/app_api_1_0_users_py.html | 241 ++++++++++++++++++++++++++++++++
tmp/coverage/app_auth_forms_py.html | 221 +++++++++++++++++++++++++++++
tmp/coverage/app_auth_views_py.html | 483 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmp/coverage/app_email_py.html | 113 +++++++++++++++
tmp/coverage/app_main___init___py.html | 117 ++++++++++++++++
tmp/coverage/app_main_views_py.html | 823 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmp/coverage/app_models_py.html | 981 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmp/coverage/coverage_html.js | 512 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmp/coverage/index.html | 260 ++++++++++++++++++++++++++++++++++
tmp/coverage/jquery.debounce.min.js | 9 ++
tmp/coverage/jquery.hotkeys.js | 99 +++++++++++++
tmp/coverage/jquery.isonscreen.js | 53 +++++++
tmp/coverage/jquery.min.js | 4 +
tmp/coverage/jquery.tablesorter.min.js | 2 +
tmp/coverage/keybd_closed.png | Bin 0 -> 264 bytes
tmp/coverage/keybd_open.png | Bin 0 -> 267 bytes
tmp/coverage/status.json | 1 +
tmp/coverage/style.css | 326 +++++++++++++++++++++++++++++++++++++++++++
74 files changed, 7248 insertions(+), 112 deletions(-)
create mode 100644 Procfile
create mode 100644 app/api_1_0/__init__.py
create mode 100644 app/api_1_0/authentication.py
create mode 100644 app/api_1_0/comments.py
create mode 100644 app/api_1_0/decorators.py
create mode 100644 app/api_1_0/errors.py
create mode 100644 app/api_1_0/posts.py
create mode 100644 app/api_1_0/users.py
create mode 100644 app/auth/__init__.py
create mode 100644 app/auth/forms.py
create mode 100644 app/auth/views.py
create mode 100644 app/email.py
create mode 100644 app/exceptions.py
create mode 100644 app/main/__init__.py
create mode 100644 app/main/error.py
create mode 100644 app/main/forms.py
create mode 100644 app/main/views.py
rename app/templates/{ => auth/email}/confirm.html (75%)
create mode 100644 app/templates/auth/email/confirm.txt
rename app/templates/{ => auth/email}/confirmmail.html (74%)
rename app/templates/{ => auth/email}/confirmmail.txt (50%)
rename app/templates/{ => auth}/login.html (71%)
rename app/templates/{ => auth}/register.html (100%)
rename app/templates/{ => auth}/renew.html (100%)
rename app/templates/{ => auth}/unconfirmed.html (80%)
delete mode 100644 app/templates/confirm.txt
rename app/templates/{ => main}/index.html (81%)
create mode 100644 app/templates/main/moderate.html
create mode 100644 app_pro.db
create mode 100644 app_test.db
create mode 100644 requirements.txt
create mode 100644 test/test_api.py
create mode 100644 test/test_basics.py
create mode 100644 test/test_client.py
create mode 100644 test/test_selenium.py
create mode 100644 tmp/coverage/app___init___py.html
create mode 100644 tmp/coverage/app_api_1_0_authentication_py.html
create mode 100644 tmp/coverage/app_api_1_0_comments_py.html
create mode 100644 tmp/coverage/app_api_1_0_decorators_py.html
create mode 100644 tmp/coverage/app_api_1_0_errors_py.html
create mode 100644 tmp/coverage/app_api_1_0_posts_py.html
create mode 100644 tmp/coverage/app_api_1_0_users_py.html
create mode 100644 tmp/coverage/app_auth_forms_py.html
create mode 100644 tmp/coverage/app_auth_views_py.html
create mode 100644 tmp/coverage/app_email_py.html
create mode 100644 tmp/coverage/app_main___init___py.html
create mode 100644 tmp/coverage/app_main_views_py.html
create mode 100644 tmp/coverage/app_models_py.html
create mode 100644 tmp/coverage/coverage_html.js
create mode 100644 tmp/coverage/index.html
create mode 100644 tmp/coverage/jquery.debounce.min.js
create mode 100644 tmp/coverage/jquery.hotkeys.js
create mode 100644 tmp/coverage/jquery.isonscreen.js
create mode 100644 tmp/coverage/jquery.min.js
create mode 100644 tmp/coverage/jquery.tablesorter.min.js
create mode 100644 tmp/coverage/keybd_closed.png
create mode 100644 tmp/coverage/keybd_open.png
create mode 100644 tmp/coverage/status.json
create mode 100644 tmp/coverage/style.css
? flask_blog git:(master) git push heroku master
Counting objects: 491, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (482/482), done.
Writing objects: 100% (491/491), 232.17 KiB | 0 bytes/s, done.
Total 491 (delta 301), reused 2 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Using set buildpack heroku/python
remote: -----> Python app detected
remote: -----> Installing runtime (python-2.7.11)
remote: -----> Installing dependencies with pip
remote: Collecting alembic==0.8.4 (from -r requirements.txt (line 1))
remote: Downloading alembic-0.8.4.tar.gz (950kB)
remote: Collecting bleach==1.4.2 (from -r requirements.txt (line 2))
remote: Downloading bleach-1.4.2-py2.py3-none-any.whl
remote: Collecting blinker==1.4 (from -r requirements.txt (line 3))
remote: Downloading blinker-1.4.tar.gz (111kB)
remote: Collecting coverage==4.0.3 (from -r requirements.txt (line 4))
remote: Downloading coverage-4.0.3.tar.gz (354kB)
remote: Collecting decorator==4.0.6 (from -r requirements.txt (line 5))
remote: Downloading decorator-4.0.6-py2.py3-none-any.whl
remote: Collecting dominate==2.1.16 (from -r requirements.txt (line 6))
remote: Downloading dominate-2.1.16.zip
remote: Collecting Flask==0.10.1 (from -r requirements.txt (line 7))
remote: Downloading Flask-0.10.1.tar.gz (544kB)
remote: Collecting Flask-Bootstrap==3.3.5.7 (from -r requirements.txt (line 8))
remote: Downloading Flask-Bootstrap-3.3.5.7.tar.gz (451kB)
remote: Collecting Flask-HTTPAuth==2.7.0 (from -r requirements.txt (line 9))
remote: Downloading Flask-HTTPAuth-2.7.0.tar.gz
remote: Collecting Flask-Login==0.3.2 (from -r requirements.txt (line 10))
remote: Downloading Flask-Login-0.3.2.tar.gz
remote: Collecting Flask-Mail==0.9.1 (from -r requirements.txt (line 11))
remote: Downloading Flask-Mail-0.9.1.tar.gz (45kB)
remote: Collecting Flask-Markdown==0.3 (from -r requirements.txt (line 12))
remote: Downloading Flask-Markdown-0.3.tar.gz (165kB)
remote: Collecting Flask-Migrate==1.6.0 (from -r requirements.txt (line 13))
remote: Downloading Flask-Migrate-1.6.0.tar.gz
remote: Collecting Flask-Moment==0.5.1 (from -r requirements.txt (line 14))
remote: Downloading Flask-Moment-0.5.1.tar.gz
remote: Collecting Flask-PageDown==0.2.1 (from -r requirements.txt (line 15))
remote: Downloading Flask-PageDown-0.2.1.tar.gz
remote: Collecting Flask-Script==2.0.5 (from -r requirements.txt (line 16))
remote: Downloading Flask-Script-2.0.5.tar.gz (42kB)
remote: Collecting Flask-SQLAlchemy==2.1 (from -r requirements.txt (line 17))
remote: Downloading Flask-SQLAlchemy-2.1.tar.gz (95kB)
remote: Collecting Flask-SSLify==0.1.5 (from -r requirements.txt (line 18))
remote: Downloading Flask-SSLify-0.1.5.tar.gz
remote: Collecting Flask-WTF==0.12 (from -r requirements.txt (line 19))
remote: Downloading Flask_WTF-0.12-py2-none-any.whl
remote: Collecting ForgeryPy==0.1 (from -r requirements.txt (line 20))
remote: Downloading ForgeryPy-0.1.tar.gz
remote: Collecting gunicorn==19.4.5 (from -r requirements.txt (line 21))
remote: Downloading gunicorn-19.4.5-py2.py3-none-any.whl (112kB)
remote: Collecting html5lib==0.9999999 (from -r requirements.txt (line 22))
remote: Downloading html5lib-0.9999999.tar.gz (889kB)
remote: Collecting httpie==0.9.3 (from -r requirements.txt (line 23))
remote: Downloading httpie-0.9.3-py2.py3-none-any.whl (66kB)
remote: Collecting itsdangerous==0.24 (from -r requirements.txt (line 24))
remote: Downloading itsdangerous-0.24.tar.gz (46kB)
remote: Collecting Jinja2==2.8 (from -r requirements.txt (line 25))
remote: Downloading Jinja2-2.8-py2.py3-none-any.whl (263kB)
remote: Collecting Mako==1.0.3 (from -r requirements.txt (line 26))
remote: Downloading Mako-1.0.3.tar.gz (565kB)
remote: Collecting Markdown==2.6.5 (from -r requirements.txt (line 27))
remote: Downloading Markdown-2.6.5.tar.gz (301kB)
remote: Collecting MarkupSafe==0.23 (from -r requirements.txt (line 28))
remote: Downloading MarkupSafe-0.23.tar.gz
remote: Collecting pbr==1.8.1 (from -r requirements.txt (line 29))
remote: Downloading pbr-1.8.1-py2.py3-none-any.whl (89kB)
remote: Collecting psycopg2==2.6.1 (from -r requirements.txt (line 30))
remote: Downloading psycopg2-2.6.1.tar.gz (371kB)
remote: Collecting Pygments==2.0.2 (from -r requirements.txt (line 31))
remote: Downloading Pygments-2.0.2-py2-none-any.whl (672kB)
remote: Collecting python-editor==0.5 (from -r requirements.txt (line 32))
remote: Downloading python-editor-0.5.tar.gz
remote: Collecting requests==2.9.1 (from -r requirements.txt (line 33))
remote: Downloading requests-2.9.1-py2.py3-none-any.whl (501kB)
remote: Collecting selenium==2.48.0 (from -r requirements.txt (line 34))
remote: Downloading selenium-2.48.0-py2-none-any.whl (872kB)
remote: Collecting six==1.10.0 (from -r requirements.txt (line 35))
remote: Downloading six-1.10.0-py2.py3-none-any.whl
remote: Collecting SQLAlchemy==1.0.10 (from -r requirements.txt (line 36))
remote: Downloading SQLAlchemy-1.0.10.tar.gz (4.7MB)
remote: Collecting sqlalchemy-migrate==0.10.0 (from -r requirements.txt (line 37))
remote: Downloading sqlalchemy_migrate-0.10.0-py2-none-any.whl (108kB)
remote: Collecting sqlparse==0.1.18 (from -r requirements.txt (line 38))
remote: Downloading sqlparse-0.1.18.tar.gz (58kB)
remote: Collecting Tempita==0.5.2 (from -r requirements.txt (line 39))
remote: Downloading Tempita-0.5.2.tar.gz
remote: Collecting visitor==0.1.2 (from -r requirements.txt (line 40))
remote: Downloading visitor-0.1.2.tar.gz
remote: Collecting Werkzeug==0.11.2 (from -r requirements.txt (line 41))
remote: Downloading Werkzeug-0.11.2-py2.py3-none-any.whl (304kB)
remote: Collecting wheel==0.24.0 (from -r requirements.txt (line 42))
remote: Downloading wheel-0.24.0-py2.py3-none-any.whl (63kB)
remote: Collecting WTForms==2.0.2 (from -r requirements.txt (line 43))
remote: Downloading WTForms-2.0.2-py27-none-any.whl (128kB)
remote: Installing collected packages: SQLAlchemy, MarkupSafe, Mako, python-editor, alembic, six, html5lib, bleach, blinker, coverage, decorator, dominate, Werkzeug, Jinja2, itsdangerous, Flask, visitor, Flask-Bootstrap, Flask-HTTPAuth, Flask-Login, Flask-Mail, Markdown, Flask-Markdown, Flask-SQLAlchemy, Flask-Script, Flask-Migrate, Flask-Moment, WTForms, Flask-PageDown, Flask-SSLify, Flask-WTF, ForgeryPy, gunicorn, Pygments, requests, httpie, pbr, psycopg2, selenium, sqlparse, Tempita, sqlalchemy-migrate, wheel
remote: Running setup.py install for SQLAlchemy
remote: Running setup.py install for MarkupSafe
remote: Running setup.py install for Mako
remote: Running setup.py install for python-editor
remote: Running setup.py install for alembic
remote: Running setup.py install for html5lib
remote: Running setup.py install for blinker
remote: Running setup.py install for coverage
remote: Running setup.py install for dominate
remote: Running setup.py install for itsdangerous
remote: Running setup.py install for Flask
remote: Running setup.py install for visitor
remote: Running setup.py install for Flask-Bootstrap
remote: Running setup.py install for Flask-HTTPAuth
remote: Running setup.py install for Flask-Login
remote: Running setup.py install for Flask-Mail
remote: Running setup.py install for Markdown
remote: Running setup.py install for Flask-Markdown
remote: Running setup.py install for Flask-SQLAlchemy
remote: Running setup.py install for Flask-Script
remote: Running setup.py install for Flask-Migrate
remote: Running setup.py install for Flask-Moment
remote: Running setup.py install for Flask-PageDown
remote: Running setup.py install for Flask-SSLify
remote: Running setup.py install for ForgeryPy
remote: Running setup.py install for psycopg2
remote: Running setup.py install for sqlparse
remote: Running setup.py install for Tempita
remote: Successfully installed Flask-0.10.1 Flask-Bootstrap-3.3.5.7 Flask-HTTPAuth-2.7.0 Flask-Login-0.3.2 Flask-Mail-0.9.1 Flask-Markdown-0.3 Flask-Migrate-1.6.0 Flask-Moment-0.5.1 Flask-PageDown-0.2.1 Flask-SQLAlchemy-2.1 Flask-SSLify-0.1.5 Flask-Script-2.0.5 Flask-WTF-0.12 ForgeryPy-0.1 Jinja2-2.8 Mako-1.0.3 Markdown-2.6.5 MarkupSafe-0.23 Pygments-2.0.2 SQLAlchemy-1.0.10 Tempita-0.5.2 WTForms-2.0.2 Werkzeug-0.11.2 alembic-0.8.4 bleach-1.4.2 blinker-1.4 coverage-4.0.3 decorator-4.0.6 dominate-2.1.16 gunicorn-19.4.5 html5lib-0.9999999 httpie-0.9.3 itsdangerous-0.24 pbr-1.8.1 psycopg2-2.6.1 python-editor-0.5 requests-2.9.1 selenium-2.48.0 six-1.10.0 sqlalchemy-migrate-0.10.0 sqlparse-0.1.18 visitor-0.1.2 wheel-0.24.0
remote:
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing... done, 44.6MB
remote: -----> Launching...
remote: Released v7
remote: https://flask-blog-chaonet.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/flask-blog-chaonet.git
* [new branch] master -> master
成功,按照requirements.txt
安裝依賴的庫
建立運(yùn)行環(huán)境
,數(shù)據(jù)庫
? flask_blog git:(master) heroku run python run.py deploy
Running python run.py deploy on flask-blog-chaonet... up, run.6723
/app/.heroku/python/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.
warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.')
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> c1b387222189, empty message
INFO [alembic.runtime.migration] Running upgrade c1b387222189 -> c4a4f802bdf4, empty message
INFO [alembic.runtime.migration] Running upgrade c4a4f802bdf4 -> 83e0975c0db1, add role permission
INFO [alembic.runtime.migration] Running upgrade 83e0975c0db1 -> ee9c55ba9b22, add user profile
INFO [alembic.runtime.migration] Running upgrade ee9c55ba9b22 -> 431d275d6a70, add user.about_me
INFO [alembic.runtime.migration] Running upgrade 431d275d6a70 -> d6f4efe3ffe1, add User.avatar_hash
INFO [alembic.runtime.migration] Running upgrade d6f4efe3ffe1 -> ac6e9871c9a4, add Post ,relationship with User
INFO [alembic.runtime.migration] Running upgrade ac6e9871c9a4 -> 6f219f6bca6e, add Post.on_changed_body, body_html, db.event.listen
INFO [alembic.runtime.migration] Running upgrade 6f219f6bca6e -> 3aca4362a467, add Follow model, user.followers
ollowed
INFO [alembic.runtime.migration] Running upgrade 3aca4362a467 -> e3cfb10aeab6, add comment model
創(chuàng)建并配置好數(shù)據(jù)庫表之后就可以重啟程序了,直接使用下述命令即可:
$ heroku restart
Restarting dynos... done
至此,程序就完全部署好了,可通過 https://<appname>.hero-kuapp.com 訪問。
查看日志
不同類型的消息,會通過顏色區(qū)分顯示
? flask_blog git:(master) heroku logs
...
2016-01-10T09:04:16.778460+00:00 heroku[run.6723]: Awaiting client
2016-01-10T09:04:16.871340+00:00 heroku[run.6723]: Starting process with command `python run.py deploy`
2016-01-10T09:04:17.236929+00:00 heroku[run.6723]: State changed from starting to up
2016-01-10T09:04:20.574974+00:00 heroku[run.6723]: State changed from up to complete
2016-01-10T09:04:20.567984+00:00 heroku[run.6723]: Process exited with status 0
2016-01-10T09:14:49.296965+00:00 heroku[web.1]: State changed from up to starting
2016-01-10T09:14:53.791001+00:00 heroku[web.1]: Starting process with command `gunicorn run:app`
2016-01-10T09:14:54.840605+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2016-01-10T09:14:56.154205+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Starting gunicorn 19.4.5
2016-01-10T09:14:56.230606+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [10] [INFO] Booting worker with pid: 10
2016-01-10T09:14:56.154848+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Listening at: http://0.0.0.0:10268 (3)
2016-01-10T09:14:56.154974+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Using worker: sync
2016-01-10T09:14:56.160120+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [9] [INFO] Booting worker with pid: 9
2016-01-10T09:14:56.476881+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [10] [INFO] Worker exiting (pid: 10)
2016-01-10T09:14:56.547413+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Shutting down: Master
2016-01-10T09:14:56.475915+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [9] [INFO] Worker exiting (pid: 9)
2016-01-10T09:14:56.529060+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Handling signal: term
2016-01-10T09:14:56.954815+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.
2016-01-10T09:14:56.954818+00:00 app[web.1]: warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.')
2016-01-10T09:14:57.283202+00:00 app[web.1]: warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.')
2016-01-10T09:14:57.283198+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.
2016-01-10T09:14:57.480937+00:00 heroku[web.1]: State changed from starting to up
2016-01-10T09:14:57.513335+00:00 heroku[web.1]: Process exited with status 0
2016-01-10T09:15:06.569626+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=32f4cf3a-d766-441b-bbe1-0e7052a37209 fwd="107.161.27.197" dyno=web.1 connect=0ms service=291ms status=200 bytes=3417
2016-01-10T09:15:09.079151+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=flask-blog-chaonet.herokuapp.com request_id=4e065440-cb19-420a-834e-8e4d8e4c956c fwd="107.161.27.197" dyno=web.1 connect=1ms service=19ms status=404 bytes=655
2016-01-10T09:15:16.012079+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=ac1e63ac-0133-4cad-adac-66563437c70c fwd="107.161.27.197" dyno=web.1 connect=0ms service=506ms status=200 bytes=3504
2016-01-10T09:15:17.703574+00:00 heroku[router]: at=info method=GET path="/followed" host=flask-blog-chaonet.herokuapp.com request_id=0fc98138-ca6f-4873-8327-4a22f892d432 fwd="107.161.27.197" dyno=web.1 connect=1ms service=13ms status=302 bytes=875
2016-01-10T09:15:18.327896+00:00 heroku[router]: at=info method=GET path="/auth/login?next=%2Ffollowed" host=flask-blog-chaonet.herokuapp.com request_id=8d44ff19-c673-4e61-929e-d6ce89678b3a fwd="107.161.27.197" dyno=web.1 connect=0ms service=25ms status=200 bytes=4071
2016-01-10T09:15:19.085786+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=flask-blog-chaonet.herokuapp.com request_id=d327a6e7-f26b-4514-8813-c2af94dfd639 fwd="107.161.27.197" dyno=web.1 connect=0ms service=3ms status=404 bytes=655
2016-01-10T09:15:20.795897+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=de598303-d092-4647-8758-9e050d089f2e fwd="107.161.27.197" dyno=web.1 connect=2ms service=23ms status=200 bytes=3504
2016-01-10T09:15:22.840818+00:00 heroku[router]: at=info method=GET path="/auth/login" host=flask-blog-chaonet.herokuapp.com request_id=db4a579c-d80b-4205-963e-53d4f8aeb4a3 fwd="107.161.27.197" dyno=web.1 connect=2ms service=9ms status=200 bytes=4014
2016-01-10T09:15:25.834388+00:00 heroku[router]: at=info method=GET path="/auth/register" host=flask-blog-chaonet.herokuapp.com request_id=32a0d112-6dfa-4c8b-bd25-2bf0296add0d fwd="107.161.27.197" dyno=web.1 connect=2ms service=31ms status=200 bytes=4084
2016-01-10T09:15:28.548938+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=0f731062-0cfe-4e51-8967-13ab87ef03c5 fwd="107.161.27.197" dyno=web.1 connect=2ms service=15ms status=200 bytes=3504
應(yīng)用程序維護(hù)模式
維護(hù)時(shí)可以設(shè)置顯示維護(hù)信息
? flask_blog git:(master) heroku maintenance -h
Usage: heroku maintenance
display the current maintenance status of app
-a, --app APP # app to run command against
-r, --remote REMOTE # git remote of app to run command against
Additional commands, type "heroku help COMMAND" for more details:
maintenance:off # take the app out of maintenance mode
maintenance:on # put the app into maintenance mode
開啟顯示維護(hù)信息
? flask_blog git:(master) heroku maintenance:on
Enabling maintenance mode for flask-blog-chaonet... done
頁面顯示的內(nèi)容
Application Offline for Maintenance
This application is undergoing maintenance right now. Please check back later.
維護(hù)結(jié)束后,重新開啟應(yīng)用,正常訪問
? flask_blog git:(master) heroku maintenance:off
Disabling maintenance mode for flask-blog-chaonet... done