NGINX + NGINX Unit + Flask でPythonのWebアプリ開発
Python で Web 開発をしようと思い、Python の Web アプリの環境構築を行いました。
これまでは、NGINX <-> uwsgi <-> Flask
という構成が主流でしたが、2018 年 4 月に NGINX 社が軽量な AP サーバーNGINX Unit
をリリースしました。
今回は NGINX Unit を使用し、NGINX <-> NGINX Unit <-> Flask
という構成で Web アプリケーションの環境を構築していきます。
環境
Web サーバーとしてNGINX
を、AP サーバーとしてNGINX Unit
を、Python の Web フレームワークにFlask
を使用します。
- OS : CentOS7
- Python : 3.7.4
- NGINX : 1.16.1
- NGINX Unit : 1.10.0
- Flask : 1.1.1
備考
サーバーは Vagrant と VirtualBox の仮想環境を使用します。
プライベートネットワークを有効にしてください。
$ vagrant init centos/7
$ vi Vagrantfile
- # config.vm.network "private_network", ip: "192.168.33.10"
+ config.vm.network "private_network", ip: "192.168.33.10"
$ vagrant up
$ vagrant ssh
vagrant ssh
で仮想環境に接続し、selinux を無効にしてください。
$ sudo vi /etc/selinux/config
- SELINUX=enforcing
+ SELINUX=disabled
$ sudo reboot
Python の開発環境構築
仮想環境に Python の開発環境を構築します。
CentOS にはデフォルトでPython 2.7.5
がインストールされています。
$ python --version
Python 2.7.5
今回はPython 3.7.4
を利用します。
CentOS に Python3 をインストール
Python の公式ページの手順を参考にして CentOS に Python をインストールします。
まずは必要なツールをインストールします。
$ sudo yum -y groupinstall "development tools"
$ sudo yum install -y bzip2-devel gdbm-devel libffi-devel libuuid-devel ncurses-devel openssl-devel readline-devel sqlite-devel tk-devel wget xz-devel zlib-devel
インストーラーを Python の公式ページからwget
でダウンロードします。
ダウンロード後に解凍します。
$ wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz
$ tar xzf Python-3.7.4.tgz
ソースコードを解凍後にビルドします。
$ cd Python-3.7.4
$ ./configure --enable-shared
$ make
$ sudo make install
$ sudo sh -c "echo '/usr/local/lib' > /etc/ld.so.conf.d/custom_python3.conf"
$ sudo ldconfig
ビルドしたコマンドは/usr/local/bin
配下ににインストールされます。
$ which python
/usr/bin/python
$ which python3
/usr/local/bin/python3
$ python3 --version
Python 3.7.4
$ which pip3
/usr/local/bin/pip3
最後にpip
をアップグレードします。
$ pip3 install --upgrade pip --user
ローカルのbin
に最新版のpip
コマンドがインストールされます。
$ which pip
~/.local/bin/pip
$ pip --version
pip 19.2.3 from /home/vagrant/.local/lib/python3.7/site-packages/pip (python 3.7)
Python の環境構築は以上になります。
Python の仮想環境の作成
プロジェクトごとにパッケージを切り替えて管理するために、Python の仮想環境を構築します。
Python には仮想環境の作成をサポートしている標準モジュールとしてvenv
が用意されています。
venv
を使用して仮想環境を作成します。
# flask_sampleという仮想環境を作成
$ python3 -m venv flask_sample
$ ls
venv
venv で作成した仮想環境を有効化します。
$ source flask_sample/bin/activate
(flask_sample)$
venv
モジュールで作成されたディレクトリ内のactivate
スクリプトを実行することで、仮想環境を有効化することができます。
仮想環境を有効化するとプロンプトの先頭に(仮想環境名)
が表示されます。
作成した仮想環境のディレクトリに移動して構成を確認します。
(flask_sample)$ cd flask_sample
(flask_sample)$ ls
bin include lib lib64 pyvenv.cfg
bin
ディレクトリには仮想環境を有効化するactivate
スクリプトや、Python のパッケージ管理ツールpip
コマンドが格納されています。
仮想環境内で pip
コマンドを実行する際は、このディレクトリ内のコマンドが実行されます。
インストールされたパッケージはlib/python3.7/site-packages
とlib64/python3.7/site-packages
内にインストールされます。
仮想環境内では、Python 本体のsite-packages
ディレクトリを無視してこちらのディレクトリ内のパッケージを使用します。
Python 本体のパッケージを汚すことなくアプリ開発を行うことができます。
Flask でサンプルプロジェクトの作成
Flask
は Python の小規模なマイクロフレームワークです。標準で掲載されている機能は最小限になっており、小規模なアプリケーションを開発する際に用いられます。
プラグインが提供されているため、機能を拡張することができます。
初めから大規模なアプリケーションを開発する場合はDjango
を使用します。
Flask のインストール
venv 仮想環境で、Flask
をインストールします。
(flask_sample)$ pip install Flask
アプリケーションの作成
サンプルプロジェクトの構成は以下のようにします。
/sample
|- app.py
|- templates
|- index.html
|- post.html
それぞれのコードは以下のように実装します。
from flask import Flask ,render_template,request
application = Flask(__name__)
@application.route('/')
def index():
return render_template('index.html')
@application.route('/sample',methods=['POST'])
def sample():
message = request.form['message']
return render_template('post.html',message=message)
if __name__=="__main__":
application.run(host='0.0.0.0')
<html>
<head>
<meta charset="utf-8" />
<title>Flask Sample</title>
</head>
<body>
<h1>Flask Smaple</h1>
<form action="sample" method="post">
<input type="text" name="message" />
<input type="submit" value="送信" />
</form>
</body>
</html>
<html>
<head>
<meta charset="utf-8" />
<title>Flask Sample</title>
</head>
<body>
<h1>Flask Smaple</h1>
メッセージ:{{message}}
</body>
</html>
実装後にapp.py
を実行し、Flask のアプリケーションを起動します。
(flask_sample)$ python /sample/app.py
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
起動後にブラウザでhttp://仮想環境のプライベートIP:5000/
にアクセスすると、index.html
が表示されます。
確認できればFlask
の動作確認は終了です。次は、NGINX Unit
で AP サーバーを構築します。
NGINX Unit
NGINX Unit は NGINX 社が開発した、軽量なアプリケーションサーバーです。
複数の言語のアプリケーションを実行することができるため、同じサーバー上で異なる言語のアプリケーションを運用できます。
言語はPython
,PHP
,Go
,Perl
,Ruby
,Node.js
,Java
に対応しています。
さらに、言語内の異なるバージョンを共存させて実行することができます。(Python2.7 と Python3 など)
API や JSON 経由で、サーバーを停止することなくリアルタイムに設定を変更することができるため、サービスを停止させることなくシームレスに設定の変更を行うことができます。
インストール
公式ドキュメントに各 OS ごとのインストール方法が公開されています。
venv 仮想環境から出て、yum のリポジトリを追加します。
(flask_sample)$ deactivate
$ sudo vi /etc/yum.repos.d/unit.repo
[unit]
name=unit repo
baseurl=https://packages.nginx.org/unit/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
インストールします。
$ sudo yum install -y unit
$ sudo yum install -y unit-devel unit-go unit-jsc8 unit-perl unit-php unit-python
NGINX Unit の自動起動を設定します。
$ sudo systemctl enable unit
Created symlink from /etc/systemd/system/multi-user.target.wants/unit.service to /usr/lib/systemd/system/unit.service.
$ sudo service unit start
Redirecting to /bin/systemctl start unit.service
$ sudo service unit status
Redirecting to /bin/systemctl status unit.service
● unit.service - NGINX Unit
Loaded: loaded (/usr/lib/systemd/system/unit.service; enabled; vendor preset: disabled)
Active: active (running) since 火 2019-11-05 15:42:47 UTC; 7h ago
Main PID: 5714 (unitd)
CGroup: /system.slice/unit.service
├─5714 unit: main v1.12.0 [/usr/sbin/unitd --log /var/log/unit/unit.log --pid /var/run/unit/unit.pid --no-daemon]
├─5716 unit: controller
└─5717 unit: router
service unit status
で NGINX Unit が起動できていることが確認できます。
Flask 用の設定を行う
NGINX Unit
で Flask のアプリケーションを実行する設定を行います。
設定ファイルを NGINX Unit のソケットから GET
して、Flask のアプリケーションを NGINX Unit
にロードする設定を行います。
NGINX Unit
のコントロール用の Unix ソケットは、/var/run/unit/control.sock
にあります。(OSによって場所は異なります)
$ cd /sample
$ sudo curl --unix-socket /var/run/unit/control.sock http://localhost/config/ > config.json
$ vi config.json
{
"listeners": {
"*:8080": {
"pass": "applications/flask_app"
}
},
"applications": {
"flask_app": {
"type": "python",
"processes": 2,
"path": "/sample/",
"module": "app"
}
}
}
- listeners : ポートの設定を行います。
*:8080
のpass
の値が、applications
の階層と紐ずいています。 - applications :
- type : モジュール名(言語)を指定
- processes : worker 数
- path : Python プログラムを配置しているパス
- module : 起動するファイル。ファイル名から拡張子を除いた形で指定
作成した設定ファイルを NGINX Unit のソケットに対して PUT して、設定の反映をします。
$ sudo curl -X PUT --data-binary @config.json --unix-socket /var/run/unit/control.sock http://localhost/config
{
"success": "Reconfiguration done."
}
success
が帰ってくると設定が完了しています。設定内容の確認もできます。
$ sudo curl --unix-socket /var/run/unit/control.sock http://localhost/
{
"certificates": {},
"config": {
"listeners": {
"*:8080": {
"pass": "applications/flask_app"
}
},
"applications": {
"flask_app": {
"type": "python",
"processes": 2,
"path": "/sample/",
"module": "app"
}
}
}
}
仮想環境を起動し、http://localhost:8080/
にアクセスします。
$ source venv/bin/activate
(flask_sample)$ curl http://localhost:8080/
<html>
<head>
<meta charset="utf-8" />
<title>Flask Sample</title>
</head>
<body>
<h1>Flask Smaple</h1>
<form action="sample" method="post">
<input type="text" name="message" />
<input type="submit" value="送信" />
</form>
</body>
</html>
index.html
が表示されれば構築完了です。ブラウザでアクセスしてもindex.html
が表示されます。
NGINX Unit
の構築は以上です。次は Web サーバーの NGINX
を構築します。
NGINX
軽量・高速が特徴のオープンソースの Web サーバー で、Apache の代替になりうるサーバーとして注目されています。
Apache と比べるとスケーラビリティの面で優れており、処理性能・並列処理・メモリ使用量の小ささなどが特徴として挙げられます。今回はプロキシサーバーとして利用します。
NGINX を CentOS にインストールする
NGINX
は公式に yum のリポジトリを公開しているため、そのリポジトリからインストールします。
公式ページの記述を参考にリポジトリを追加してインストールを行います。
リポジトリの追加
一度 Python 仮想環境から出ます。
yum リポジトリの追加を行います。/etc/yum.repos.d/NGINX.repo
を追加します。
$ sudo vi /etc/yum.repos.d/NGINX.repo
[NGINX]
name=NGINX repo
baseurl=http://NGINX.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
インストール
リポジトリの確認を行います。
$ sudo yum info nginx
Available Packages
Name : NGINX
Arch : x86_64
Epoch : 1
Version : 1.16.1
Release : 1.el7_4.ngx
Size : 754 k
Repo : NGINX/x86_64
Summary : High performance web server
URL : http://NGINX.org/
License : 2-clause BSD-like license
Description : NGINX [engine x] is an HTTP and reverse proxy server, as well as
: a mail proxy server.
yum info
コマンドでリポジトリに NGINX があるとこが確認できたらインストールを行います。
$ sudo yum install nginx
自動起動を設定し、
NGINX を起動します。
$ sudo systemctl enable nginx
$ sudo service start nginx
$ ![nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239179/0d818e0a-7aee-8a07-af95-72d34dfaa824.png)
service status nginx
● NGINX.service - NGINX - high performance web server
Loaded: loaded (/usr/lib/systemd/system/NGINX.service; enabled; vendor preset: disabled)
Active: active (running)
NGINX を起動後にブラウザでhttp://仮想環境のプライベートIP
にアクセスします。
以下のうような画面が表示されれば起動が完了です。
NGINX と NGINX Unit の連携
NGINX の設定ファイル
NGINX
は NGINX Unit
の前の WEB サーバーやプロキシサーバーとして運用します。
アプリケーションへのリクエストを Nginx Unit にプロキシします。
NGINX
の設定ファイルは/etc/nginx/conf.d
にあります。
$ sudo vi /etc/nginx/conf.d/app.conf
upstream unit-python {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name localhost;
location ~ / {
proxy_pass http://unit-python;
proxy_set_header Host $host;
}
}
NGINX を再起動し、http://localhost/
にアクセスします。
$ sudo service restart nginx
$ curl http://localhost/
<html>
<head>
<meta charset="utf-8" />
<title>Flask Sample</title>
</head>
<body>
<h1>Flask Smaple</h1>
<form action="sample" method="post">
<input type="text" name="message" />
<input type="submit" value="送信" />
</form>
</body>
</html>
'index.html'が表示されればプロキシ設定が完了です。ブラウザでhttp://仮想環境のプライベートIP
にアクセスしindex.html
を確認することができます。
以上でPythonのWebアプリの環境構築は終了です。
まとめ
NGINX
+ NGINX Unit
+ Flask
で WEB アプリケーションの環境構築を行いました。
NGINX Unit
はマイクロサービスの運用に特化しているため、今後も注目されて行くと思います。
継続して触れていきたいと思います。