DjangoをDEBUG=FalseでHerokuにデプロイする方法
プロジェクトのディレクトリ構造は、『現場で使えるDjangoの教科書 基礎編』に準拠している。
HerokuCLIをインストール
Herokuではherokuコマンドを実行して、事前にログインをした上でデプロイを行う。下記からインストールする。
https://devcenter.heroku.com/ja/articles/heroku-cli
herokuコマンドを実行して、デプロイ先のサーバーでマイグレーション等の操作を行うためにある。
【補足1】Herokuコマンドが使えない。
Windowsの場合、HerokuCLIをインストール直後にherokuコマンドを実行しようとしても、コマンドとして認識されないことがある。
そんな時は、PCを再起動するとherokuコマンドが使えるようになる。
Herokuのアカウント作成、アプリ作成から設定まで
予めHerokuのアカウントを作っておく。クレジットカード不要で必要なものはメールアドレスだけ。
まずはHerokuアカウントからデプロイ先として指定するアプリを作る。ダッシュボードにアクセスすると下記画面が見える。右上のNEWをクリックする。
ツールチップが表示されるので、Create new appをクリック。
app nameを指定する。サーバーのリージョン(居場所)はアメリカを指定注意:無料アカウントでは作成できるアプリの数の上限は5個。それ以上は作れないため注意。
端末からHerokuにログインする。
heroku login
DBのパスワード、ホスト名などを控える
Heroku側にはDBのPostgreSQLが用意されている。そのパスワードとホスト名等を控え、settings.pyに書き込むことでDBが使用できる
デフォルトではpostgresqlは実装されていないため、実装する必要がある。まずはHerokuのResourceタブをクリックする。
Add-onsにて、postgresと入力する。Heroku Postgresをクリック
Submit Order Formをクリック。
このような表示がされれば問題なく利用できる。
Heroku Postgres のリンクをクリック、Settingsタブをクリック。View Credentialsをクリック
DBの使用に必要なユーザー名、DBの名前、パスワードなどが表示される。これを後のsettings.pyに書き込む。
settings.pyの設定
下記に倣ってsettings.pyを書き換える。DEBUGモードの無効化をお忘れなく。
# DEBUGモードを無効化
# DEBUG = True
DEBUG = False
# 静的ファイルの読み込み設定がwhitenoiseに影響が及ぶので、デバッグ時にのみ有効にしておく。
if DEBUG:
STATICFILES_DIRS = [ BASE_DIR / "static" ]
if not DEBUG:
# ALLOWED_HOSTSにホスト名)を入力
ALLOWED_HOSTS = [ 'hogehoge.herokuapp.com' ]
# 静的ファイル配信ミドルウェア、whitenoiseを使用。※ 順番不一致だと動かないため下記をそのままコピーする。
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# DBを使用する場合は下記を入力する。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': '',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '5432',
}
}
#HerokuPostgresの接続方法(SSL使用、接続の有効時間は600秒)
import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=600, ssl_require=True)
DATABASES['default'].update(db_from_env)
# 静的ファイル(static)の存在場所を指定する。
STATIC_ROOT = BASE_DIR / 'static'
#osモジュールを使う場合はこちら。
#STATIC_ROOT = os.path.join(BASE_DIR, 'static')
settings.pyの修正を終えたら、pipコマンドでデプロイ後に必要になるライブラリをインストールさせる。
pip install django-heroku dj-database-url gunicorn whitenoise psycopg2
requirements.txtにて控えを用意する。このrequirements.txtに基づき、Herokuにデプロイ時にライブラリがインストールされる。
pip freeze > requirements.txt
gunicorn(ウェブサーバーとDjangoをつなげるライブラリ)の設定を施す。下記コマンドを実行する。
echo "web: gunicorn config.wsgi:application --log-file -" > Procfile
【補足1】Windowsで作った設定ファイル類がHeroku上で読めない
Windowsの場合、echoコマンドを実行したときの文字コードがUTF-8ではないため、Heroku上で読むことができない。
そんな場合は統合開発環境から、ファイルを作り、echoのダブルクオーテーションで囲んだ部分を記入すると良いだろう。
つまり、
echo "web: gunicorn config.wsgi:application --log-file -" > Procfile
であれば、Procfile
というファイルを作り、その中にweb: gunicorn config.wsgi:application --log-file -
と書き込む。
これでHerokuが読める設定ファイルになる。
【補足2】wsgi.pyを格納しているディレクトリ名が違うため、デプロイに失敗する
もし、settings.pyやurls.pyなど設定ファイル関係を格納しているディレクトリが、configではなく、プロジェクト名である場合、下記は間違いである。
echo "web: gunicorn config.wsgi:application --log-file -" > Procfile
仮にディレクトリ名がconfigではなくmyprojectの場合、下記のように修正する必要がある。
echo "web: gunicorn myproject.wsgi:application --log-file -" > Procfile
つまり、設定ファイル関係を格納するディレクトリにある、wsgi.pyを参照して動かしているということ。
wsgi.pyを格納しているディレクトリ名が違うとデプロイに失敗する。
いざデプロイ
プロジェクトをgitで管理する。gitでコミットする。
git init
git add .
git commit -m "heroku deploy"
Herokuのデプロイ先とローカルリポジトリを関連付ける。
ダッシュボードからDeployタブをクリックした時に表示される下記画像に倣ってコマンドを打つ。
heroku git:remote -a アプリの名前
この状態で、デプロイする。下記コマンドを実行してherokuにプッシュ。git push origin master
ではない点に注意。
git push heroku master
ターミナルに表示されるページにアクセスする。アプリがスリープ中の場合、復帰しないといけないため、ブラウザに表示されるまでに1分程度かかる。エラーではない。
【補足1】gitでcommitできない
Herokuデプロイを境に初めてgitをインストールして使う場合、事前にやっておくことがある。コミットするユーザーの名前とメールアドレスの登録である。
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
これをやっておかないとコミットすることができない。
参照:https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration
デプロイ後の設定
DBを使用するタイプのウェブアプリであればデプロイ後にマイグレーションの実行する必要がある。
heroku run python3 manage.py migrate
初期データをインプットするのであれば下記コマンドも実行。
heroku run python3 manage.py loaddata ./アプリ名/fixture/jsonファイル
環境変数の設定
例えば、EMAIL_BACKEND
に値を入れたい場合、下記のように指定すれば良い。
heroku config:set PASSWORD="password"
Python側から読む時、以下のようにする。
import os
PASSWORD_LIST = [ os.environ['PASSWORD'] ]
これでパスワードなどの情報をsettings.pyに直接書かなくても済む
動かないときの対策
設定はしっかりしているのに、エラーが出てしまう場合、下記コマンドを実行してDoneが表示されれば正常に設定が再読込され、動くようになる。
heroku ps:scale web=1
結論
Herokuデプロイでつまずく最大の原因は、余計なものをsettings.pyに書いてしまうこと。
特にHerokuにはストレージがないので、メディアファイルの扱いをsettings.pyに書くともれなく500エラーが返ってくる。ファイルのアップロード関係のウェブアプリを作る予定であれば、別途S3等の外部クラウドストレージを用意してあげましょう。
それからwhitenoiseの位置にも注意。INSTALLED_APPSの順序間違えると動かない。
requirements.txtの記述にも注意が必要。pip freezeコマンドを忘れずに。
【補足】ストレージありのデプロイはどうする?
下記を参照する。
DjangoをHeroku+Cloudinary(基本無料ストレージ)の環境にデプロイする【ウェブアプリのデモを一般公開したい場合などに】
ストレージであるCloudinaryを使う。前もってクレジットカードの登録が必要。