衝動的にLightsailとDjangoでWebサイトを作る その4
前回からの続き。
構成(再掲)
- レンタルサーバー:AWS Lightsail
- OS:Ubuntu 20.04.2
- データベース:MySQL 8.0.25
- サーバーソフト:Apache 2.4.41
- 言語:Python 3.8.5
- フレームワーク:Django 3.2.2
- ドメイン取得:AWS Route 53
- 構成(再掲)
- Apacheとmod_wsgiとDjangoを連携させる
- Apacheとmod_wsgiとDjangoを連携したつもりが動かない
- Pythonの仮想環境を構築する
- Apacheとmod_wsgiとDjangoを連携できた
- 続く
Apacheとmod_wsgiとDjangoを連携させる
サーバーの/etc/apache2/sites-availableに新しく.confファイルを作成し、公開のための設定を書き込む。
サーバーへのファイルのアップロードはWinSCPを使って行っていたが、/etc/apache2/sites-availableはアクセス権の問題でファイルの書き込みができなかったので、/home/ubuntuに一度アップロードしてからsudo mvで移動させることにした。(不用意に外部からのアクセスを許可したくなかったため)
.confファイル作成に必要なパスは、いちいち自分で確認せずとも、mod_wsgi-express module-configを実行すると出力してくれる。
Apacheとmod_wsgiとDjangoを連携したつもりが動かない
上述のページ等で入手した情報を参考に設定を行い、Djangoプロジェクトをサーバーにデプロイしたが、実際にブラウザにIPを入力して接続を試した段階でInternalErrorが発生。
/var/log/apache2内にログファイルが残されているので、確認すると以下のエラーが発生していた。
#IPなど一部情報は削除しています [mpm_event:notice] AH00489: Apache/2.4.41 (Ubuntu) configured -- resuming normal operations [core:notice] AH00094: Command line: '/usr/sbin/apache2' [mpm_event:notice] AH00493: SIGUSR1 received. Doing graceful restart [mpm_event:notice] AH00489: Apache/2.4.41 (Ubuntu) mod_wsgi/4.7.1 Python/3.8 configured -- resuming normal operations [core:notice] AH00094: Command line: '/usr/sbin/apache2' [wsgi:error] mod_wsgi (pid=): Failed to exec Python script file '/home/ubuntu/uma/musu/me/wsgi.py'. [wsgi:error] mod_wsgi (pid=): Exception occurred processing WSGI script '/home/ubuntu/uma/musu/me/wsgi.py'. [wsgi:error] Traceback (most recent call last): [wsgi:error] File "/home/ubuntu/uma/musu/me/wsgi.py", line 12, in <module> [wsgi:error] from django.core.wsgi import get_wsgi_application [wsgi:error] ModuleNotFoundError: No module named 'django'
エラーを見ると、wsgi.pyでDjangoをインポートしようとしたときに、Djangoが見つけられずエラーが発生しているみたいなので、これを何とかしようと考えた。
各パッケージがサーバー上のどこにあるのか確認してみると、mod_wsgiだけ/usr/local/lib/python3.8/dist-packagesにインストールされていることが分かった。djangoや他のパッケージは/home/ubuntu/.local/lib/python3.8/site-packagesに入っている。
なんだこれという感じだが、どうもDebian パッケージからインストールされたサードパーティの Python ソフトウェアは、site-packages ではなく dist-packages に入るらしい。
正直よくわからない。
全てpipでインストールしたはずなのに、何故別のフォルダに分かれてしまったのか理由は不明。ただ、作成した.confファイルでWSGIPythonHomeとして/usr/lib/python3.8を指定していること、djangoが/usr/配下とは全く別の/home/配下のディレクトリに存在することが影響しているのではないかと予想した。
そこで、必要なパッケージ全てをsite-pakagesにまとめられればDjangoが見つからない事態は防げるかも…と考えたのだが、さらに調べてみるとそもそもUbuntuにプリインストールされているPythonはOS自体の機能で利用されるものらしく、安定性を損なう可能性もあることからパッケージをインストールなどしない方がいいらしい、ということを知った(今更)。
実は今まで仮想環境を構築せず、Ubuntuに元から入っていたPythonをそのまま使って動かそうとしていた。
上述の参考資料も、仮想環境でPythonが用意されている前提の内容だったため、書かれている通り真似をしていないのだからエラーが出ても当たり前といえば当たり前ではある。しかし、パスの設定等を正しくできれば、仮想環境じゃなくても動くんじゃないかと思い試行錯誤していた。
書いてあることをそのまま真似するだけでなく、色々弄って試してみることも時には大事だと思う。
(最終的には、そもそもプリインストールされたPythonは弄らないほうがいいと知ってしまったため、おとなしく仮想環境を構築して動かすことになったが…。 )
とはいえ仮想環境ならDjangoもmod_wsgiも同じディレクトリに入ってくれてきっとすんなり動くはず。
Pythonの仮想環境を構築する
仮想環境の構築にはvenvを用いる。venvはPython3の標準ライブラリで、pipでインストールしたパッケージのバージョン分けが可能。仮想環境AにはDjango3.2が入っていて、 仮想環境BにはDjango3.0が入っているみたいなことができる。(仮想環境を使わない場合はどれか1つのバージョンしかインストールできない。)
環境の切り分けができるので、プロジェクトAのために入れたパッケージがプロジェクトBのために使いたいパッケージと干渉してしまう、といったことも防ぐことができる。
仮想環境を有効にすると、「python」コマンドを実行したとき、仮想環境のpythonが実行されるようになる。仮想環境に導入したライブラリは全て仮想環境のディレクトリ内で管理される。
Apacheとmod_wsgiとDjangoを連携できた
仮想環境を作成し、Django、mod_wsgi、mysqlclientを導入。
mod_wsgi-express module-configを実行した結果は以下の通り。
#パスの一部をマスクしています LoadModule wsgi_module "/home/ubuntu/.../venv/lib/python3.8/site-packages/mod_wsgi/server/mod_wsgi-py38.cpython-38-x86_64-linux-gnu.so" WSGIPythonHome "/home/ubuntu/.../venv"
.confファイルを上の通り変更して実行すると、module XXX(デプロイしたいプロジェクト)が無いと言われたので、改めてチュートリアル通りにWSGIPythonPathを設定し直した。
WSGIPythonPathは、指定したパスによってimport mysiteの状態になるように設定する。例えば/home/ubuntu/に配置したgundamというプロジェクトをデプロイする場合は、WSGIPythonPathに/home/ubuntu/gundamを指定する。
これで無事ページが表示されるようになった。
続く
本日はここまで。あと1~2回で多分終わる予定。