Skip to content

Latest commit

 

History

History
187 lines (126 loc) · 6.87 KB

24-deploy-to-heroku.md

File metadata and controls

187 lines (126 loc) · 6.87 KB

先從簡單的開始。一個 Django 網站的 deployment 包含以下項目:

  1. Django、你的網站程式碼、第三方套件。
  2. 靜態檔(static files)。在 Django 中這代表所有你的網站有用到,但不是 Python 程式與 templates 的檔案,例如圖片、CSS、JavaScript 檔案等等。
  3. 媒體檔(media files)。在 Django 中這代表在網站執行時動態產生的非程式檔案,例如使用者上傳的照片。
  4. WSGI HTTP 伺服器,用來執行 Python 程式。
  5. 檔案 HTTP 伺服器,用來 serve static 與 media files。
  6. HTTP 伺服器,用來作為 WSGI 與檔案伺服器的統一入口。在比較小的網站中,這可以和檔案 HTTP 伺服共用同一個伺服器程式。

我們這裡從簡單的開始:Heroku。

Heroku 已經提供 HTTP 伺服器功能,而且本身不支援檔案上傳(當然你可以選擇把檔案伺服架在其他服務上,不過這邊先不談),所以我們不需要管 3 和 6,5 的設定也只要做一半。

對了,你必須安裝 Git 與 Heroku Toolbelt。在遙遠的第一章裡有個安裝教學連結,如果你當初照著做,應該就已經有了。如果沒有,現在把它們裝起來。

首先我們要讓 Heroku 使用 Python。建立一個檔案 runtime.txt,內容只有一行:

python-3.4.2

這個檔案必須被放在專案的最上層,也就是與你的 apps(basestores 等等)同一層。

接著要告訴 Heroku 必須裝哪些東西。Heroku 使用 PIP 的 requirements file 格式,所以我們可以在專案頂層用下面的指令快速匯出目前使用的套件:

pip freeze > requirements.txt

打開產生的 requirements.txt,在最後面加入下面這行:

django-toolbelt

這個套件包含所有 Heroku 需要的額外套件,包括:

  • Django(這我們其實上面有列了,不過沒關係)
  • Gunicorn(WSGI server)
  • DJ-Static(靜態檔伺服)
  • dj-database-url 與 Psycopg2

其中最後兩個是 Heroku 專用套件。Heroku 不支援檔案伺服,但是我們可以藉由 DJ-Static,用 WSGI 伺服模擬一個。最後一項則是用來存取資料庫;Heroku 使用 PostgreSQL,所以必須安裝它的 Python binding——Psycopg2,dj-database-url 則可以方便我們設定資料庫的參數。

再來,告訴 Heroku 要怎麼執行這個網站。同樣在頂層目錄,建立 Procfile(注意沒有副檔名!):

web: gunicorn lunch.wsgi --log-file -

這裡我們使用 gunicorn 這個 WSGI server,要求執行 WSGI 程式。後面的參數代表把 error log 輸出至 stderr,這樣才能讓這些 logs 被 Heroku 紀錄。

很久很久以前我們提過,開發機與部署時會需要不同的設定。我們要為 Heroku 增加一個設定檔:

# lunch/settings/deploy_heroku.py

from .base import *     # noqa
import dj_database_url

# 把 debug 模式關掉。
DEBUG = False

# 設定 secret key。
SECRET_KEY = get_env_var('DJANGO_SECRET_KEY')

# 尊重 HTTPS 連線中的 "X-Forwarded-Proto" header。
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# 設定靜態檔位置。
STATIC_ROOT = 'static'

# 設定資料庫。
DATABASES = {
    'default': dj_database_url.config()
}

# 允許所有網址連至本網站。
ALLOWED_HOSTS = ['*']

如果你看不懂其中某些設定,沒關係,只要先記得這樣設就可以了。其中有些設定是專為 Heroku 設定的,但大部份我們之後都會再解釋。

注意上面我們用到了一個 function get_env_var。我們要在 lunch/settings/base.py 定義它:[註 1]

from django.core.exceptions import ImproperlyConfigured

def get_env_var(key):
    try:
        return os.environ[key]
    except KeyError:
        raise ImproperlyConfigured(
            'Environment variable {key} required.'.format(key=key)
        )

最後修改 lunch/wsgi.py,啟用 DJ-Static:

# lunch/wsgi.py

import os
from django.core.wsgi import get_wsgi_application
from dj_static import Cling

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lunch.settings")
application = Cling(get_wsgi_application())     # 注意這一行。

這樣就準備完成了!接著是建立 Git repository。你可能會想要先建立一個 .gitignore 檔案(同樣放在最頂層,和 requirements.txt 一起):

*.py[co]
__pycache__

然後執行指令:

git init
git add .
git commit -m "Make it so"

接下來我們要在 Heroku 建立一個 instance,好把我們的程式上傳。先到 http://heroku.com/ 註冊一個帳號。註冊認證完成後,你應該會進入你的 Heroku dashboard。接著在終端機登入你的 Heroku 帳號:

heroku login

如果你是第一次登入,系統會要求上傳一個 SSH public key。請直接允許。

接著建立 project:

heroku create <project_name>

名稱可以隨意取,之後這就會顯示在你的網站網址裡(不過如果有人用過這個名稱就不能再用,所以還滿容易撞名);如果你留白,Heroku 會隨機幫你取一個很電波的名字。

然後用 Git Push 上傳整個 respository:(這應該會跑一段時間)

git push heroku master

再建立一個 instance:

heroku ps:scale web=1

接著我們要設定 secret key 用到的環境變數,以及設定檔的位置。你可以自己產生一個字串來當成 secret key,或者如果不知道怎麼產生,請參考 https://djskgen.herokuapp.com/

這樣設定:

heroku config:set DJANGO_SECRET_KEY=<your_secret_key>
heroku config:set DJANGO_SETTINGS_MODULE=lunch.settings.deploy_heroku

注意 shell 中某些字元會被視為 escape sequence,所以你可能會需要用單引號把 secret key 包起來。如果你搞不定,其實 Heroku 網頁上也有地方可以設。

接著重跑 migration,讓遠端的資料庫與我們之前的設定相符:

heroku run python manage.py migrate

如果你想在 Heroku 上執行某些指令,只要在原本的指令前面加上 heroku run 即可。你也可以用一樣的方法建立 superuser:

heroku run python manage.py createsuperuser

這樣就搞定了!打開你的網站看看:

heroku open

以上是最簡單的 deploy 設定,實務上還有一些可以改的東西,例如有人建議Waitress 取代 Gunicorn(我個人也推薦用這個),或者有人習慣用 Whitenoise 而非 DJ-Static。不過基本上的設定都一樣。明天我們會試著把 Django deploy 到一個 Linux server 上,來看看比較進階的 deploy 設定。


註 1:當然其實我們可以在 deploy_heroku.py 定義就好,但這個 function 很有用,所以我們把它丟在頂層,未來在其他地方也可以用。