Amazon LinuxでFlask/Apache/mod_wsgi/virtualenvなアプリを動かす

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Flaskの組み込みWebサーバーを使ったインストールは過去にご紹介しました。

EC2上でFlaskを動かしてみる | Developers.IO

プロダクション環境では組み込みWebサーバーでの運用はお勧めできないため、 今回は mod_wsgi モジュールを使って Apache 上で Flask アプリケーションを動かします。

システム構成図

flask-apache

コンポーネントについて

  • 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) など他のウェブサーバーとも容易に連携させることもできます。

他の連携方法についても、機会があれば紹介したいと思います。

参考URL