Djangoを本番環境へデプロイ
Djangoのwebアプリケーションを開発し、いよいよ本番環境にデプロイ!というフェーズになった時、詰まることはたくさんあると思います。
あくまで私の主観ですが、Djangoは他の言語やフレームワークに比べて若干本番の環境構築など手順は多めだと思います。
備忘録として手順を残しましたので、参考にしていただければと思います。
バージョン情報は以下
Python 2.7.10
Django 1.9.6
CentOS 6.8
Apache 2.2.15
※サーバ操作はすべてrootユーザで行ってます。
本番環境設定手順
Apache関係の必要モジュールのインストール
まずは、Apacheなど必要モジュールをyumでインストールして起動させます。
yum -y install httpd httpd-devel mod_wsgi service httpd start
ここでmod_wsgiというちょっと見慣れないモジュールが出てきましたが、これはApacheでWSGIを動作させるためのモジュールです。
そもそもWSGIって何?と思われる方もいるかもしれませんが、こちらはWeb Server Gateway Interface (ウィズギー)の略で、PythonのWebアプリケーションとWebサーバを接続するためのインターフェースです。
簡単に言えば、ApacheでPythonのアプリケーションを動かすためにはこのモジュールが間になければいけません。
ちなみにDjangoではプロジェクトを作成した段階で、デフォルトでwsgi.pyというファイルが作成されます。
のちほどそのファイルも修正を加えることになりますが、WSGIはApacheとの接続に必要なモジュールであるということを意識して手順を進めてください。
続いてchkconfigでApacheの自動起動設定もしておきましょう。
chkconfig httpd on chkconfig --list | grep httpd
※httpd.confの細かい設定は省きますので、必要に応じて適宜行ってください。
今回は必要最小限の設定になりますので、httpd.confは特に何も設定をしなくても大丈夫です。
WSGIの設定
以下の手順を行う前に、まずはGitやFTPを使用してDjangoのプロジェクトファイルを「/var/www/cgi-bin/」直下に配置してください。
続いて、前回までの手順でmod_wsgiをインストールしているため、「/etc/httpd/conf.d/wsgi.conf」というWSGIの設定ファイルが作成されています。
このファイルを修正しましょう。
vim /etc/httpd/conf.d/wsgi.conf
LoadModule wsgi_module modules/mod_wsgi.so # プロジェクトのwsgi.pyのパスに合わせて設定 WSGIScriptAlias / /var/www/cgi-bin/testdir1/testdir2/wsgi.py # Directoryはプロジェクトのパスに合わせてください <Directory /var/www/cgi-bin/testdir1/testdir2> Order deny,allow Allow from all </Directory>
Pythonのバージョンアップ
元々CentOSのサーバにはPythonの2.6.6が入っていたので、2.7.10を読み込むように設定します。
一応元のバージョンを確認してください。
python --version Python 2.6.6
新バージョンをインストールします。
cd /usr/src curl -O https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz tar zxf Python-2.7.10.tgz
展開してインストールします。
cd Python-2.7.10 ./configure make & make altinstall
そして元のバージョンをバックアップして置き換えましょう。
mv /usr/bin/python /usr/bin/python2.6.6 cp /usr/local/src/Python-2.7.10/python /usr/bin/python
そしてyumのファイルも変える必要があります。
vim /usr/bin/yum
先頭の行を以下のようにしてください。
#!/usr/bin/python2.6.6
そしてバージョンを確認します。
python --version Python 2.7.10
これでバージョンアップは完了です。
結構手間がかかりましたね。
pipとvirtualenv
次にpipとvirtualenvのインストールです。
easy_install pip pip install virtualenv virtualenv ENV1 cd ENV1 . bin/activate
これでENV1環境に入れるはずなので、次にDjangoのインストールです。
pip install django==1.9.6
virtualenvのPythonを参照させる
次に「wsgi.py」を書き換えて、virtualenvのPythonを参照するようにします。
vim /var/www/cgi-bin/testdir1/testdir2(プロジェクトのパスに合わせてください)/wsgi.py
import os try: from local_wsgi import * except ImportError: import site import sys site.addsitedir("/root/ENV1/lib/python2.7/site-packages") sys.path.append('/var/www/cgi-bin/testdir1(ご自身のdjangoのパスに合わせてください)') sys.path.append('/var/www/cgi-bin/testdir1/testdir2(ご自身のdjangoのパスに合わせてください)') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "プロジェクト名.settings") activate_env = os.path.expanduser("/root/ENV1/bin/activate_this.py") execfile(activate_env, dict(__file__=activate_env)) from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "プロジェクト名.settings") application = get_wsgi_application()
※上記は開発環境と本番環境でPythonの読み込み先を変えるようにしています。
開発環境だけlocal_wsgiという空ファイルを作り、ファイルが存在していれば何もせず、存在しない場合はPythonの読み込み先を変えるようにしています。
ブラウザにアクセス、そして迷走
さあ、Apacheを再起動してブラウザにアクセスしてみましょう。
service httpd restart
...これでブラウザにアクセスすると、残念ながらApacheのエラーが出ると思います。
エラー内容を見てみましょう。
「/var/log/httpd/error_log」に記載があります。
mod_wsgi (pid=28251): Target WSGI script '/var/www/cgi-bin/test1/test2/wsgi.py' cannot be loaded as Python module. mod_wsgi (pid=28251): Exception occurred processing WSGI script '/var/www/cgi-bin/test1/test2/wsgi.py'. Traceback (most recent call last): File "/var/www/cgi-bin/test1/test2/wsgi.py", line 22, in <module> execfile(activate_env, dict(__file__=activate_env)) IOError: [Errno 13] Permission denied: '/root/ENV1/bin/activate_this.py'
どうやら「/root/ENV1/bin/activate_this.py」に権限がないらしい。
色々試して「activate_this.py」にだけ755権限の権限を与えてもダメでした。
ディレクトリごとに権限を与える必要があるようです。
やりたくないですがrootに755の権限を与えてみました。
root直下に作らなきゃよかったな...
chmod 755 /root
再度アクセスするとまたエラーが...
今度のエラー内容は下記のものでした。
mod_wsgi (pid=28294): Target WSGI script '/var/www/cgi-bin/test1/test2/wsgi.py' cannot be loaded as Python module. mod_wsgi (pid=28294): Exception occurred processing WSGI script '/var/www/cgi-bin/test1/test2/wsgi.py'. Traceback (most recent call last): File "/var/www/cgi-bin/test1/test2/wsgi.py", line 25, in <module> from django.core.wsgi import get_wsgi_application File "/root/ENV1/lib/python2.7/site-packages/django/__init__.py", line 1, in <module> from django.utils.version import get_version File "/root/ENV1/lib/python2.7/site-packages/django/utils/version.py", line 7, in <module> from django.utils.lru_cache import lru_cache File "/root/ENV1/lib/python2.7/site-packages/django/utils/lru_cache.py", line 28 fasttypes = {int, str, frozenset, type(None)}, ^ SyntaxError: invalid syntax
シンタックスエラーが出ているのですが、これはPythonのバージョンが2.7でない時に発生するようです。
あれ?ちゃんと2.7を読み込んでるはずなのになんでろう...
本当に2.6の方を読み込んでるの?と疑問に思い、Djangoのソースコードに以下の一文を入れました。
print(sys.version_info)
「wsgi.py」に入れると良いと思います。
これで実行し、再度エラーログを見ると以下の一文が...
[error] (2, 6, 6, 'final', 0)
確かに旧バージョンを読み込んでいました。
「mod_wsgi」が旧バージョンの方を見ているらしく、再度コンパイルをしても直らず...
こちらの対応が一番時間がかかりました。
結果的には一度mod_wsgiをアンインストールし、再度入れ直してコンパイルすることで直りました。
ではmod_wsgiをアンインストールします。
yum remove mod_wsgi
この時点で「/etc/httpd/conf.d/wsgi.conf」は「/etc/httpd/conf.d/wsgi.conf.rpmsave」に変更されます。
mod_wsgiをインストールして展開してください。
cd /usr/src wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.2.8.tar.gz -O mod_wsgi-4.2.8.tar.gz tar xzf mod_wsgi-4.2.8.tar.gz cd mod_wsgi-4.2.8 ./configure --with-python=/usr/local/bin/python2.7 make & make install
コンパイルが終わったら、
wsgi.confを元に戻しましょう。
cd /etc/httpd/conf.d/ cp wsgi.conf.rpmsave wsgi.conf
これでブラウザにアクセスすると、また別なエラーが!
「Bad Request (400)」と表示されます。
あと一息。
settings.pyのALLOWED_HOSTSでアクセス制限をかけていないでしょうか。
もしかけている場合は、
ALLOWED_HOSTS = ['ドメイン名']
としてみてください。
私はそれで上手く表示されました。
まとめ
いやー、サーバで表示させるだけで大変でした。
まだDjangoは静的ファイルの扱いとかデータベースの設定もあるのに最初にこんなに詰まるとは。
本番環境へのデプロイで詰まった場合、以下の点を確認すると大抵うまくいくと思います。
- 仮想環境(virtualenv)を用意した場合、プロジェクトのWSGIがvirtualenvを向いているか
- サーバのPythonのバージョンを変えた場合、プロジェクトが新バージョンを向いているか
- プロジェクトが設置されているディレクトリに読み込み可能な権限が付加されているか
でもまぁ、Djangoの実行の流れはわかったから今後は大丈夫かな。
- 作者: 関根裕紀,新井正貴
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2019/05/07
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
Python3 + Django2.0入門 - Pythonで作るWebアプリケーション開発入門 - その1(第二版)
- 作者: ナカノヒトシ
- 発売日: 2018/07/12
- メディア: Kindle版
- この商品を含むブログを見る