NGINX Unitのインストール・設定手順【PythonでWebアプリを動かす】

NGINX Unitのインストール・設定手順【PythonでWebアプリを動かす】 プログラミング

この記事では、NGINX Unitのインストール・設定手順をまとめています。

本記事の内容

  • NGINX Unitをインストールする前に
  • NGINX Unitのインストール環境
  • NGINX Unitのインストール
  • NGINX Unitの設定
  • 残された課題

それでは、上記に沿ってNGINX Unitをインストールしていきます。

NGINX Unitをインストールする前に

PythonでWebアプリを動かすには、次の記事が参考になります。

上記記事の内容を簡単に言うと、Webサーバーとアプリケーションサーバーの話です。
「Webサーバーは、ApacheではなくNginxを使っていきましょう」
「アプリケーションサーバーは、何個か候補があります」

この記事では、NGINX Unitをアプリケーションサーバーとして選んでいます。
そして、インストールするという流れです。

NGINX Unitのインストール環境

インストールに関係のあるモノは以下。

  • Ubuntu 18.04
  • Nginx 1.14.0
  • NGINX Unit 1.20.0

Linuxでのインストール作業は、OSと各バージョンには注意が必要です。
同じディストリビューションであれば、それほど問題になりません。

しかし、CentOSとUbuntuでは、かなり異なります。
そのため、ディストリビューションには特に注意してください。

Ubuntu 18.04

OSのバージョン確認です。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"

利用可能な最新(安定版)バージョンは、 ‎Ubuntu 20.04です。
でも、利用しているVPSでは、Ubuntu 18.04までしか選択できませんでした。

まあ、月額349円という格安なので全く文句はありません。
格安VPSの契約から利用までについては、次の記事で解説しています。

Nginx 1.14.0

Nginxのバージョン確認です。

$ nginx -V
nginx version: nginx/1.14.0 (Ubuntu)

Nginxのインストールに関しては、次の記事で解説しています。

NGINX Unit 1.20.0

2020年の10月8日に公開されたばかりです。
Nginx同様、もちろんオープンソースとなります。

対応言語は以下。

  • Assembly
  • Go
  • JavaScript(Node.js)
  • Java
  • Perl
  • PHP
  • Python
  • Ruby

対応と言っても、すべてが組み込んであるわけではありません。
利用するためには、何かしらのインストールや設定が必要になります。

なお、Pythonに関しては以下のように表記されています。

Python: via WSGI and ASGI 3.0 with WebSocket support

では、NGINX Unitをインストールしていきます。

NGINX Unitのインストール

公式サイトのインストール手順
https://unit.nginx.org/installation/

上記の参考にして、インストールを行ないます。

インストール

いつもの感じでsudoで。

$ sudo curl -sL https://nginx.org/keys/nginx_signing.key | apt-key add -

でも、これは失敗します。

E: This command can only be used by root.
(23) Failed writing body

仕方がないので、rootになります。

$ sudo su

では、気を取り直して。

# curl -sL https://nginx.org/keys/nginx_signing.key | apt-key add -
OK

次に、NGINX Unitインストールに必要な情報をリポジトリ追加します。
ただし、/etc/apt/sources.listに追記する形ではありません。

公式では、/etc/apt/sources.list.dの下に「unit.list」を作成します。
そのファイルの内容は以下。

deb https://packages.nginx.org/unit/ubuntu/ bionic unit
deb-src https://packages.nginx.org/unit/ubuntu/ bionic unit

結果的には、次のようになればOKです。

# cat /etc/apt/sources.list.d/unit.list           
deb https://packages.nginx.org/unit/ubuntu/ bionic unit
deb-src https://packages.nginx.org/unit/ubuntu/ bionic unit

いざ、インストールコマンドですね。
パッケージを更新してからのインストールです。

# apt update
# apt install unit
# apt install unit-dev unit-go unit-jsc8 unit-jsc11 unit-perl unit-php unit-python2.7 unit-python3.6 unit-python3.7 unit-ruby

利用予定の言語のパッケージだけを選択するようにと記載されています。
今回であれば、Pythonです。
よって、「unit-python2.7 unit-python3.6 unit-python3.7」を選択すればOK。

個人的には、他の言語も機会があれば動かしてみたいと考えています。
そのため、他言語のパッケージもインストールしています。

その辺りの判断はご自由に。
ただし、本番環境では一つだけ「unit-python3.6」 とバージョンまで絞り込んでインストールします。
本番環境ではできる限りで、無駄なモノはインストールしたくありません。

確認

パッケージからインストールした場合は、自動で起動しているようです。
そのように公式サイトには、記載されています。

起動状況を確認します。

$ systemctl status unit
● unit.service - NGINX Unit
   Loaded: loaded (/lib/systemd/system/unit.service; disabled; vendor preset: enabled)
   Active: active (running) since Sun 2020-10-18 11:31:56 JST; 15min ago
Main PID: 15070 (unitd)
    Tasks: 3 (limit: 1152)
   CGroup: /system.slice/unit.service
           ├─15070 unit: main v1.20.0 [/usr/sbin/unitd --log /var/log/unit.log --pid /var/run/unit.pid]
           ├─15072 unit: controller
           └─15073 unit: router

10月 18 11:31:56 meet systemd[1]: Starting NGINX Unit...
10月 18 11:31:56 meet unitd[15069]: 2020/10/18 11:31:56 [info] 15069#15069 unit started
10月 18 11:31:56 meet systemd[1]: unit.service: Can't open PID file /var/run/unit.pid (yet?) after start: No such file or directory
10月 18 11:31:56 meet systemd[1]: Started NGINX Unit.

