Amazon LinuxでFlask/Apache/mod_wsgi/virtualenvなアプリを動かす
Flaskの組み込みWebサーバーを使ったインストールは過去にご紹介しました。
EC2上でFlaskを動かしてみる | Developers.IO
プロダクション環境では組み込みWebサーバーでの運用はお勧めできないため、 今回は mod_wsgi モジュールを使って Apache 上で Flask アプリケーションを動かします。
システム構成図
コンポーネントについて
- Apache : ウェブサーバー
- Flask :Web Server Gateway Interface(WSGI) アプリケーション
- mod_wsgi : WSGI インターフェースのPythonアプリケーションを Apache 上で動作させるApacheモジュール
- virtualenv : システムワイドではない専用のPython環境を提供
検証環境
- Amazon Linux/2015.09
- Apache/2.4.16 (Amazon)
- mod_wsgi/3.5
- Python/2.7.10
- Flask/0.10.1
作業の流れ
Apache/mod_wsgiのインストール
Apache httpd 2.4 と Python2.7 向けの mod_wsgi をインストールします。
$ sudo yum install -y mod24_wsgi-python27
- apr
- apr-util
- httpd24
- httpd24-tools
- mod24_wsgi-python27
がまとめてインストールされます。
Apache(2.4)やPython(2.7)のバージョンは適宜読み替えてください。
Apacheの自動起動を有効にし、起動します。
$ sudo chkconfig httpd on $ sudo service httpd start
Flaskアプリケーションのインストール
/var/www/flask_wsgi_demo
以下にアプリケーションをインストールします。
最終的に/var/www/flask_wsgi_demo
以下のファイル構成は次の様になります。
$ tree -L 2 . |-- app.py # Flask application |-- flask_wsgi_demo.wsgi # WSGI interface file |-- requirements.txt # package requirements file `-- venv # virtual environment |-- bin |-- include |-- lib |-- lib64 |-- local `-- pip-selfcheck.json
ディレクトリを用意
root ユーザーで作業します。
# mkdir /var/www/flask_wsgi_demo # cd /var/www/flask_wsgi_demo # virtualenv venv New python executable in venv/bin/python2.7 Also creating executable in venv/bin/py # . venv/bin/activate (venv)$
Python パッケージをインストール
Flask(0.10.1) をpipでインストールします。 依存パッケージは requirements.txt で指定します。
# cat requirements.txt Flask==0.10.1 # pip install -r requirements.txt
アプリをインストール
ルートパスにアクセスすると、"Hello World!" を返すだけの Flask アプリを用意します。
# app.py # "hello world" flask app from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run()
組み込みWebサーバーでFlaskアプリを起動
Flaskの組み込みWebサーバーでFlaskアプリを起動します。
$ python app.py * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) 127.0.0.1 - - [13/Mar/2016:04:41:07 +0000] "GET / HTTP/1.1" 200 12 "-" "curl/7.40.0"
別ターミナルから、ローカルホストの 5000 に GET して正常なレスポンスが帰ることを確認します。
$ curl -D - localhost:5000 HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 12 Server: Werkzeug/0.11.4 Python/2.7.10 Date: Sun, 13 Mar 2016 04:42:23 GMT Hello World!
"Hello World!" と返ってきたのでOKです。 レスポンスヘッダーから組み込みサーバーは「Werkzeug/0.11.4」で動いていることがわかります。
Apache/mod_wsgi でFlaskアプリを起動
次に mod_wsgi モジュール経由で Apache でFlaskアプリを起動します。
.wsgi ファイルを作成
mod_wsgi がアプリ起動時に利用する .wsgi ファイルを作成します。 中身は Python プログラムです。
# flask_wsgi_demo.wsgi import os import sys DIR=os.path.dirname(__file__) sys.path.append(DIR) activate_this = os.path.join(DIR, 'venv/bin/activate_this.py') execfile(activate_this, dict(__file__=activate_this)) from app import app as application
次の箇所でFlaskアプリケーションのあるパスをサーチパスに追加します。
DIR=os.path.dirname(__file__) sys.path.append(DIR)
次の箇所でvirtualenvを読みこむようにします。
activate_this = os.path.join(DIR, 'venv/bin/activate_this.py') execfile(activate_this, dict(__file__=activate_this))
deactivate
コマンドを実行して、virtualenv 環境から一時的に抜け、正しく設定できているか確認します
# deactivate # <- disabple virtualenb # python flask_wsgi_demo.wsgi # echo $? 0
例えば .wsgi ファイル内でvirtualenb を正しく読み込めていなければ、以下のような Flask モジュールのインポートエラーが発生します。
# python flask_wsgi_demo.wsgi Traceback (most recent call last): File "flask_wsgi_demo.wsgi", line 7, in <module> from app import app as application File "/var/www/flask_wsgi_demo/app.py", line 1, in <module> from flask import Flask ImportError: No module named flask
Apache 設定の変更
最後の Apache の設定変更をします。
次の内容のファイル /etc/httpd/conf.d/flask.conf
を追加します。
<VirtualHost *:80> ServerName example.com WSGIDaemonProcess flask_wsgi_demo user=apache group=apache threads=5 WSGIScriptAlias / /var/www/flask_wsgi_demo/flask_wsgi_demo.wsgi WSGIScriptReloading On <Directory /var/www/flask_wsgi_demo> WSGIProcessGroup flask_wsgi_demo WSGIApplicationGroup %{GLOBAL} Order deny,allow Allow from all </Directory> </VirtualHost>
主要なディレクティブについてだけ解説します。
WSGIScriptAlias
.wsgi ファイルのパスです。
WSGIScriptReloading
この設定を On にしておくと、.wsgi ファイルの変更イベントを捕まえせて、Apacheのデーモンプロセスが設定を再読み込します。
Directory
Flask アプリケーションのパス
Apache 設定を確認し、Apacheを再起動します。
# service httpd configtest Syntax OK # service httpd restart Stopping httpd: [ OK ] Starting httpd: [ OK ]
Apache が LISTEN している 80 番ポートにローあるホストとインターネットから HTTP GET して、動作を確認します。
$ curl -D - localhost HTTP/1.1 200 OK Date: Sun, 13 Mar 2016 04:41:07 GMT Server: Apache/2.4.16 (Amazon) mod_wsgi/3.5 Python/2.7.10 Content-Length: 12 Content-Type: text/html; charset=utf-8 Hello World! $ curl ec2-52-192-162-44.ap-northeast-1.compute.amazonaws.com Hello World!
レスポンスヘッダーからサーバーは Apache/mod_wsgi であることがわかります。
まとめ
今回は Python 製マイクロフレームワークとApache/mod_wsgi の連携を紹介しました。
WSGI のおかげで gunicornやuWSGI(nginx) など他のウェブサーバーとも容易に連携させることもできます。
他の連携方法についても、機会があれば紹介したいと思います。