HerokuにDjangoアプリケーションをデプロイしてもcollectstaticが実行されないことがある
【2014年6月3日追記】この後、ビルド時にデフォルトで環境変数を参照できるようになったため、現在この問題は発生しません。
user-env-compile
も廃止されました。
See: App environment available in all builds | Heroku Dev Center
はじめに
Heroku では、Djangoの静的ファイル(画像・CSS・JSなど)をサーブするために、dj-static を使うようガイドがあります。大規模なアプリケーションであればCDNの利用を検討するべきですが、ある程度までは問題ないようです。
Getting Started with Django on Heroku | Heroku Dev Center
しかし、python manage.py collectstatic
の実行にconfig(環境変数)の値を必要とする場合、デプロイ時にcollectstatic
が実行されないことがあります。
この条件に当てはまると、静的ファイルがサーブされず画像が表示されないといった問題が起こります。
問題が起きたケース
settings.py
に以下のように書いたらこの問題が発生しました。
import os SECRET_KEY = os.environ.get('SECRET_KEY')
これは、秘密にすべきSECRET_KEY
の値をソースコードリポジトリに格納せず、代わりにconfig(環境変数)を使うというTwelve-Factor Appでも推奨されている方法 です。
このプロジェクトをデプロイすると以下のようになり、特にエラーも出ないままcollectstatic
が実行されませんでした。
$ git push heroku master Fetching repository, done. Counting objects: 7, done. Delta compression using up to 2 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 350 bytes, done. Total 4 (delta 3), reused 0 (delta 0) -----> Python app detected -----> No runtime.txt provided; assuming python-2.7.4. -----> Using Python runtime (python-2.7.4) -----> Installing dependencies using Pip (1.3.1) Cleaning up... -----> Discovering process types Procfile declares types -> web -----> Compressing... done, 32.9MB -----> Launching... done, v12 http://xxxxx.herokuapp.com deployed to Heroku To git@heroku.com:xxxxx.git xxxxxx..yyyyyy master -> master
なお、使用したDjangoのバージョンは1.6.1、HerokuのStackはCedarです。
原因
この問題は、以下の理由が複合して発生します。
- Herokuへのデプロイ時にはconfig(環境変数)の値を参照できない。
SECRET_KEY
が空だとINSTALLED_APPS
に列挙されたアプリケーションのインポートに失敗するため、Djangoのコアに含まれないコマンドは実行できない。- Herokuへのデプロイ時に
collectstatic
のdry-runが失敗すると、エラーを出すことなくcollectstatic
の実行はスキップされる。
Herokuのドキュメントでも以下のように書いてありました。
Normally, application configuration isn’t available when your application is being compiled. This can be a problem with, for example, using collectstatic to upload files to S3 with Django-Storages.
If your application needs access to runtime configuration during the build, you can turn it on with user-env-compile:
Django and Static Assets | Heroku Dev Center
対策
上で引用したドキュメントにあるように、以下のコマンドを実行すると解決します。このコマンドを実行すると、デプロイ時にconfig(環境変数)の値を参照できるようになります。
heroku labs:enable user-env-compile
なお、これは実験的な機能 のため将来使えなくなるかもしれません。
まとめ
Herokuのデフォルトの設定では、デプロイ時にconfig(環境変数)を参照できず、問題が起きる可能性があります。自分でBuildpack を書く場合などにも気をつける必要があります。
なお、Herokuのファイルシステム では、デプロイ後に書き込んだファイルは書き込んだプロセスからしか見えません。このため、手動でheroku run python manage.py collectstatic
を実行しても、Webサーバーのプロセスからは見えないため効果がありません。
余談ですが、dj-staticが依存する static はPython 3に対応していないため、Herokuがガイドする方法はPython 3では動きません。対応しようとする動き はありますが、難しいみたいです。今後HerokuにおけるPython/Djangoのサポート状況がもう少し良くなることを期待したいです。