NGINX UnitでDjangoアプリケーションを動かしてみる

NGINX Unitは、NGINXの開発元が作ってるアプリケーションサーバー。

http://unit.nginx.org/

Pythonのアプリケーションも動かせるとのことなので、Djangoアプリで試してた。

試した環境は、Vagrant上でUbuntu 16.04 LTS、Python 3.6.2(deadsnakes PPA)、Django 2.0.4、NGINX UnitはGithubのmaster(749f7c0)

インストール

ドキュメント通りだとPython3.6用のモジュールが提供されないので、ビルドしてインストールした。

python3.6やpython3.6-develなどはdeadsnakes PPAからインストール済み。

インストール先は、 /opt/unit/ としました。

git clone https://github.com/nginx/unit.git
cd unit
./configure
./configure python --config=python3.6-config
make all
sudo make install DESTDIR=/opt/unit/

※参考にしたページには、virtualenvに対応するためにパッチを当てる旨の記載があったが、masterで問題が修正されたので特に変更なしで動いた。

unitdの起動

オプション指定なしだと起動時のカレントディレクトリにログファイル unit.log が作成される。また、カレントディレクトリから相対パスで拡張モジュールを探しにいくので、 --module で指定したほうがよさそう。

今回はUbuntuへのログイン時のユーザー vagrant で起動してみる。

cd /home/vagrant/
/opt/unit/sbin/unitd --modules /opt/unit/build/

これで、unitdが起動し、API経由で設定を投入できる状態になった。

Djangoのアプリケーションを用意する

「Hello, World!」と表示するだけなので手抜きで。

cd /home/vagrant/
python3.6 -m venv venv
. venv/bin/activate
django-admin startproject myproject

myproject/myproject/settings.py(変更部分):

ALLOWED_HOSTS = ['*']  # ホスト側のブラウザから確認したかったので設定

myproject/myproject/urls.py:

from django.urls import path
from django.http import HttpResponse

def index(request):
    return HttpResponse('Hello, World!')

urlpatterns = [
    path('', index),
]

設定の投入

curlで投入してみるので、設定をファイルで用意する。

myproject.json:

{
    "listeners": {
        "*:8000": {
            "application": "myproject"
        }
    },
    "applications": {
        "myproject": {
            "type": "python 3.6",
            "processes": 1,
            "path": "/home/vagrant/myproject/",
            "home": "/home/vagrant/venv/",
            "module": "myproject.wsgi"
        }
    }
}

home キーの値にvenvのディレクトリを指定するが、末尾にスラッシュがないとエラーになった。ソースを確認したところ、よしなにしてくれない。

設定の投入が問題なければ、レスポンスは正常終了の旨が返される。

$ curl -X PUT -d @./myproject.json --unix-socket ./control.unit.sock 'http://localahost/'
{
        "success": "Reconfiguration done."
}

Webブラウザで 8000 ポートを確認し、「Hello, World!」と表示されればOK。

感想

  • NGINX Unitは動的に設定を投入できることが特徴ということだが、現状ではそれ以外にあまり利点がないので、gunicornやuWSGIで事足りる場合は、そちらを使ったほうが良さそう。
    • 無停止でワーカープロセス数を増やすぐらいならgunicornやuWSGIでも可能
  • 1つのホストでUnit経由で複数のアプリケーションをホストするにしても、リソース制御などがほしくなるから、Dockerか何かコンテナに対応してないと使いづらいか...
    • その用途なら今だとdocker-composeで事足りそうな気も。
    • クラスタ化して使えるようになったとしても、それはk8sでよいような気もするし..
  • NGINX Controllerで制御する自前のプロダクトということでUnitを作っているのかな?
  • HTTP/2のルーティングに対応するなら、NGINXとの組み合わせでオーバーヘッドが減るかも?
  • アプリケーションのプロセスは、killしても自動で再起動されてた

参考