Flask 教程 第十八章:Heroku上的部署
本文轉(zhuǎn)載自:https://www.jianshu.com/p/d13dc21c6e43
這是Flask Mega-Tutorial系列的第十八部分,我將在其中部署Microblog到Heroku云平臺(tái)。
在前面的文章中,我向你展示了托管Python應(yīng)用程序的“傳統(tǒng)”方式,并且我演示了兩個(gè)部署到Linux的服務(wù)器的實(shí)際示例。 如果你不曾管理過(guò)Linux系統(tǒng),那么你可能認(rèn)為需要投入大量工作到這項(xiàng)任務(wù)中,而且肯定會(huì)有一個(gè)更簡(jiǎn)單的方法。
在本章中,我將向你展示一種完全不同的部署方法,該方法依賴第三方云托管提供程序來(lái)執(zhí)行大部分管理任務(wù),從而使你能夠騰出更多時(shí)間處理應(yīng)用程序。
許多云托管提供商提供了一個(gè)應(yīng)用程序可以運(yùn)行的托管平臺(tái)。 你只需提供部署到這些平臺(tái)上的實(shí)際應(yīng)用程序,因?yàn)橛布?#xff0c;操作系統(tǒng),腳本語(yǔ)言解釋器,數(shù)據(jù)庫(kù)等都由該服務(wù)管理。 這種服務(wù)稱為平臺(tái)即服務(wù)(PaaS)。
是不是感到難以置信?
我將把Microblog部署到Heroku,這是一種流行的云托管服務(wù),對(duì)Python應(yīng)用程序也非常友好。 我選擇Heroku不僅僅是因?yàn)樗浅J軞g迎,還因?yàn)樗幸粋€(gè)免費(fèi)的服務(wù)級(jí)別,可以讓你跟隨我并在不花錢的情況下完成部署。
本章的GitHub鏈接為:Browse,?Zip,?Diff.
托管于Heroku
Heroku是首批PaaS平臺(tái)之一。 它以Ruby的應(yīng)用程序的托管服務(wù)開(kāi)始,隨后逐漸發(fā)展到支持諸多其他語(yǔ)言,如Java,Node.js和Python。
在Heroku中部署Web應(yīng)用程序主要是通過(guò)git版本控制工具完成的,因此你必須將應(yīng)用程序放在git代碼庫(kù)中。 Heroku在應(yīng)用程序的根目錄中查找名為Procfile的文件,以獲取有關(guān)如何啟動(dòng)應(yīng)用程序的描述。 對(duì)于Python項(xiàng)目,Heroku還期望requirements.txt文件列出需要安裝的所有模塊依賴項(xiàng)。 在通過(guò)git將應(yīng)用程序上傳到Heroku的服務(wù)器之后,你的工作基本就完成了,只需等待幾秒鐘,應(yīng)用程序就會(huì)上線。 整個(gè)操作流程就是這么簡(jiǎn)單。
Heroku提供不同的服務(wù)級(jí)別,允許你自主選擇為應(yīng)用程序提供多少計(jì)算能力和運(yùn)行時(shí)間,隨著用戶群的增長(zhǎng),你需要購(gòu)買更多的“dynos”計(jì)算單元。
準(zhǔn)備好了嗎?讓我們開(kāi)始吧!
創(chuàng)建Heroku賬戶
在部署應(yīng)用到Heroku之前,你需要擁有一個(gè)帳戶。 所以請(qǐng)?jiān)L問(wèn)heroku.com并創(chuàng)建一個(gè)免費(fèi)賬戶。 一旦注冊(cè)成功并登錄到Heroku,你將可以訪問(wèn)一個(gè)dashboard,其中列出了你的所有應(yīng)用程序。
安裝Heroku命令行客戶端
Heroku提供了一個(gè)名為Heroku CLI的命令行工具來(lái)與服務(wù)交互,可安裝于Windows,Mac OS X和Linux。 該文檔包括了支持的所有平臺(tái)的安裝說(shuō)明。 如果你計(jì)劃部署應(yīng)用程序以測(cè)試該服務(wù),請(qǐng)將其安裝在你的系統(tǒng)上。
安裝CLI后應(yīng)該做的第一件事是登錄到你的Heroku帳戶:
$ heroku loginHeroku CLI會(huì)要求你輸入電子郵件地址和帳戶密碼。 你的身份驗(yàn)證狀態(tài)將在隨后的命令中被記住。
設(shè)置Git
git工具是Heroku應(yīng)用程序部署的核心,因此如果你還沒(méi)有安裝它的話,則必須將它安裝到你的系統(tǒng)上。 如果你沒(méi)有可用于你的操作系統(tǒng)的安裝包,可以訪問(wèn)git site下載安裝程序。
使用git的原因很多并且都理由充分。 如果你打算部署應(yīng)用到Heroku,那么這些原因就要又增加一個(gè),因?yàn)橐渴饝?yīng)用到Heroku,你的應(yīng)用程序必須在git代碼庫(kù)中。 如果你要為Microblog執(zhí)行測(cè)試部署,可以從GitHub克隆應(yīng)用程序:
$ git clone https://github.com/miguelgrinberg/microblog $ cd microblog $ git checkout v0.18git checkout命令將代碼庫(kù)切換到指定的歷史提交點(diǎn),也就是本章所處的位置。
如果更喜歡使用你自己的代碼,你可以通過(guò)在頂層目錄中運(yùn)行g(shù)it init .來(lái)將你自己的項(xiàng)目轉(zhuǎn)換成git代碼庫(kù)(注意init后面的句號(hào),它告訴git你想要在當(dāng)前目錄中初始化代碼庫(kù))。
創(chuàng)建Heroku應(yīng)用
要用Heroku注冊(cè)一個(gè)新應(yīng)用,需要在應(yīng)用程序根目錄下使用apps:create子命令,并將應(yīng)用程序名稱作為唯一參數(shù)傳遞:
$ heroku apps:create flask-microblog Creating flask-microblog... done http://flask-microblog.herokuapp.com/ | https://git.heroku.com/flask-microblog.gitHeroku要求應(yīng)用程序的名稱具有唯一性。 我上面已使用了flask-microblog這個(gè)名稱,所以你需要為你的部署選擇一個(gè)不同的名稱。
該命令的輸出將包含Heroku分配給應(yīng)用程序的URL以及git代碼庫(kù)。 你的本地git代碼庫(kù)將配置一個(gè)額外的remote,稱為heroku。 你可以用git remote命令驗(yàn)證它是否存在:
$ git remote -v heroku https://git.heroku.com/flask-microblog.git (fetch) heroku https://git.heroku.com/flask-microblog.git (push)根據(jù)你創(chuàng)建git代碼庫(kù)的方式,上述命令的輸出還可能包含另一個(gè)名為origin的遠(yuǎn)程倉(cāng)庫(kù)地址。
臨時(shí)文件系統(tǒng)
Heroku平臺(tái)與其他部署平臺(tái)不同之處在于它在虛擬化平臺(tái)上運(yùn)行的文件系統(tǒng)是臨時(shí)的。 那是什么意思? 這意味著Heroku可以隨時(shí)將運(yùn)行你的應(yīng)用的虛擬服務(wù)器重置為干凈狀態(tài)。 你不該天真地認(rèn)為你保存到文件系統(tǒng)的任何數(shù)據(jù)都會(huì)被持久存儲(chǔ),事實(shí)上,Heroku經(jīng)?;厥辗?wù)器。
在這種條件下工作會(huì)為我的應(yīng)用程序帶來(lái)一些問(wèn)題,因?yàn)樗褂昧巳缦碌膸讉€(gè)文件:
- 默認(rèn)的SQLite數(shù)據(jù)庫(kù)引擎將數(shù)據(jù)寫(xiě)入磁盤文件中
- 應(yīng)用程序的日志也寫(xiě)入磁盤文件中
- 編譯的語(yǔ)言翻譯存儲(chǔ)庫(kù)同樣是本地文件
以下部分將針對(duì)這三個(gè)方面提出解決方案。
使用Heroku Postgres數(shù)據(jù)庫(kù)
為了解決第一個(gè)問(wèn)題,我將切換到不同的數(shù)據(jù)庫(kù)引擎。 在第十七章中,你看到我使用MySQL數(shù)據(jù)庫(kù)為Ubuntu部署添加健壯性。 Heroku基于Postgres數(shù)據(jù)庫(kù)提供了自己的數(shù)據(jù)庫(kù)產(chǎn)品,因此我將轉(zhuǎn)而使用它來(lái)避免使用基于文件的SQLite。
Heroku應(yīng)用的數(shù)據(jù)庫(kù)使用相同的Heroku CLI進(jìn)行設(shè)置。 在本章中,我將創(chuàng)建一個(gè)免費(fèi)級(jí)別的數(shù)據(jù)庫(kù):
$ heroku addons:add heroku-postgresql:hobby-dev Creating heroku-postgresql:hobby-dev on flask-microblog... free Database has been created and is available! This database is empty. If upgrading, you can transfer! data from another database with pg:copy Created postgresql-parallel-56076 as DATABASE_URL Use heroku addons:docs heroku-postgresql to view documentation新創(chuàng)建的數(shù)據(jù)庫(kù)的URL存儲(chǔ)在DATABASE_URL環(huán)境變量中,該變量在應(yīng)用程序運(yùn)行時(shí)將可用。 這就非常方便了,因?yàn)閼?yīng)用程序已經(jīng)設(shè)定為在該變量中查找數(shù)據(jù)庫(kù)URL。
輸出日志到標(biāo)準(zhǔn)輸出
Heroku希望應(yīng)用程序直接輸出日志到stdout。 當(dāng)你使用heroku logs命令時(shí),應(yīng)用程序打印到標(biāo)準(zhǔn)輸出的任何內(nèi)容都將被保存并返回。 所以我要添加一個(gè)配置變量,指示我是要輸出日志到stdout,還是像我之前那樣輸出到文件。 這是配置的變化:
config.py:輸出日志到標(biāo)準(zhǔn)輸出的選項(xiàng)。
class Config(object):# ...LOG_TO_STDOUT = os.environ.get('LOG_TO_STDOUT')然后在應(yīng)用工廠函數(shù)中,我會(huì)檢查此配置以了解應(yīng)該如何配置應(yīng)用程序的日志記錄器:
app/__init__.py:輸出日志到標(biāo)準(zhǔn)輸出或文件。
def create_app(config_class=Config):# ...if not app.debug and not app.testing:# ...if app.config['LOG_TO_STDOUT']:stream_handler = logging.StreamHandler()stream_handler.setLevel(logging.INFO)app.logger.addHandler(stream_handler)else:if not os.path.exists('logs'):os.mkdir('logs')file_handler = RotatingFileHandler('logs/microblog.log',maxBytes=10240, backupCount=10)file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s ''[in %(pathname)s:%(lineno)d]'))file_handler.setLevel(logging.INFO)app.logger.addHandler(file_handler)app.logger.setLevel(logging.INFO)app.logger.info('Microblog startup')return app所以現(xiàn)在我需要在Heroku中運(yùn)行應(yīng)用程序時(shí)設(shè)置LOG_TO_STDOUT環(huán)境變量,但在其他配置中則不需要。 Heroku CLI使得做到這一點(diǎn)變得簡(jiǎn)單,因?yàn)樗峁┝艘粋€(gè)選項(xiàng)來(lái)設(shè)置運(yùn)行時(shí)使用的環(huán)境變量:
$ heroku config:set LOG_TO_STDOUT=1 Setting LOG_TO_STDOUT and restarting flask-microblog... done, v4 LOG_TO_STDOUT: 1編譯翻譯
Microblog依賴本地文件的第三個(gè)方面是編譯后的語(yǔ)言翻譯文件。 確保這些文件永遠(yuǎn)不會(huì)從臨時(shí)文件系統(tǒng)中消失的粗暴做法是將編譯后的語(yǔ)言文件添加到git代碼庫(kù),以便在部署到Heroku后它們成為應(yīng)用程序初始狀態(tài)的一部分。
在我看來(lái),更優(yōu)雅的選擇是在Heroku的啟動(dòng)命令中包含flask translate compile命令,以便在服務(wù)器重新啟動(dòng)時(shí)再次編譯這些文件。 我打算選擇這個(gè)方案,因?yàn)槲抑绬?dòng)過(guò)程需要多個(gè)命令,至少我還需要運(yùn)行數(shù)據(jù)庫(kù)遷移。 所以現(xiàn)在,我將把這個(gè)問(wèn)題放在一邊,稍后當(dāng)我寫(xiě)Procfile的時(shí)候會(huì)重新討論它。
托管Elasticsearch
Elasticsearch是可以添加到Heroku項(xiàng)目中的眾多服務(wù)之一,但與Postgres不同的是,這不是由Heroku提供的服務(wù),而是由與Heroku合作提供附加組件的第三方提供的。 在我寫(xiě)這篇文章的時(shí)候,有三個(gè)不同的集成Elasticsearch服務(wù)提供商。
在配置Elasticsearch之前,請(qǐng)注意,Heroku要求你的帳戶在安裝任何第三方附加組件之前添加信用卡信息,即使你仍處于在免費(fèi)級(jí)別中。 如果你不想將信用卡信息提供給Heroku,請(qǐng)?zhí)^(guò)此部分。 你仍然可以部署應(yīng)用程序,但搜索功能不起作用。
在可作為附加組件提供的Elasticsearch選項(xiàng)中,我決定嘗試SearchBox,它附帶一個(gè)免費(fèi)的初試計(jì)劃。 要將SearchBox添加到你的帳戶,你必須在登錄到Heroku后運(yùn)行以下命令:
$ heroku addons:create searchbox:starter該命令將部署一個(gè)Elasticsearch服務(wù),并將該服務(wù)的連接URL保存在與你的應(yīng)用程序關(guān)聯(lián)的SEARCHBOX_URL環(huán)境變量中。 請(qǐng)記住,除非將你的信用卡信息添加到你的Heroku帳戶中,否則此命令將失敗。
回憶一下第十六章,我的應(yīng)用程序在Elasticsearch連接URL中查找的是ELASTICSEARCH_URL變量,所以我需要添加這個(gè)變量并將其設(shè)置為由SearchBox分配的連接URL:
$ heroku config:get SEARCHBOX_URL <your-elasticsearch-url> $ heroku config:set ELASTICSEARCH_URL=<your-elasticsearch-url>在這里,我首先要求Heroku打印SEARCHBOX_URL的值,然后將其添加到一個(gè)名為ELASTICSEARCH_URL的新環(huán)境變量中。
更新依賴
Heroku期望依賴關(guān)系在requirements.txt文件中,就像我在第十五章中定義的那樣。 但是為了在Heroku上運(yùn)行應(yīng)用程序,我需要為這個(gè)文件添加兩個(gè)新的依賴關(guān)系。
Heroku不提供自己的Web服務(wù)器。 相反,它希望應(yīng)用程序根據(jù)環(huán)境變量$PORT中給出的端口號(hào)啟動(dòng)自己的Web服務(wù)器。 由于Flask開(kāi)發(fā)Web服務(wù)器不足以用于生產(chǎn),因此我將再次使用gunicorn,這是Heroku為Python應(yīng)用程序推薦的服務(wù)器。
該應(yīng)用程序還將連接到Postgres數(shù)據(jù)庫(kù),為此SQLAlchemy依賴psycopg2軟件包的安裝。
gunicorn?和psycopg2?都需要添加到requirements.txt文件中。
Procfile
Heroku需要知道如何執(zhí)行應(yīng)用程序,并且它會(huì)在應(yīng)用程序的根目錄中使用名為Procfile的文件。 這個(gè)文件的格式很簡(jiǎn)單,每行包含一個(gè)進(jìn)程名稱,一個(gè)冒號(hào),然后是啟動(dòng)進(jìn)程的命令。 在Heroku上運(yùn)行的最常見(jiàn)的應(yīng)用程序類型是一個(gè)Web應(yīng)用程序,對(duì)于這種類型的應(yīng)用程序,進(jìn)程名稱應(yīng)該是web。 下面你可以看到Microblog的Procfile:
Procfile:Heroku Procfile。
web: flask db upgrade; flask translate compile; gunicorn microblog:app在這里,我定義的啟動(dòng)命令中將按順序執(zhí)行三個(gè)命令作以啟動(dòng)Web應(yīng)用程序。 首先,我運(yùn)行數(shù)據(jù)庫(kù)遷移升級(jí),然后編譯語(yǔ)言翻譯,最后啟動(dòng)服務(wù)器。
因?yàn)榍皟蓚€(gè)子命令是基于flask命令的,所以我需要添加FLASK_APP環(huán)境變量:
$ heroku config:set FLASK_APP=microblog.py Setting FLASK_APP and restarting flask-microblog... done, v4 FLASK_APP: microblog.pygunicorn命令比我用于Ubuntu部署的還要簡(jiǎn)單,因?yàn)檫@個(gè)服務(wù)與Heroku環(huán)境有很好的集成。 例如,$PORT環(huán)境變量默認(rèn)會(huì)被設(shè)置,取代使用-w選項(xiàng)來(lái)設(shè)置worker的數(shù)量,heroku推薦添加一個(gè)名為WEB_CONCURRENCY的環(huán)境變量,在-w參數(shù)沒(méi)有提供的時(shí)候,就會(huì)使用這個(gè)環(huán)境變量,因此你可以靈活地控制worker的數(shù)量而無(wú)需修改Procfile。
部署應(yīng)用
所有準(zhǔn)備步驟都已完成,所以現(xiàn)在是時(shí)候執(zhí)行部署了。 要將應(yīng)用程序上傳到Heroku的服務(wù)器進(jìn)行部署,需要使用git push命令。 這與你將本地git代碼庫(kù)中的更改推送到GitHub或其他遠(yuǎn)程git服務(wù)器的方式類似。
現(xiàn)在我已經(jīng)達(dá)到了最有趣的部分,就是將應(yīng)用程序推送到我們的Heroku托管帳戶。 這其實(shí)很簡(jiǎn)單,我只需要使用git將應(yīng)用程序推送到Heroku git代碼庫(kù)的主分支就行了。 關(guān)于如何做到這一點(diǎn)有幾種方法,取決于你是如何創(chuàng)建你的git代碼庫(kù)的。 如果你使用我的v0.18代碼,那么你需要基于此標(biāo)記創(chuàng)建一個(gè)分支,并將其作為遠(yuǎn)程主分支推送,如下所示:
$ git checkout -b deploy $ git push heroku deploy:master相反,如果你正在使用自己的代碼庫(kù),那么你的代碼已經(jīng)在master分支中,所以你首先需要確保你的更改已經(jīng)提交:
$ git commit -a -m "heroku deployment changes"然后運(yùn)行如下命令啟動(dòng)部署:
$ git push heroku master無(wú)論你如何推送分支,都應(yīng)該看到Heroku的以下輸出:
$ git push heroku deploy:master Counting objects: 247, done. Delta compression using up to 8 threads. Compressing objects: 100% (238/238), done. Writing objects: 100% (247/247), 53.26 KiB | 3.80 MiB/s, done. Total 247 (delta 136), reused 3 (delta 0) remote: Compressing source files... done. remote: Building source: remote: remote: -----> Python app detected remote: -----> Installing python-3.6.2 remote: -----> Installing pip remote: -----> Installing requirements with pip ... remote: remote: -----> Discovering process types remote: Procfile declares types -> web remote: remote: -----> Compressing... remote: Done: 57M remote: -----> Launching... remote: Released v5 remote: https://flask-microblog.herokuapp.com/ deployed to Heroku remote: remote: Verifying deploy... done. To https://git.heroku.com/flask-microblog.git* [new branch] deploy -> master我們?cè)趃it push命令中使用的標(biāo)簽heroku是在創(chuàng)建應(yīng)用程序時(shí)由Heroku CLI自動(dòng)添加的遠(yuǎn)程代碼庫(kù)。?deploy:master參數(shù)意味著我將代碼從本地代碼庫(kù)的deploy分支推送到Heroku代碼庫(kù)上的master分支。 當(dāng)你使用自己的項(xiàng)目時(shí),你可能會(huì)用git push heroku master命令推動(dòng)你的本地master分支。 由于這個(gè)項(xiàng)目的代碼庫(kù)分支結(jié)構(gòu),我推送了一個(gè)非master的分支,但Heroku側(cè)要求的目標(biāo)分支是’master’,因?yàn)檫@是Heroku唯一接受部署的分支。
就這樣,應(yīng)用程序現(xiàn)在應(yīng)該已經(jīng)部署在創(chuàng)建應(yīng)用程序的命令的輸出中給出的URL上了。 在我的案例中,URL是https://flask-microblog.herokuapp.com,所以這就是我需要鍵入和訪問(wèn)該應(yīng)用程序的URL。
如果你想查看正在運(yùn)行的應(yīng)用程序的日志,請(qǐng)使用heroku logs命令。 如果由于任何原因?qū)е聭?yīng)用程序無(wú)法啟動(dòng),該命令可能很有用。 如果有任何錯(cuò)誤,將在日志中顯示。
部署應(yīng)用更新
要部署新版本的應(yīng)用程序,只需要使用git push命令將新的代碼庫(kù)推送到Heroku即可。 這將重復(fù)部署過(guò)程,關(guān)停舊部署,然后用新代碼替換它。 Procfile中的命令將作為新部署的一部分再次運(yùn)行,因此在此過(guò)程中將更新任何新的數(shù)據(jù)庫(kù)遷移或翻譯內(nèi)容。
總結(jié)
以上是生活随笔為你收集整理的Flask 教程 第十八章:Heroku上的部署的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎么把视频里的音乐提取出来
- 下一篇: git 命令行使用(基础篇)