私の目標:
Heroku で Django アプリを構築するための "The Twelve-Factor App" 方法論に従うつもりです。
序章:
「Heroku での Django 入門」クイック スタート ガイドに従っています。現時点では、次のディレクトリ構造があります。
~/Projects/
hellodjango_rep/
.env (empty)
.git
.gitignore
Procfile
requirements.txt
hellodjango/
manage.py
hellodjango/
__init__.py
settings/
urls.py
wsgi.py
django-toolbelt をインストールし、単純な Django アプリケーションを作成し、Procfile でプロセスを開始しました... すべて正常に動作しているように見えましたが、Heroku 環境用にアプリケーションを構成して追加したときに問題が発生しました。
import dj_database_url
DATABASES['default'] = dj_database_url.config()
私のsettings.pyファイルの一番下に。
アプリケーションのリポジトリを Heroku にプッシュし、ブラウザーでアプリを$ heroku open
正常にアクセスしましたが、ローカル:dj_database_url.config()
空の辞書が返されました。
ローカル:
OS X 10.8.4
pip==1.4.1
virtualenv==1.10.1
virtualenvwrapper==4.1.1
wsgiref==0.1.2
ポート 5432 で実行されている Postgres.app
環境変数:
mac-pol:hellodjango_rep oubiga$ python
>>> import os
>>> os.environ
{
'PROJECT_HOME': '/Users/oubiga/Projects'...
'PATH': '/usr/local/heroku/bin:/usr/local/share/python:/usr/local/bin:/Applications/Postgres.app/Contents/MacOS/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin'...
'HOME': '/Users/oubiga'...
'WORKON_HOME': '/Users/oubiga/Envs'...
'VIRTUALENVWRAPPER_HOOK_DIR': '/Users/oubiga/Envs'...
'PWD': '/Users/oubiga/Projects/hellodjango_rep'
}
hellodjango_venv:
Django==1.5.2
dj-database-url==0.2.2
dj-static==0.0.5
django-toolbelt==0.0.1
gunicorn==18.0
psycopg2==2.5.1
static==0.4
これは私の wsgi.py ファイルにあるものです:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hellodjango.hellodjango.settings")
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
これは私のmanage.pyファイルにあるものです:
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hellodjango.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
これは私のProcfileにあるものです:
web: gunicorn hellodjango.hellodjango.wsgi
環境変数:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ python hellodjango/manage.py shell
>>> import os
>>> os.environ
{
'PROJECT_HOME': '/Users/oubiga/Projects'...
'PATH': '/Users/oubiga/Envs/hellodjango_venv/bin:/usr/local/heroku/bin:/usr/local/share/python:/usr/local/bin:/Applications/Postgres.app/Contents/MacOS/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin',
'HOME': '/Users/oubiga'...
'WORKON_HOME': '/Users/oubiga/Envs'...
'VIRTUAL_ENV': '/Users/oubiga/Envs/hellodjango_venv'...
'VIRTUALENVWRAPPER_HOOK_DIR': '/Users/oubiga/Envs'...
'PWD': '/Users/oubiga/Projects/hellodjango_rep'...
'DJANGO_SETTINGS_MODULE': 'hellodjango.settings'
}
Heroku の場合:
環境変数:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ heroku run python hellodjango/manage.py shell
>>> import os
>>> os.environ
{
'DATABASE_URL': 'postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname',
'HEROKU_POSTGRESQL_ORANGE_URL': 'postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname',
'LIBRARY_PATH': '/app/.heroku/vendor/lib', 'PWD': '/app'...
'DJANGO_SETTINGS_MODULE': 'hellodjango.settings',
'PYTHONHOME': '/app/.heroku/python'...
'PYTHONPATH': '/app/'...
'DYNO': 'run.9068',
'LD_LIBRARY_PATH': '/app/.heroku/vendor/lib'...
'HOME': '/app', '_': '/app/.heroku/python/bin/python',
'PATH': '/app/.heroku/python/bin:/usr/local/bin:/usr/bin:/bin'...
}
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ heroku config
=== damp-dusk-5382 Config Vars
DATABASE_URL: postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname
HEROKU_POSTGRESQL_ORANGE_URL: postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname
リサーチ:
環境に構成を保存する: The Twelve-Factor App から
@adamwiggins は次のように書いています。
Twelve-Factor アプリは構成を環境変数に保存します。環境変数は、コードを変更せずにデプロイ間で簡単に変更できます。設定ファイルとは異なります。
dj_database_url.config()
空のオブジェクトを返しています: Heroku フォーラムから
@chrisantonic は次のように答えました。
... dj_database_url.config() は、Heroku 環境変数から Postgres 認証情報を取得します。しかし、ローカル マシンでは、これらの変数は存在しません。それらを /venv/bin/activate シェルスクリプトに配置する必要があります...そこに変数を配置します。
DATABASE_URL = "xxx"
export DATABASE_URLのようなもの
必要なものごとに。次に...「無効化」...そして...もう一度「有効化」して再起動します。
Django および Heroku の使用を開始する手順で ImproperlyConfigured エラーが発生しました: Heroku フォーラムから
@jwpe は次のように答えました。
... dj-database-url は、「12 要素アプリの原則」で推奨されているように、開発環境と運用環境でまったく同じ settings.py コードを使用できるため、優れたユーティリティです... dj_database_url.config とは() が行っているのは、DATABASE_URL 環境変数を探し、それを Django の優先形式に解析することです... Heroku で postgres DB を手動で作成および昇格していない場合、DATABASE_URL は存在せず、ImproperlyConfigured エラーが発生します. dj_database_url.config() のデフォルトをローカル DB URL として設定することは、アプリケーションが開発環境で動作することを確認する 1 つの方法です。ただし、必ずしもそれが唯一の方法ではありません。多分代わりに、ローカルの .env ファイルに DATABASE_URL を手動で設定することをお勧めします。次に、Foreman を使用してアプリをローカルで実行すると、環境変数として読み込まれ、dj_database_url がそれを見つけます。したがって、.env には以下が含まれます。
DATABASE_URL=postgres://user:pass@localhost/dbname
つまり、次の
settings.py
ものだけが必要です。
DATABASES['default']= dj_database_url.config()
...単一のハードコーディングされたデフォルトの代わりにローカル環境変数を使用する利点は、DATABASE_URL が設定されている任意の環境でコードが実行されることです。ローカル DB の名前を変更する場合、または別の開発マシンでコードを実行する場合は、 settings.py をいじる代わりに .env ファイルを更新するだけで済みます。
本番/ステージング/開発の Django 設定を管理するには?: Heroku フォーラムから
@rdegges は次のように答えました。
... 次のような方法でアプリケーションを動作させようとしています。
- ラップトップでアプリを実行している場合、ローカルの Postgres サーバーが使用されます。
- ステージング Heroku アプリでアプリを実行している場合、Postgres サーバー アドオンが使用されます。
- 本番 Heroku アプリでアプリを実行している場合、Postgres サーバー アドオンが使用されます。
これを実現する最善の方法は、環境変数を使用することです!…環境変数は、異なる環境間でアプリケーションの構成を処理する最も洗練された (そしてスケーラブルな) 方法です… 多くの設定ファイルを持つ代わりに、1 つのファイル settings.py を定義し、環境変数を利用してサービス情報と資格情報を取得します... Herokuでは、次を実行して環境変数を手動で設定できます。
$ heroku config:set SOME_VARIABLE=some_value
... Kenneth Reitz の優れた autoenv ツールが常にあります。これにより、プロジェクト ディレクトリに単純な .env ファイルを定義できます。プロジェクト ディレクトリに入るたびに、これらの環境変数が自動的に設定されるため、特別なことをする必要はありません。プロジェクトを実行するだけで、すべてが期待どおりに機能します。
python manage.py runserver
最初の試みとして:
DATABASE_URL
.env ファイル に手動で設定しました。DATABASE_URL=postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname
しかし、$ foreman start
コマンドを実行すると:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman start
17:25:39 web.1 | started with pid 319
17:25:39 web.1 | 2013-09-11 17:25:39 [319] [INFO] Starting gunicorn 18.0
17:25:39 web.1 | 2013-09-11 17:25:39 [319] [INFO] Listening at: http://0.0.0.0:5000 (319)
17:25:39 web.1 | 2013-09-11 17:25:39 [319] [INFO] Using worker: sync
17:25:39 web.1 | 2013-09-11 17:25:39 [322] [INFO] Booting worker with pid: 322
ブラウザでアプリを開こうとしましたhttp://0.0.0.0:5000
:
17:26:59 web.1 | 2013-09-11 10:26:59 [322] [ERROR] Error handling request
17:26:59 web.1 | Traceback (most recent call last):
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 131, in handle_request
17:26:59 web.1 | respiter = self.wsgi(environ, resp.start_response)
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/dj_static.py", line 59, in __call__
17:26:59 web.1 | return self.application(environ, start_response)
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 236, in __call__
17:26:59 web.1 | self.load_middleware()
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 53, in load_middleware
17:26:59 web.1 | raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
17:26:59 web.1 | ImproperlyConfigured: Error importing middleware django.contrib.auth.middleware: "dlopen(/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so, 2): Library not loaded: @loader_path/../lib/libssl.1.0.0.dylib
17:26:59 web.1 | Referenced from: /Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so
17:26:59 web.1 | Reason: image not found"
ただし、次のようにdj_database_url.config()
返されます。
{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dbname',
'HOST': 'ec2-23-21-196-147.compute-1.amazonaws.com',
'USER': 'dbuser',
'PASSWORD': 'dbpassword',
'PORT': 5432
}
2 回目の試行として:
DATABASE_URL
ホストを変更する.envファイルを手動で設定しました。「ec2-184-73-162-34.compute-1.amazonaws.com:5432」を「localhost:5000」に置き換えました。$ deactivate
そして$ workon hellodjango_venv
また。
DATABASE_URL=postgres://dbuser:dbpassword@localhost:5000/dbname
しかし、$ foreman start
コマンドを実行すると:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman start
17:38:41 web.1 | started with pid 687
17:38:41 web.1 | 2013-09-11 17:38:41 [687] [INFO] Starting gunicorn 18.0
17:38:41 web.1 | 2013-09-11 17:38:41 [687] [INFO] Listening at: http://0.0.0.0:5000 (687)
17:38:41 web.1 | 2013-09-11 17:38:41 [687] [INFO] Using worker: sync
17:38:41 web.1 | 2013-09-11 17:38:41 [690] [INFO] Booting worker with pid: 690
ブラウザでアプリを開こうとしましたhttp://0.0.0.0:5000
:
17:38:46 web.1 | 2013-09-11 10:38:46 [690] [ERROR] Error handling request
17:38:46 web.1 | Traceback (most recent call last):
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 131, in handle_request
17:38:46 web.1 | respiter = self.wsgi(environ, resp.start_response)
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/dj_static.py", line 59, in __call__
17:38:46 web.1 | return self.application(environ, start_response)
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 236, in __call__
17:38:46 web.1 | self.load_middleware()
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 53, in load_middleware
17:38:46 web.1 | raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
17:38:46 web.1 | ImproperlyConfigured: Error importing middleware django.contrib.auth.middleware: "dlopen(/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so, 2): Library not loaded: @loader_path/../lib/libssl.1.0.0.dylib
17:38:46 web.1 | Referenced from: /Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so
17:38:46 web.1 | Reason: image not found"
今回は、次のようにdj_database_url.config()
返されました。
{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dbname',
'HOST': 'localhost',
'USER': 'dbuser',
'PASSWORD': 'dbpassword',
'PORT': 5000
}
3 回目の試行として:
autoenv をインストールしたケネス・レイツが書いたmac-pol:~ oubiga$ pip install autoenv
このクックブックから、次のように記述しました。
use_env() {
typeset venv
venv="$1"
if [[ "${VIRTUAL_ENV:t}" != "$venv" ]]; then
if workon | grep -q "$venv"; then
workon "$venv"
else
echo -n "Create virtualenv $venv now? (Yn) "
read answer
if [[ "$answer" == "Y" ]]; then
mkvirtualenv "$venv"
fi
fi
fi
}
私の .bashrc ファイルに。
コマンドを実行します$ foreman start
:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman start
18:11:57 web.1 | started with pid 1104
18:11:57 web.1 | 2013-09-11 18:11:57 [1104] [INFO] Starting gunicorn 18.0
18:11:57 web.1 | 2013-09-11 18:11:57 [1104] [INFO] Listening at: http://0.0.0.0:5000 (1104)
18:11:57 web.1 | 2013-09-11 18:11:57 [1104] [INFO] Using worker: sync
18:11:57 web.1 | 2013-09-11 18:11:57 [1107] [INFO] Booting worker with pid: 1107
ブラウザでアプリを開こうとしましたhttp://0.0.0.0:5000
:うまくいきました!
^CSIGINT received
18:12:06 system | sending SIGTERM to all processes
18:12:06 web.1 | 2013-09-11 11:12:06 [1107] [INFO] Worker exiting (pid: 1107)
SIGTERM received
18:12:06 web.1 | 2013-09-11 18:12:06 [1104] [INFO] Handling signal: int
18:12:06 web.1 | 2013-09-11 18:12:06 [1104] [INFO] Shutting down: Master
18:12:06 web.1 | exited with code 0
しかし、dj_database_url.config()
再び空の辞書を返します。
最後の試みとして:
コマンドが気python manage.py runserver
になったので調べてみました。
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman run python hellodjango/manage.py runserver
Validating models...
0 errors found
September 11, 2013 - 18:42:37
Django version 1.5.2, using settings 'hellodjango.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
ブラウザでアプリを開こうとしましたが、http://127.0.0.1:8000/
うまくいきませんでした!
アンImportError: No module named hellodjango.urls
が育てられました。
ROOT_URLCONF = 'hellodjango.hellodjango.urls'
settings.py ファイルを に置き換えたROOT_URLCONF = 'hellodjango.urls'
ところ、最終的に機能しました。
予想どおり、dj_database_url.config()
空の辞書が返されました。
そう:
今、私は少し圧倒されているように感じます。ここでいくつかのコアコンセプトを誤解しているのではないかと心配しています。
- Django 開発サーバーの代わりに gunicorn を使用するポイントは何ですか?
dj_database_url.config()
が完全に入力された辞書を返す場合と、空の辞書を返す場合があるのはなぜですか?- .env ファイルで環境変数を手動で設定できますか? autoenv、heroku-config などのツールをインストールする必要がありますか?
前もって感謝します。