「active (running)」です。
以上、NGINX Unitのインストールは完了です。

次は、設定ですね。
Nginx上でPythonアプリが起動するように設定を行います。

NGINX Unitの設定

インストール同様、公式サイトを参考にします。
https://unit.nginx.org/howto/samples/

Pythonアプリ(プログラム)の作成

まずは、アプリ(プログラム)の作成からです。
以下の内容のファイルを作成します。

def application(environ, start_response):
    start_response("200 OK", [("Content-Type", "text/plain")])
    return (b"Hello, Python on Unit!")

公式では、/www/wsgi.pyファイルを作成するように記載があります。
でも、「/」の直下にディレクトリを増やすのは嫌ですね。。。
なので、/var/wwwの下に専用のディレクトリを作成します。

$ sudo mkdir /var/www/python

ここにwsgi.pyを作成します。

$ cat /var/www/python/wsgi.py
def application(environ, start_response):
    start_response("200 OK", [("Content-Type", "text/plain")])
    return (b"Hello, Python on Unit!")

Pythonアプリの登録

NGINX UnitにPythonアプリを登録します。
その際の設定方法は、特殊です。

curlによりjsonをNGINX Unitに送り付けて登録するのです。
以下は公式サイトに記載されている方法の一つです。

# curl -X PUT --data-binary '{             \
  "listeners": {                           \
      "*:8080": {                          \
          "pass": "applications/python_app"\
      }                                    \
  },                                       \
  "applications": {                        \
      "python_app": {                      \
          "type": "python",                \
          "path": "/www/",                 \
          "module": "wsgi"                 \
      }                                    \
  }                                        \
  }' --unix-socket /path/to/control.unit.sock http://localhost/config/

コマンドラインでjsonを送るのは、ちょっと違和感あります。
そのため、ファイルにして送ります。

まず、/var/www/pythonにconf.jsonを作成します。

# cat conf.json
{
"listeners": {
"*:8080": {
"pass": "applications/python_app"
}
},
"applications": {
"python_app": {
"type": "python",
"path": "/var/www/python/",
"module": "wsgi"
}
}
}

pathやmoduleは各自の環境に変更する必要があります。
今回は、/var/www/pythonの下にwsgi.pyファイルを作成しました。

よって、pathは/var/www/pythonとなります。
また、moduleは、wsgi.pyよる「.py」を除去したモノとなります。

NGINX Unitにconf.jsonの内容を反映させます。
以下のコマンドとなります。

# cd /var/www/python/
# curl -X PUT --data-binary @conf.json --unix-socket /var/run/control.unit.sock http://localhost/config

成功した場合、失敗した場合の結果を載せておきます。

成功した場合

{
        "success": "Reconfiguration done."
}

失敗した場合

私は、2種類のエラーを確認しました。
パターン別に表示します。

jsonファイルに問題がある場合

{
        "error": "Invalid JSON.",
        "detail": "A double quote (\") is expected here.  There must be a valid JSON object member starts with a name, which is a string enclosed in double quotes.",
        "location": {
                "offset": 14,
                "line": 1,
                "column": 15
        }
}

jsonviewerなどで適切なjsonファイルになるように修正してください。

モジュール(json上ではtypeで指定)が存在しない場合

{
        "error": "Invalid configuration.",
        "detail": "The module to run \"python\" is not found among the available application modules."
}

エラー内容は、python用のモジュールが見つからないと言っています。
ubuntuの場合は、「/usr/lib/unit/modules/」を確認します。

$ ls /usr/lib/unit/modules/
java11.unit.so  java8.unit.so  perl.unit.so  php.unit.so  python2.7.unit.so  python3.6.unit.so  python3.7.unit.so  ruby.unit.so

存在しているのに、見つからないことがありえます。
その場合は、NGINX Unitを再起動します。

$ sudo systemctl restart unit

これで、モジュールが見つからない問題は解決します。

Pythonアプリの動作確認

8080ポートにcurlでアクセスします。

$ curl localhost:8080
Hello, Python on Unit!

上記のように「Hello, Python on Unit!」と表示されれば、OKです。
Pythonアプリの動作確認は完了です。

残された課題

念のため、ブラウザでも確認しておきましょう。
そのためには、ポートの開放が必要です。

$ sudo ufw allow 8080

conf.json上で8080を登録しましたよね。
そのため、ポート8080を開放しています。

この状態で次のURLにアクセス。
http://サーバIP:8080

ブラウザで確認できてこそ、Webアプリと言えますね。
めでたし、めでたし。

という訳にはいかないのです。
上記表示を行うプログラムを再度確認しましょう。

def application(environ, start_response):
    start_response("200 OK", [("Content-Type", "text/plain")])
    return (b"Hello, Python on Unit!")

これをどうやって、htmlタグと組み合わせるのでしょうか?
PHPなら、次のようにPHPの処理を簡単に埋め込むことができました。

<div><?php echo "テスト"; ?></div>

Pythonでは?
この問いに答えるために、便利なモノが用意されています。

それはフレームワークと呼ばれています。
Django、Flaskとか聞いたことはありませんか?

これらのフレームワークを利用すると、上記の問い(課題)を解決できます。
ただし、本記事ではここまでとします。

また、別の記事でフレームワークについて解説します。

タイトルとURLをコピーしました