1851 words
9 minutes
さくらのレンタルサーバーでDjangoを動かす手順

さくらのレンタルサーバー上で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用の仮想環境を作成する。

Terminal window
python3 -m venv venv

有効化。

Terminal window
source venv/bin/activate

必要なパッケージをインストールする。

Terminal window
pip install django
pip install gunicorn

実際にはプロジェクトで使用しているrequirements.txtがあるなら、

Terminal window
pip install -r requirements.txt

でまとめて入れる。


Gunicornが使えることを確認する#

まず確認。

Terminal window
gunicorn --version

ここで、

gunicorn: Command not found

となる場合は、Gunicornそのものより先に今どのPython環境を使っているかを確認する。

Terminal window
which python
which pip
which gunicorn

仮想環境を使っているなら、それぞれが仮想環境配下を向いているか確認する。

今回もGunicornをインストールしたのにCommand not foundになり、仮想環境やPATHを確認することになった。


GunicornからDjangoを起動する#

Djangoプロジェクトのmanage.pyがあるディレクトリへ移動する。

Terminal window
cd ~/django-app

Gunicornを起動。

Terminal window
gunicorn mysite.wsgi:application \
--bind 127.0.0.1:8000

重要なのが、

mysite.wsgi

の部分。

wsgi.pyが、

mysite/wsgi.py

にあるなら、

mysite.wsgi

と指定する。

プロジェクト直下に移動したからといって、

Terminal window
gunicorn wsgi

でいいわけではない。

Pythonのモジュールとして指定する必要がある。


まずcurlで確認する#

Apacheの設定を触る前に、Gunicorn単体でDjangoが動いているか確認する。

Terminal window
curl http://127.0.0.1:8000

ここでDjango側のレスポンスが返ってくれば、

Gunicorn
↓
Django

までは正常。

この確認はかなり大事。

ブラウザからアクセスしてInternal Server Errorになった場合でも、

Terminal window
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"

そのうえで、

Terminal window
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を確認する。

Terminal window
which python
which pip
which gunicorn

.htaccessにApache設定を何でも書けるわけではない#

今回、

DocumentRoot
ProxyPass
Alias

などを試したが、共有サーバーでは使えないものがあった。

not allowed here

が出たら、その設定自体が.htaccessで許可されているか確認する。


Internal Server ErrorならまずGunicorn単体を確認する#

Terminal window
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ファイルの配信を確認する。

Terminal window
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と戦うより、この順番の方がだいぶ迷子になりにくい。