ConoHaのVPSで複数のDjangoアプリを動かす

# はじめに
 
パワプロ2020楽しいですね！[^1]


以前、Djangoで[栄冠ナインデータベース](https://note.com/shimayu22/n/n3a320a86a915)を作成しました。
アプリの特性上、Djangoの開発用サーバーで実行してもいいのですが、今は[ConoHaのVPS](https://www.conoha.jp/vps/)に置いています。
Herokuは早々にレコード数が上限に達しました。


[栄冠ナインデータベース](https://note.com/shimayu22/n/n3a320a86a915)ですが、栄冠ナインの周回プレイは考慮しておらず[^2]その場合はもうひとつVPSを用意しようかと思いましたが、一番安いプランのリソースですら余っているので一つのVPS内に二つのDjangoアプリ[^3]を入れればええやん？ってなりましたが意外と苦戦しました。

[Eikan-Database](https://github.com/shimayu22/Eikan-Database)
 
[^1]: 時候の挨拶
[^2]: 私を含めごくわずかなプレイヤーしかしないだろうし
[^3]: 今回は同一のアプリですが

# ConoHaのVPSとは
[公式](https://www.conoha.jp/vps/)

## 今回の環境

※2020/9/24現在

- メモリ 512MB/CPU 1Core
- Djangoテンプレート
    - CentOS 7.7
    - Apache 2.4.6
    - Python 3.6.8
    - mod_wsgi
 
 
# ConoHaのVPSでDjangoアプリを動かす

まず、コードを`/home/django/`に格納します。
Djangoテンプレートを使用した場合、単純にソースを`/home/django/`配下に配置し、/etc/httpd/conf/httpd.confを以下のように変更することで使えます。


```/etc/httpd/conf/httpd.conf（元の状態）
# ファイルの一番下

WSGIScriptAlias / /home/django/sample/sample/wsgi.py
WSGIPythonPath /home/django/sample

<Directory /usr/lib64/python3.6/site-packages/django/contrib/admin/static>
  Require all granted
</Directory>

<Directory /home/django/sample/sample>
  <Files wsgi.py>
    Require all granted
  </Files>
</Directory>
```


```/etc/httpd/conf/httpd.conf（変更後）

# /home/django/sample/sample/wsgi.pyの部分を自分のアプリのwsgi.pyへのパスに変更する
WSGIScriptAlias / /home/django/eikan-database/config/wsgi.py

# 同様に自分のアプリのフォルダに変更する
WSGIPythonPath /home/django/eikan-database

# 変更なし
<Directory /usr/lib64/python3.6/site-packages/django/contrib/admin/static>
  Require all granted
</Directory>

# wsgi.pyが入っているフォルダのパスに変更する
<Directory /home/django/eikan-database/config>
  <Files wsgi.py>
    Require all granted
  </Files>
</Directory>
``` 

最初からsample用の設定を書き換えることであっさりDjangoアプリが使えるようになります[^4]。

[^4]: データベースの設定とか使用するパッケージのインストールとかhttpsの設定とかは別途必要ですが...

 
# ConoHaのVPSで複数のDjangoアプリを動かす

## つまずきポイント

ConoHaのVPSのDjangoテンプレートではApache + mod_wsgiを使っています。
この環境で複数のDjangoアプリを動かそうとググるとすぐ出るのは、WSGIPythonPathを`:`で繋げる方法ですが、この方法ではできませんでした。

[WSGIDaemonProcess](https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html)を見てみると、デフォルトは`%{GLOBAL}`となっていて２つ以上のDjangoアプリが入っていると、実行時に全部一緒のプロセスになるため、WSGIPythonPathだけを変更してもプロセスが上書きされて同時に複数のDjangoアプリを実行することができないっぽいです。

WSGIDaemonProcessおよびWSGIProcessGroupを分けてあげることによって、mod_wsgi環境で複数のDjangoアプリを実行することができます。


## ディレクトリ型の場合

同じように、もう一つのアプリを`/home/django/`に格納します。

今回は`eikan-database`と`eikan-database-2`としています。
※sampleはもともと存在するやつ

```
/home/django
├── eikan-database
├── eikan-database-2
└── sample
```

また、この例ではパワプロ2016の栄冠ナイン３周目用のアプリを/201603、
パワプロ２０２０の栄冠ナイン１周目用のアプリを/202001としています。
こんな感じ↓

- [https://endb.shimay.uno/201603](https://endb.shimay.uno/201603)
- [https://endb.shimay.uno/202001](https://endb.shimay.uno/202001)


/etc/httpd/conf/httpd.confを以下のようにする
 
```/etc/httpd/conf/httpd.conf

# WSGIDaemonProcessのすぐ後ろは任意の名前でおk
# python-pathはそれぞれのアプリのフォルダを指定する
WSGIDaemonProcess endb201603 python-path=/home/django/eikan-database
WSGIDaemonProcess endb202001 python-path=/home/django/eikan-database-2

# WSGIDaemonProcessで指定した名前を指定する
# WSGIProcessGroup %{ENV:PROCESS_GROUP}とすると、プロセスグループ名は、指定された環境変数の値に設定されます。
SetENV PROCESS_GROUP endb201603
WSGIProcessGroup %{ENV:PROCESS_GROUP}

# このアプリのルートディレクトリを/201603とする
WSGIScriptAlias /201603 /home/django/eikan-database/config/wsgi.py
<Directory /home/django/eikan-database/config>
  <Files wsgi.py>
    Order deny,allow
    Allow from all
    Require all granted
  </Files>
</Directory>

# このアプリのルートディレクトリを/202001とする
WSGIScriptAlias /202001 /home/django/eikan-database-2/config/wsgi.py
<Directory /home/django/eikan-database-2/config>
  <Files wsgi.py>
    SetENV PROCESS_GROUP endb202001
    Order deny,allow
    Allow from all
    Require all granted
  </Files>
</Directory> 
```

こうしておけばこのまま周回を重ねても簡単に増やしていけますね。

`/var/www/html`にhtmlファイルを入れて、
[https://endb.shimay.uno/](https://endb.shimay.uno/)
のような感じにリンクを貼っておけば切り替えも楽々。[^5]

[^5]: 自分しか使わないのでクッソ雑なページですが。

サブドメイン型もたぶんこういう感じでプロセス分けてやればいいのかな・・・？（未検証）

 
# 終わりに

最初からNginx + uWSGIでやった方が早かったのでは・・・？:thinking: 
もしくはアプリ側でユーザー切り替えとか周回プレイを考慮した作りにしておけば・・・？:thinking: 
Docker使うとか・・・？:thinking:
VPS使わずローカルで開発用サーバーで動かすとか・・・？

# 参考
- https://mowa-net.jp/wiki/Django
- [WSGIDaemonProcess](https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html)
- [WSGIProcessGroup](https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIProcessGroup.html)
- [WSGIScriptAlias](https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIScriptAlias.html)