nginx + Gunicorn + Flask で Python の Web アプリ入門

この記事では以下の順でアプリケーションを作成します。

  1. Python アプリケーションで Hello World を実行
  2. 動的 Web サーバー(アプリケーションサーバー)で Hello World を実行
  3. Web アプリケーションフレームワークで Hello World を実行
  4. 静的 Web サーバーで Hello World を実行
完成図

静的Webサーバ
- コンピューター (ハードウェア) と HTTP サーバ (ソフトウェア) から構成されます。
- サーバが保持しているファイルをブラウザーへ「そのまま」送る

動的Webサーバ
- 静的Webサーバと一般的にはアプリケーションサーバとデータベースからなります
- 保持しているファイルを変更してから、HTTP サーバを通してブラウザーに送る

https://developer.mozilla.org/ja/docs/Learn/Common_questions/What_is_a_web_server より
スポンサーリンク

Python アプリケーションで Hello World

まずは「Hello World」と表示する単純なアプリケーションを作成します。

Python アプリケーションで Hello World を実行
echo 'print("Hello World")' > local.py
python3 local.py
Hello World
スポンサーリンク

アプリケーションサーバーで Hello World

外部のパソコンから HTTP リクエストを利用して、「Hello World」と表示するアプリケーションを実行するために、アプリケーションサーバーを用意します。

アプリケーションサーバーで Hello World を実行

Python でよく利用するアプリケーションサーバーは以下の3つです。

  • Gunicorn
  • Nginx Unit
  • uWSGI

今回はアプリケーションサーバーに「Gunicorn」を利用します。

なお、「Gunicorn」と 「Python アプリケーション」を接続するために「WSGI」と呼ばれる仕様を利用します。

WSGI アプリケーションの作成

Python アプリケーション側で満たすべき「WSGI」の仕様は以下の3つです。

  1. 引数「環境変数」と「ステータスコードレスポンスヘッダ」を設定するオブジェクトを持つ関数
  2. 第2引数を使って「ステータスコード」と「レスポンスヘッダ」をセットする
  3. バイト列を戻り値とする

それでは、「Hello World」と表示する WSGI アプリケーションを作成します。

vim wsgi.py
def app(env, start_response): #2つの引数を持つ関数
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain; charset=utf-8')]
    start_response(status, response_headers) #ステータスコードとレスポンスヘッダをセット
    return [b'Hello World\n'] #バイト列を戻り値とする

Gunicorn の使い方

外部のパソコンから HTTP リクエストを利用して WSGI アプリケーションを実行するために、アプリケーションサーバーである「Gunicorn」を用意します。

pip3 install Gunicorn

「gunicorn <モジュール名>:<関数名>」コマンドで WSGI アプリケーションを gunicorn

gunicorn wsgi:app

別端末から HTTP リクエストを利用して WSGI アプリケーションを実行します。

curl localhost:8000
Hello World

HTTP リクエストを利用して「Hello World」アプリケーションが実行できました。

パスで動作を変更

HTTP リクエストの指定するパスによって WSGI アプリケーションの動作を以下のように変更します。

  • パスに「/」を指定すると「Hello World」を表示
  • パスに「/other」を指定すると「Other World」を表示
vim wsgi_path.py
def app(env, start_response): #2つの引数を持つ関数
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain; charset=utf-8')]
    start_response(status, response_headers) #ステータスコードとレスポンスヘッダをセット

    if env.get("PATH_INFO") == "/": # "/" パス
        return [b'Hello World\n'] #バイト列を返す
    if env.get("PATH_INFO") == "/other": # "/other" パス
        return [b'Other World\n'] #バイト列を返す
gunicorn wsgi_path:app

パス「/」と「/other」でアプリケーションを実行します。

curl localhost:8000/
Hello World
curl localhost:8000/other
Other World
スポンサーリンク

Web アプリケーションフレームワークで Hello World

毎回「WSGI の仕様」に準拠したり「パスで動作を変更」機能を実装するのめんどくさいな〜〜〜。

という方のために Web アプリケーションフレームワークと呼ばれる「Web アプリケーション開発でよく利用する機能を集めたもの」があります。

Web アプリケーションフレームワークで Hello World を実行

Python でよく利用する Web アプリケーションは以下の3つです。

  • Flask
  • Django
  • Tornado

今回は Web アプリケーションフレームワークに Flask を利用します。

Flask で WSGI アプリケーションを作成

pip3 install flask
vim flask_app.py
from flask import Flask
  
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World\n'

@app.route('/other')
def other():
    return 'Other World\n'

WSGI の仕様は、Flask の @app.route() デコレーターがいい感じに満たしてくれます。

パスで動作を変更」も自分で実装しなくても、@app.route() の引数にパスを指定するだけです。

gunicorn flask_app:app
curl localhost:8000/
Hello World
curl localhost:8000/other
Other World

「パスで動作を変更」で作成した WSGI アプリケーションと同じものを Flask アプリケーションフレームワークで作成できました。

静的 Web サーバーで Hello World

本番稼働したらアクセスが多すぎて動かなくなっちゃった!という時は「動的 Web サーバー」の前段に「静的 Web サーバー」を配置します。

リクエストの度に動的に Web ページを生成するのはサーバーに負荷がかかるので、静的 Web ページの場合は静的 Web サーバーに任せましょう。

完成図

「静的 Web ページ」と「動的 Web ページ」の使い分けの例は以下のとおりです。

  • ホームページを表示する:毎回同じ内容でいいので静的 Web ページ
  • 売上ランキングを表示する:売上ランキングは変化するので動的 Web ページ

nginx の使い方

nginx の詳細については以下の記事をご覧ください。

sudo amazon-linux-extras install nginx1 -y
sudo sh -c 'echo "This page is static" > /usr/share/nginx/html/static.html'

パス「/」・「/other」に対する nginx へのリクエストは、Gunicorn に転送するように設定します

sudo vim /etc/nginx/conf.d/proxy.conf
server {
    listen 80;
    root /usr/share/nginx/html/;

    location /hello {
        proxy_pass  http://localhost:8000/;
        }
        location /other {
                proxy_pass  http://localhost:8000/other;
        }
}
sudo systemctl start nginx.service
gunicorn flask_app:app
curl localhost:80/static.html
This page is static

静的 Web ページにアクセスできたこと確認しました。

curl localhost:80/hello
Hello World
curl localhost:80/other
Other World

ポート 80(nginx)にアクセスして、Gunicorn で稼働しているアプリケーションの内容が返ってきていることを確認しました。

コメント