以下は「エックスサーバー」でのDjangoアプリのデプロイ方法です。
他のレンタルサーバーでも概ねの流れは変わらないと思います。
本番環境へのデプロイ方法【レンタルサーバー】
準備:django-environを導入しておく
開発環境で作成したDjangoアプリに、django-environを導入しておきましょう。
導入方法や設定方法については以下の記事で解説していますので、参考にしてください。
DjangoでWebアプリケーションを作成し、いざ本番環境に上げる際に設定は重要な要素です。 開発環境とは違い、重要な情報はなるべく秘匿したいですよね。 今回はそれに便利なDjangoパッケージであるdjango-environにつ[…]
とりあえず、開発環境はdjango-environに対応しておきましょう。
本番環境の設定は後ほど行います。
準備:サーバー関連の準備を進める
レンタルサーバー側の準備を進めましょう。
大きく以下のような準備が必要になります。
- サブドメインの取得
- データベースの作成
- データベース用ユーザーの設定
- SSHの設定確認
各種設定や確認方法はレンタルサーバーによって違いがあるとは思います。
公式サイトを参考に、設定をしてみてください。
準備:SSHで本番環境に入り、仮想環境を作成する
このステップはレンタルサーバー内にPythonがない場合に必要になります。
例えばエックスサーバーはPythonが使えないため、仮想環境を組み立てる必要があります。
(正確にはエックスサーバーにPythonは入っているのですが、複数人が使用するレンタルサーバーのため、使用する権限がユーザーに与えられていません)
私はMinicondaを使用しましたが、機能が充実したAnacondaでも良いでしょう。
ただし以前は使えていたLinuxbrewは2023年現在はエラーになるようですので、使用をオススメしません。
以下に、Minicondaでの仮想環境作成手法を紹介します。
Minicondaでの仮想環境作成手順
https://docs.conda.io/en/latest/miniconda.html
ダウンロードするファイルについてはサーバーに適応したものにしてください。
(基本的にはLinuxだと思います)
TeraTermなどのSSH用アプリを使用して本番環境にアクセスして実行します。
実行ファイル名は、ダウンロードしたファイル名に合わせてください。
先ほど実行したことで作成された仮想環境ディレクトリにPATHを通します。
Pythonのバージョンは開発環境に合わせましょう。
また、これから先仮想環境に入ったあとはコマンドの先頭に「conda」をつけることが多くなることも合わせて覚えておきましょう。
作成した仮想環境ディレクトリまで念のために移動し、次のコマンドを打ちます。
打った後に、左側に(仮想環境名)が付いていれば、仮想環境にアクセスできています。
①アプリやパッケージをpip経由で本番環境にインストール
さて、準備に時間がかかりましたが、ようやく本番環境デプロイになります。
まずは作成したDjangoアプリで使用しているアプリやパッケージを本番環境にもインストールします。
Djangoから始めて、全てインストールしてください。
仮想環境を作成している場合は、仮想環境に入ったあとにインストールしましょう。
すべてインストールした後は、以下のコマンドで一覧を出して、開発環境と見比べると良いでしょう。
②サブドメイン配下にプロジェクトをコピーする
サブドメインのルートディレクトリに移動し、Djangoプロジェクトをコピーします。
Gitで同期しても良いですし、プロジェクトとアプリを作成した後にファイルをコピーしても構いません。
ただどちらの場合も、同期(コピー)しないものには注意してください。
例えばdjango-environで作成した「.env」ファイルなどは同期、コピーしないようにしましょう。
③index.cgiおよび.htaccessを作成する
Djangoアプリを起動する「manage.py」ファイルと同じ階層に、「index.cgi」と「.htaccess」というファイルを作成します。
それぞれの記述は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 |
import sys, os,site site.addsitedir("/home/[サーバー名]/miniconda3/envs/django-env/lib/python3.9/site-packages") sys.path.insert(0, "/home/[サーバー名]/miniconda3/envs/django-env/bin") os.environ['DJANGO_SETTINGS_MODULE'] = "[アプリ名].settings" from wsgiref.handlers import CGIHandler from django.core.wsgi import get_wsgi_application application = get_wsgi_application() CGIHandler().run(application) |
miniconda3以降は仮想環境のパスですので、実際にレンタルサーバー上のフォルダと合わせてください。
上記はdjango-envという仮想環境を作成したことを想定しています。
またindex.cgiのパーミッションは755に変更しておいてください。
1 2 3 4 5 6 7 |
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /[アプリ名]/index.cgi/$1 [QSA,L] RewriteEngine On RewriteCond %{HTTPS} !on RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] |
.htaccessはアプリ名の部分だけ気を付けてください。
同じフォルダ内にある、先ほど作成したindex.cgiを参照してくれるように設定しましょう。
④必要があればsettingsのURL関連を修正する
本番環境で画像やCSSの参照が上手くいかない場合があります。
画像やCSSが参照しているURLにDjangoのプロジェクト名がないことが原因です。
settings.pyの以下の値を確認し、先頭にプロジェクト名をつけてあげてください。
- STATIC_URL
- MEDIA_URL
⑤Viewの、月日のクエリを見直す(MySQLのみ)
本番環境によってはViewの日付関連のfilterが正常に動作しない場合があります。
CONVERT_TZという関数があるのですが、これを内部的に使用しない方法へとコーディングを行うことで対応可能です。
主にDjangoによるFilterではなく、Pythonのクエリ作成を使えば成功するケースが多いです。
なぜ月と日付関連で上手く絞り込みが出来ないのかは次で説明します。(興味がない方は読み飛ばしてください)
EX:レンタルサーバーでMySQLを使用している場合の月日取得エラーについて
Djangoのfilterで月や日付を指定する場合、以下のように簡単に指定することが可能です。
この処理では対象のデータベースがMySQLの場合、内部的にCONVERT_TZという関数が使われていて、mysqlデータベースにあるtimezoneというテーブルを参照しています。
しかしレンタルサーバーによってはこのtimezoneテーブルが存在しないことがあり、そうなると正常な値が取れないために、クエリ結果が空になることがあります。
さらにレンタルサーバーの場合はmysqlデータベースにアクセスする権限が与えられていないために、timezoneテーブルを作成することもできません。
それゆえに、CONVERT_TZを使用しない月や日の絞り込み方法に切り替える必要があります。
(年に関してはCONVERT_TZ関数が使用されていないために、問題なく絞り込みができます)
おわりに
レンタルサーバー上にDjangoアプリを公開すると、ランニングコストが低いのがメリットです。
ただその分、公開の敷居は少し高くなりますね。
AWSなどのクラウドサーバーならば仮想環境を入れる必要はありませんし、MySQLのCONVERT_TZで苦労することもないと思います。
けれどレンタルサーバーでも公開まで漕ぎつけてしまえばあとの管理は意外と楽だったりします。