Flask 教程 第十八章:Heroku上的部署
本文轉載自:https://www.jianshu.com/p/d13dc21c6e43
這是Flask Mega-Tutorial系列的第十八部分,我將在其中部署Microblog到Heroku云平臺。
在前面的文章中,我向你展示了托管Python應用程序的“傳統”方式,并且我演示了兩個部署到Linux的服務器的實際示例。 如果你不曾管理過Linux系統,那么你可能認為需要投入大量工作到這項任務中,而且肯定會有一個更簡單的方法。
在本章中,我將向你展示一種完全不同的部署方法,該方法依賴第三方云托管提供程序來執行大部分管理任務,從而使你能夠騰出更多時間處理應用程序。
許多云托管提供商提供了一個應用程序可以運行的托管平臺。 你只需提供部署到這些平臺上的實際應用程序,因為硬件,操作系統,腳本語言解釋器,數據庫等都由該服務管理。 這種服務稱為平臺即服務(PaaS)。
是不是感到難以置信?
我將把Microblog部署到Heroku,這是一種流行的云托管服務,對Python應用程序也非常友好。 我選擇Heroku不僅僅是因為它非常受歡迎,還因為它有一個免費的服務級別,可以讓你跟隨我并在不花錢的情況下完成部署。
本章的GitHub鏈接為:Browse,?Zip,?Diff.
托管于Heroku
Heroku是首批PaaS平臺之一。 它以Ruby的應用程序的托管服務開始,隨后逐漸發展到支持諸多其他語言,如Java,Node.js和Python。
在Heroku中部署Web應用程序主要是通過git版本控制工具完成的,因此你必須將應用程序放在git代碼庫中。 Heroku在應用程序的根目錄中查找名為Procfile的文件,以獲取有關如何啟動應用程序的描述。 對于Python項目,Heroku還期望requirements.txt文件列出需要安裝的所有模塊依賴項。 在通過git將應用程序上傳到Heroku的服務器之后,你的工作基本就完成了,只需等待幾秒鐘,應用程序就會上線。 整個操作流程就是這么簡單。
Heroku提供不同的服務級別,允許你自主選擇為應用程序提供多少計算能力和運行時間,隨著用戶群的增長,你需要購買更多的“dynos”計算單元。
準備好了嗎?讓我們開始吧!
創建Heroku賬戶
在部署應用到Heroku之前,你需要擁有一個帳戶。 所以請訪問heroku.com并創建一個免費賬戶。 一旦注冊成功并登錄到Heroku,你將可以訪問一個dashboard,其中列出了你的所有應用程序。
安裝Heroku命令行客戶端
Heroku提供了一個名為Heroku CLI的命令行工具來與服務交互,可安裝于Windows,Mac OS X和Linux。 該文檔包括了支持的所有平臺的安裝說明。 如果你計劃部署應用程序以測試該服務,請將其安裝在你的系統上。
安裝CLI后應該做的第一件事是登錄到你的Heroku帳戶:
$ heroku loginHeroku CLI會要求你輸入電子郵件地址和帳戶密碼。 你的身份驗證狀態將在隨后的命令中被記住。
設置Git
git工具是Heroku應用程序部署的核心,因此如果你還沒有安裝它的話,則必須將它安裝到你的系統上。 如果你沒有可用于你的操作系統的安裝包,可以訪問git site下載安裝程序。
使用git的原因很多并且都理由充分。 如果你打算部署應用到Heroku,那么這些原因就要又增加一個,因為要部署應用到Heroku,你的應用程序必須在git代碼庫中。 如果你要為Microblog執行測試部署,可以從GitHub克隆應用程序:
$ git clone https://github.com/miguelgrinberg/microblog $ cd microblog $ git checkout v0.18git checkout命令將代碼庫切換到指定的歷史提交點,也就是本章所處的位置。
如果更喜歡使用你自己的代碼,你可以通過在頂層目錄中運行git init .來將你自己的項目轉換成git代碼庫(注意init后面的句號,它告訴git你想要在當前目錄中初始化代碼庫)。
創建Heroku應用
要用Heroku注冊一個新應用,需要在應用程序根目錄下使用apps:create子命令,并將應用程序名稱作為唯一參數傳遞:
$ heroku apps:create flask-microblog Creating flask-microblog... done http://flask-microblog.herokuapp.com/ | https://git.heroku.com/flask-microblog.gitHeroku要求應用程序的名稱具有唯一性。 我上面已使用了flask-microblog這個名稱,所以你需要為你的部署選擇一個不同的名稱。
該命令的輸出將包含Heroku分配給應用程序的URL以及git代碼庫。 你的本地git代碼庫將配置一個額外的remote,稱為heroku。 你可以用git remote命令驗證它是否存在:
$ git remote -v heroku https://git.heroku.com/flask-microblog.git (fetch) heroku https://git.heroku.com/flask-microblog.git (push)根據你創建git代碼庫的方式,上述命令的輸出還可能包含另一個名為origin的遠程倉庫地址。
臨時文件系統
Heroku平臺與其他部署平臺不同之處在于它在虛擬化平臺上運行的文件系統是臨時的。 那是什么意思? 這意味著Heroku可以隨時將運行你的應用的虛擬服務器重置為干凈狀態。 你不該天真地認為你保存到文件系統的任何數據都會被持久存儲,事實上,Heroku經常回收服務器。
在這種條件下工作會為我的應用程序帶來一些問題,因為它使用了如下的幾個文件:
- 默認的SQLite數據庫引擎將數據寫入磁盤文件中
- 應用程序的日志也寫入磁盤文件中
- 編譯的語言翻譯存儲庫同樣是本地文件
以下部分將針對這三個方面提出解決方案。
使用Heroku Postgres數據庫
為了解決第一個問題,我將切換到不同的數據庫引擎。 在第十七章中,你看到我使用MySQL數據庫為Ubuntu部署添加健壯性。 Heroku基于Postgres數據庫提供了自己的數據庫產品,因此我將轉而使用它來避免使用基于文件的SQLite。
Heroku應用的數據庫使用相同的Heroku CLI進行設置。 在本章中,我將創建一個免費級別的數據庫:
$ 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新創建的數據庫的URL存儲在DATABASE_URL環境變量中,該變量在應用程序運行時將可用。 這就非常方便了,因為應用程序已經設定為在該變量中查找數據庫URL。
輸出日志到標準輸出
Heroku希望應用程序直接輸出日志到stdout。 當你使用heroku logs命令時,應用程序打印到標準輸出的任何內容都將被保存并返回。 所以我要添加一個配置變量,指示我是要輸出日志到stdout,還是像我之前那樣輸出到文件。 這是配置的變化:
config.py:輸出日志到標準輸出的選項。
class Config(object):# ...LOG_TO_STDOUT = os.environ.get('LOG_TO_STDOUT')然后在應用工廠函數中,我會檢查此配置以了解應該如何配置應用程序的日志記錄器:
app/__init__.py:輸出日志到標準輸出或文件。
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所以現在我需要在Heroku中運行應用程序時設置LOG_TO_STDOUT環境變量,但在其他配置中則不需要。 Heroku CLI使得做到這一點變得簡單,因為它提供了一個選項來設置運行時使用的環境變量:
$ heroku config:set LOG_TO_STDOUT=1 Setting LOG_TO_STDOUT and restarting flask-microblog... done, v4 LOG_TO_STDOUT: 1編譯翻譯
Microblog依賴本地文件的第三個方面是編譯后的語言翻譯文件。 確保這些文件永遠不會從臨時文件系統中消失的粗暴做法是將編譯后的語言文件添加到git代碼庫,以便在部署到Heroku后它們成為應用程序初始狀態的一部分。
在我看來,更優雅的選擇是在Heroku的啟動命令中包含flask translate compile命令,以便在服務器重新啟動時再次編譯這些文件。 我打算選擇這個方案,因為我知道啟動過程需要多個命令,至少我還需要運行數據庫遷移。 所以現在,我將把這個問題放在一邊,稍后當我寫Procfile的時候會重新討論它。
托管Elasticsearch
Elasticsearch是可以添加到Heroku項目中的眾多服務之一,但與Postgres不同的是,這不是由Heroku提供的服務,而是由與Heroku合作提供附加組件的第三方提供的。 在我寫這篇文章的時候,有三個不同的集成Elasticsearch服務提供商。
在配置Elasticsearch之前,請注意,Heroku要求你的帳戶在安裝任何第三方附加組件之前添加信用卡信息,即使你仍處于在免費級別中。 如果你不想將信用卡信息提供給Heroku,請跳過此部分。 你仍然可以部署應用程序,但搜索功能不起作用。
在可作為附加組件提供的Elasticsearch選項中,我決定嘗試SearchBox,它附帶一個免費的初試計劃。 要將SearchBox添加到你的帳戶,你必須在登錄到Heroku后運行以下命令:
$ heroku addons:create searchbox:starter該命令將部署一個Elasticsearch服務,并將該服務的連接URL保存在與你的應用程序關聯的SEARCHBOX_URL環境變量中。 請記住,除非將你的信用卡信息添加到你的Heroku帳戶中,否則此命令將失敗。
回憶一下第十六章,我的應用程序在Elasticsearch連接URL中查找的是ELASTICSEARCH_URL變量,所以我需要添加這個變量并將其設置為由SearchBox分配的連接URL:
$ heroku config:get SEARCHBOX_URL <your-elasticsearch-url> $ heroku config:set ELASTICSEARCH_URL=<your-elasticsearch-url>在這里,我首先要求Heroku打印SEARCHBOX_URL的值,然后將其添加到一個名為ELASTICSEARCH_URL的新環境變量中。
更新依賴
Heroku期望依賴關系在requirements.txt文件中,就像我在第十五章中定義的那樣。 但是為了在Heroku上運行應用程序,我需要為這個文件添加兩個新的依賴關系。
Heroku不提供自己的Web服務器。 相反,它希望應用程序根據環境變量$PORT中給出的端口號啟動自己的Web服務器。 由于Flask開發Web服務器不足以用于生產,因此我將再次使用gunicorn,這是Heroku為Python應用程序推薦的服務器。
該應用程序還將連接到Postgres數據庫,為此SQLAlchemy依賴psycopg2軟件包的安裝。
gunicorn?和psycopg2?都需要添加到requirements.txt文件中。
Procfile
Heroku需要知道如何執行應用程序,并且它會在應用程序的根目錄中使用名為Procfile的文件。 這個文件的格式很簡單,每行包含一個進程名稱,一個冒號,然后是啟動進程的命令。 在Heroku上運行的最常見的應用程序類型是一個Web應用程序,對于這種類型的應用程序,進程名稱應該是web。 下面你可以看到Microblog的Procfile:
Procfile:Heroku Procfile。
web: flask db upgrade; flask translate compile; gunicorn microblog:app在這里,我定義的啟動命令中將按順序執行三個命令作以啟動Web應用程序。 首先,我運行數據庫遷移升級,然后編譯語言翻譯,最后啟動服務器。
因為前兩個子命令是基于flask命令的,所以我需要添加FLASK_APP環境變量:
$ heroku config:set FLASK_APP=microblog.py Setting FLASK_APP and restarting flask-microblog... done, v4 FLASK_APP: microblog.pygunicorn命令比我用于Ubuntu部署的還要簡單,因為這個服務與Heroku環境有很好的集成。 例如,$PORT環境變量默認會被設置,取代使用-w選項來設置worker的數量,heroku推薦添加一個名為WEB_CONCURRENCY的環境變量,在-w參數沒有提供的時候,就會使用這個環境變量,因此你可以靈活地控制worker的數量而無需修改Procfile。
部署應用
所有準備步驟都已完成,所以現在是時候執行部署了。 要將應用程序上傳到Heroku的服務器進行部署,需要使用git push命令。 這與你將本地git代碼庫中的更改推送到GitHub或其他遠程git服務器的方式類似。
現在我已經達到了最有趣的部分,就是將應用程序推送到我們的Heroku托管帳戶。 這其實很簡單,我只需要使用git將應用程序推送到Heroku git代碼庫的主分支就行了。 關于如何做到這一點有幾種方法,取決于你是如何創建你的git代碼庫的。 如果你使用我的v0.18代碼,那么你需要基于此標記創建一個分支,并將其作為遠程主分支推送,如下所示:
$ git checkout -b deploy $ git push heroku deploy:master相反,如果你正在使用自己的代碼庫,那么你的代碼已經在master分支中,所以你首先需要確保你的更改已經提交:
$ git commit -a -m "heroku deployment changes"然后運行如下命令啟動部署:
$ git push heroku master無論你如何推送分支,都應該看到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我們在git push命令中使用的標簽heroku是在創建應用程序時由Heroku CLI自動添加的遠程代碼庫。?deploy:master參數意味著我將代碼從本地代碼庫的deploy分支推送到Heroku代碼庫上的master分支。 當你使用自己的項目時,你可能會用git push heroku master命令推動你的本地master分支。 由于這個項目的代碼庫分支結構,我推送了一個非master的分支,但Heroku側要求的目標分支是’master’,因為這是Heroku唯一接受部署的分支。
就這樣,應用程序現在應該已經部署在創建應用程序的命令的輸出中給出的URL上了。 在我的案例中,URL是https://flask-microblog.herokuapp.com,所以這就是我需要鍵入和訪問該應用程序的URL。
如果你想查看正在運行的應用程序的日志,請使用heroku logs命令。 如果由于任何原因導致應用程序無法啟動,該命令可能很有用。 如果有任何錯誤,將在日志中顯示。
部署應用更新
要部署新版本的應用程序,只需要使用git push命令將新的代碼庫推送到Heroku即可。 這將重復部署過程,關停舊部署,然后用新代碼替換它。 Procfile中的命令將作為新部署的一部分再次運行,因此在此過程中將更新任何新的數據庫遷移或翻譯內容。
總結
以上是生活随笔為你收集整理的Flask 教程 第十八章:Heroku上的部署的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么把视频里的音乐提取出来
- 下一篇: git 命令行使用(基础篇)