Djangoで作った自作WEBシステムをHerokuにデプロイした際に、ビルド自体は成功するものの500エラーが返ってきてしまう現象に遭遇しました。原因はStaticファイルに関わる設定にあったようで、Django側の設定を変更して500エラーを解決できました。しかし、このあたりの設定について理解できていないことが多いのでここに調査して整理しておきます。
500エラー以前に、デプロイが失敗するとき
collectstaticコマンドが失敗する
DjangoをHerokuにデプロイする際に、自動的にDjangoのcollectstaticというコマンドが実行されます。Herokuのドキュメントにも記載があります。
python manage.py collectstatic --noinput
この際にDjangoのStaticファイルの設定が正しくない場合ビルドが失敗します。
(Staticファイルを使っていないなら)collectstaticの自動実行を止められる
もし自分のDjangoプロジェクトでStaticファイル(静的ファイル:CSSや画像ファイルなど)を使っていない場合には以下のコマンドでcollectstaticをビルド時にさせないようにできます。
heroku config:set DISABLE_COLLECTSTATIC=1
ネットでHerokuへのデプロイに失敗する事例を調べて見つかる「DISABLE_COLLECTSTATICを無効にして解決しました!」という情報は、Staticファイルを使っていないプロジェクトの話だと思います。
Staticファイルを使っているならcollectstaticの無効化では解決しない
もし自分のDjangoプロジェクトがStaticファイルを使っているのにDISABLE_COLLECTSTATICを設定すると、collectstaticを実行せずエラーを出さないので一見ビルドが成功します。
しかし、いざアプリケーションにアクセスしてみると、おそらく500エラーを返してきます。
つまりDISABLE_COLLECTSTATICを設定せずに、Staticファイルの設定を正しく行う必要があります。
500エラーが出る時
500エラーが出る原因はStaticファイルの設定によるものだけとは限りませんが、ここではStaticファイルの設定に関わるものが原因と考えられる500エラーの解決策を調査した内容について書きます。
Heroku公式に記載のStaticファイルの設定
HerokuのドキュメントにStaticファイルの設定について記載されています。
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
公式に記載されている内容ですので、自分のプロジェクトでもこちらに従い設定しました。(しかしcollectstatic時にエラーとなる)
Staticファイルの設定項目を確認
Djangoのsettings.pyに記載するStaticファイルの設定項目は正直なところイマイチわかりづらいと感じますが、ネットで検索すると参考になる記事が見つかりますのでご紹介します。
STATIC_ROOTはHerokuのドキュメントでは「staticfiles」としており、自分のDjangoプロジェクトにも予めこのディレクトリを作っておきます。そして、collectstaticコマンドが実行された際には、このstaticfilesディレクトリにStaticファイルが集められます。
STATIC_URLはWEBサーバーがStaticファイルを見に行く場所を設定する項目だそうですが、「/static/」とされておりSTATIC_ROOTのパスと異なる点が個人的に理解できていません。STATIC_ROOTとSTATIC_URLの設定について調べると両方とも同じ「/static/」に設定されている例が多くみつかります。
HerokuにデプロイしたアプリケーションのStaticファイルのURLを確認してみると、/static/○○/□□/hogehoge.pngといった形になっていました。つまり、STATIC_ROOTの「staticfiles」には静的ファイルの実態が保存されており、STATIC_URLの「/static/」がサーバーとして公開されるディレクトリになっていることを確認しました。このあたりは個人的にHerokuに限らずサーバー関係の取り扱いについて知識が足りておらず理解できていないため、調査中です。
STATICFILES_DIRSはDjangoの個別アプリケーションに限らず共通で使うファイルを置くディレクトリを設定する項目のようです。こちらはSTATIC_ROOTにコピーされます。つまり、Herokuの設定に従うと「staticfiles」にコピーされます。
STATIC_URLの設定については以下の記事も参考になると思います。
500エラーの解決
結局のところ個人的に解決には至ったのですが、正直なところその理由については明確に理解できていません。
結論としてはsettings.pyからSTATICFILES_DIRSを削除することで500エラーが解消しました。
# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
これをHerokuデプロイ時に読み込まれる設定から削除したところ500エラーが解消し、アプリケーションが動作しました。
Herokuの環境を確認するために、heroku run bash
を実行してHeroku上のstaticfiles(STATIC_ROOTで設定したディレクトリ)の中を確認すると確かにStaticファイルが保存されていました。
500エラーの解決についてネットで調べると以下の記事が出てきました。
この記事ではSTATICFILES_DIRSがいらないとされています。
STATICFILES_DIRSはいらない。
https://www.mathpython.com/ja/django-debug-false/
また、以下の記事では直接STATICFILES_DIRSについては触れられていませんが、結果的にSTATICFILES_DIRSの設定が削除されています。
結果として500エラーの解決には至りましたが、どうして解決できたか理解できていないため引き続き調査する予定です。
なお、HerokuはGitで管理されていないファイルは自動的に削除されるため、今回の解決に至った設定が誤っている恐れもあるため引き続き確認を行います。
コメント