はじめに
この記事は JSL (日本システム技研) Advent Calendar 2020 - Qiita 24日目の記事です。
先日のアドベントカレンダー記事で、年一回のノルマは達成したものの、記録への挑戦をしたい年頃のため以前より興味のあったnginx unit
について書きました。
nginx unitとは
ざっくり言うと、以下のような特徴があります(公式ページ)。
- NGINX社製のアプリケーションサーバーです。
- 多言語対応したアプリケーションサーバーです。
- Go、Node.js、Perl、PHP、Python、Ruby
- 言語の異なるバージョンでも共存可能
- REST API経由でサーバー無停止で設定変更が可能です。
今回のゴール
- EC2(Amazon Linux2)に
nginx unit
をインストールしてDjangoアプリケーションのデプロイするまでを書きます。
書かないこと
- Djangoアプリケーションの一般的な環境設定のこと
-
uWSGI
やGunicorn
との比較
各種バージョン
- Amazon Linux2
- Python 3.7.9
- Django 3.1.1
- MariaDB 15.1
- Nginx Unit 1.21.0
インストール
公式ページを確認しながら進めます。
/etc/yum.repos.d/unit.repo
を作成し、リポジトリの追加をします。
[unit]
name=unit repo
baseurl=https://packages.nginx.org/unit/amzn2/$releasever/$basearch/
gpgcheck=0
enabled=1
# nginx unitのインストール
$ sudo yum install unit
# 必要なモジュールをインストール
$ sudo yum install unit-devel unit-python37
# 自動起動の設定
$ sudo systemctl enable unit
# nginx unitの起動
$ sudo systemctl start unit
# helpオプションで各設定のデフォルト値の確認ができます。
$ unitd --help
unit options:
--version print unit version and configure options
--no-daemon run unit in non-daemon mode
--control ADDRESS set address of control API socket
default: "unix:/var/run/unit/control.sock"
--pid FILE set pid filename
default: "/var/run/unit/unit.pid"
--log FILE set log filename
default: "/var/log/unit/unit.log"
--modules DIRECTORY set modules directory name
default: "/usr/lib64/unit/modules"
--state DIRECTORY set state directory name
default: "/var/lib/unit"
--tmp DIRECTORY set tmp directory name
default: "/var/tmp"
--user USER set non-privileged processes to run as specified user
default: "nobody"
--group GROUP set non-privileged processes to run as specified group
default: user's primary group
環境の確認
nginx unit
は、REST API経由で環境確認や設定を行います。
$ sudo curl --unix-socket /var/run/unit/control.sock http://localhost/
{
"certificates": {},
"config": {
"listeners": {},
"applications": {}
}
}
現状は、なにも設定されていない状態です。
Djangoアプリケーションのデプロイ
Djangoアプリケーションのデプロイも公式ページに沿って進めます。
デプロイ先を/var/www
配下と想定して設定用ファイル(config.json)を作成します。
config.jsonの格納先は悩みましたが、今回はDjangoアプリケーション配下に置くようにしました。
{
"listeners": {
"*:80": {
"pass": "routes"
}
},
"routes": [
{
"match": {
"uri": "/static/*"
},
"action": {
"share": "/var/www/my_djangoapp/"
}
},
{
"action": {
"pass": "applications/django"
}
}
],
"applications": {
"django": {
"type": "python 3.7",
"user": "ec2-user",
"group": "ec2-user",
"path": "/var/www/my_djangoapp/",
"home": "/var/www/my_djangoapp/env/",
"module": "my_djangoapp.wsgi",
}
}
}
以下のようにconfig.json
を適用します。
$ sudo curl -X PUT --data-binary @config.json --unix-socket /var/run/unit/control.sock http://localhost/config/
{
"success": "Reconfiguration done."
}
以上でnginx unit
の設定は終了です。Djangoアプリケーションのmigrate
なり、collectstatic
をして環境と整えることは別途必要です。
設定上のポイント
-
config.jsonの
type
で指定する名称は、--modules
で指定しているディレクトリのモジュール名を指定するのですが、バージョンの間に空白を入れる必要があるようです。 -
Djangoアプリケーションのディレクトリは、config.jsonで指定する
user
とgroup
で指定した値で適切に所有権を設定してあげる必要があります。
所感
-
マイクロサービスで複数の言語やバージョンを扱うWebアプリケーションを運用する場合は、
nginx unit
のみで保守運用出来そうなため選択肢の一つとして検討しても良いように思いました。 -
REST API経由での設定は新鮮ではあったが、調査範囲では構文チェックする機能が見当たらずログファイルを確認しながらエラーチェックをするのが少々厳しかったです。
-
PythonのみWebアプリケーションを想定している場合は、
uWSGI
やGunicorn
でも充分かなと思いました。