さくらのレンタルサーバー上でDjangoを動かしたときの手順をまとめる。
実際にやったときは、
- Gunicornが見つからない
.htaccessでApacheに怒られる- Internal Server Error
- Rewriteが無限ループする
- Django管理画面のCSSが消える
など、いろいろ寄り道した。
この記事ではその辺の調査過程はいったん横に置いて、最終的にDjangoを動かすために何をしたかだけ整理する。
実際にハマった流れについては別記事にまとめている。
全体の構成
今回の構成はざっくりこう。
ブラウザ ↓Apache ↓.htaccess ↓Rewrite ↓Gunicorn ↓Djangoさくらのレンタルサーバーは共有サーバーなので、ApacheのVirtualHostを自由に設定することはできない。
そのため、Apache側は.htaccessのRewriteを使ってGunicornへリクエストを渡す構成にした。
Djangoプロジェクトを配置する
まずサーバー上にDjangoプロジェクトを配置する。
たとえば、
~/www/~/django-app/のように、公開ディレクトリとDjangoプロジェクトを分けておく。
Django側は通常通り、
django-app/├── manage.py├── mysite/│ ├── settings.py│ ├── urls.py│ └── wsgi.py└── ...のような構成。
ここではDjangoプロジェクト名をmysiteとして説明する。
Python仮想環境を作る
Django用の仮想環境を作成する。
python3 -m venv venv有効化。
source venv/bin/activate必要なパッケージをインストールする。
pip install djangopip install gunicorn実際にはプロジェクトで使用しているrequirements.txtがあるなら、
pip install -r requirements.txtでまとめて入れる。
Gunicornが使えることを確認する
まず確認。
gunicorn --versionここで、
gunicorn: Command not foundとなる場合は、Gunicornそのものより先に今どのPython環境を使っているかを確認する。
which pythonwhich pipwhich gunicorn仮想環境を使っているなら、それぞれが仮想環境配下を向いているか確認する。
今回もGunicornをインストールしたのにCommand not foundになり、仮想環境やPATHを確認することになった。
GunicornからDjangoを起動する
Djangoプロジェクトのmanage.pyがあるディレクトリへ移動する。
cd ~/django-appGunicornを起動。
gunicorn mysite.wsgi:application \ --bind 127.0.0.1:8000重要なのが、
mysite.wsgiの部分。
wsgi.pyが、
mysite/wsgi.pyにあるなら、
mysite.wsgiと指定する。
プロジェクト直下に移動したからといって、
gunicorn wsgiでいいわけではない。
Pythonのモジュールとして指定する必要がある。
まずcurlで確認する
Apacheの設定を触る前に、Gunicorn単体でDjangoが動いているか確認する。
curl http://127.0.0.1:8000ここでDjango側のレスポンスが返ってくれば、
Gunicorn↓Djangoまでは正常。
この確認はかなり大事。
ブラウザからアクセスしてInternal Server Errorになった場合でも、
curl http://127.0.0.1:8000が成功していれば、
DjangoやGunicornではなく、ApacheからGunicornまでの経路がおかしい
と切り分けられる。
今回の調査でも、この確認でかなり範囲を絞れた。
.htaccessを設定する
次にApacheからGunicornへリクエストを渡す。
共有サーバーなので、
<VirtualHost>や、
ProxyPassを自由に設定することはできなかった。
実際、
not allowed hereとなった。
そのため.htaccessのRewriteを使う。
設定イメージは、
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/static/RewriteRule ^(.*)$ http://127.0.0.1:8000/$1 [P,L]のようになる。
実際の配置場所やURL構成に応じてRewriteRuleは調整する。
Rewriteの無限ループに注意
Rewrite設定では、転送先が再び同じRewriteRuleに引っかからないよう注意する。
今回も設定途中で、
Request exceeded the limit of 10 internal redirectsが発生した。
原因はRewriteが自分自身へ向いてしまい、
リクエスト↓Rewrite↓同じURL↓Rewrite↓同じURL↓...となっていたこと。
このエラーが出たら、Djangoより先にRewriteRuleを見る。
staticファイルを配置する
Django管理画面などではstaticファイルも必要になる。
まずsettings.pyでSTATIC_ROOTを設定する。
STATIC_ROOT = BASE_DIR / "static"そのうえで、
python manage.py collectstaticを実行する。
これでDjangoが使用するstaticファイルを一箇所に集める。
Apache側ではstaticをGunicornへ流さない
staticファイルまで毎回Gunicornへ渡す必要はない。
そのためRewrite側で、
RewriteCond %{REQUEST_URI} !^/static/のように除外する。
今回、ApacheのAliasも試したが、
Alias not allowed hereとなった。
共有サーバーでは使えるApache設定に制限があるため、VirtualHost環境と同じ設定をそのまま持ってくるとハマりやすい。
表示確認
ここまで設定したらブラウザからアクセスする。
確認する順番としては、
1. Gunicornが起動しているか ↓2. curl 127.0.0.1:8000 が通るか ↓3. Apache経由でDjangoが表示されるか ↓4. staticファイルが取得できるかくらいに分けると分かりやすい。
いきなりブラウザのInternal Server Errorだけを見ていると、
Django?Gunicorn?Apache?Rewrite?のどこがおかしいのか分からなくなる。
ハマりやすかったポイント
今回実際にハマったところをまとめる。
Gunicornを入れたのにコマンドが見つからない
gunicorn: Command not found仮想環境やPATHを確認する。
which pythonwhich pipwhich gunicorn.htaccessにApache設定を何でも書けるわけではない
今回、
DocumentRootProxyPassAliasなどを試したが、共有サーバーでは使えないものがあった。
not allowed hereが出たら、その設定自体が.htaccessで許可されているか確認する。
Internal Server ErrorならまずGunicorn単体を確認する
curl http://127.0.0.1:8000これが通るなら、DjangoとGunicornはひとまず動いている。
ApacheやRewrite側へ調査対象を移せる。
Request exceeded the limit of 10 internal redirects
Rewriteの無限ループを疑う。
Rewrite後のURLが、もう一度同じRewriteRuleに引っかかっていないか確認する。
管理画面だけCSSがない
Django本体ではなくstaticファイルの配信を確認する。
python manage.py collectstaticを実行し、Apache側からstaticへアクセスできる状態にする。
DBについては別問題
ここまでで、
Apache↓Gunicorn↓Djangoを動かすところまではできる。
ただし、DjangoからDBを使う場合は別途DB環境が必要。
今回の環境では、この後、
django.db.utils.NotSupportedError:MySQL 8 or later is required(found 5.7.40)という別の問題に遭遇した。
そして、
じゃあMySQL8を自前で入れればいいのでは?
と考えた結果、Boostやlibunwindが次々出てくる「依存関係モグラ叩き編」が始まることになる。
そこはDjangoを動かす手順とは別問題なので、別記事に分けている。
今回の構成
最終的には、
ブラウザ ↓Apache ↓.htaccess / Rewrite ↓Gunicorn(127.0.0.1:8000) ↓Djangoという構成になった。
共有サーバーなので、VPSでDjangoを構築するときのようにApacheやNginxを自由に設定できるわけではない。
その制約を理解したうえで、
「まずGunicorn単体で動かす → curlで確認する → 最後にApacheと繋ぐ」
の順番で確認するのがポイント。
最初から全部繋いでInternal Server Errorと戦うより、この順番の方がだいぶ迷子になりにくい。