最終更新日:2022/12/17 原本2020-09-30

Chapter 03無料公開

Nginx + uWSGI + Flaskによるwebアプリの構築

今関翔太
今関翔太
2020.09.30に更新

3. やること

本章では、Hello World!を返すだけの簡単なFlaskアプリケーションをインターネット上に公開する。その際にwebサーバーにはNginxを、アプリケーションサーバーにはuWSGIを採用した。下記にて、簡単に用語の説明と構成図を掲載しておく。

用語


webサーバー

クライアントからのリクエスト(HTTP, HTTPSなど)を受け取り、サーバー内にある特定のファイル(htmlファイルや画像など)を返すサーバー。リクエストの内容によっては、アプリケーションサーバーにリクエストを行うこともある。
NginxはOSSのwebサーバーであり、高速・高負荷な処理に強く、大量の同時リクエストに耐えられることが特徴の一つである。Nginxについては、まだまだ理解が甘いため、nginx実践ガイドを読了後、修正・加筆を行う予定である。

アプリケーションサーバー

webサーバーからのリクエストを受けて、アプリケーションを実行するサーバー。プログラムの実行やDBとの接続を行う。
uWSGIを理解するためにはまず、WSGIについて理解する必要がある。WSGIはWeb Server Gateway Interfaceの略称であり、Pythonで記述されたアプリケーションとwebサーバーのプロトコル(やりとりする際の規約のようなもの)である。FlaskやDjangoなど、Pythonのアプリケーションフレームワークの増加に伴い、webサーバーとの共通のプロトコルを作る必要があった。そのような背景からWSGIは生まれた。
uWSGIは、簡単に言うとWSGIに則ったアプリケーションサーバーである。uWSGI意外には、Gunicornなども有名である。

構成図


今回のサーバー構成を図にすると下記のようになる。青矢印がリクエストの流れになる。都合上、レスポンスは省略しているが、リクエストの逆の流れになる。

3.1. 各種インストール作業

3.1.に限らず本章での作業は全てインスタンス上になる。前章2.3.3.で説明した手順をもとにインスタンスにSSH接続を行っておくこと。

3.1.1. Python3及びpipのインストール

  1. 下記コマンドを実行し、yum(LinuxのRedHat系ディストリビューション用のパッケージ管理ツール)の更新を行う。
    $ sudo yum -y update
    
  2. python3をインストールする。
    $ sudo yum install python37
    
  3. 任意のフォルダを作成し、.pyファイルをダウンロード、pipをインストールする。
    $ mkdir setup
    $ cd setup
    $ curl -O https://bootstrap.pypa.io/get-pip.py
    $ python3 get-pip.py --user
    $ pip --version # 動作確認
    pip 20.2.3 from ...
    

3.1.2. Nginxのインストール

公式ドキュメントを参考にインストールを行う。なお、ここではRHEL/CentOS系のインストール方法しか記載していないが、公式ドキュメントにUbuntuなどのインストール方法も記載されている。

  1. リポジトリ設定ファイルを作成する。
    $ sudo vi /etc/yum.repos.d/nginx.repo
    
  2. ファイルには、下記内容を記載して保存する。
    [nginx]
    name=nginx repo
    baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
    gpgcheck=0
    enabled=1
    
  3. Nginxをインストールする。
    $ sudo yum install nginx
    $ nginx -V # 動作確認
    
  4. Nginxを起動する。
    $ sudo service nginx start
    
  5. Google Chromeなどの適当なブラウザを開き、アドレスバー(URLを入力する窓の部分)にインスタンスのElastic IPを入力すると、下記画面が表示されるようになっている。

※ 表示されない場合
Nginx側でエラーが起きている可能性がある。その際はログを確認して、エラーを解決する必要がある。

  • Nginxの設定ファイルの中身を確認する。
    $ cat /etc/nginx/nginx.conf
    
  • confファイル内にerror.logのディレクトリを示している箇所がある。
    error_log  /var/log/nginx/error.log warn;
    
  • error.logの中身を確認し、エラーを解決する。

3.1.3. uWSGIのインストール

WSGIを利用することで、WebサーバとWebアプリケーションの実装を切り離すことができ、WebサーバとWebアプリケーションフレームワークの組み合わせを柔軟に選択することができる

こちらも公式ドキュメントを参考にインストールを行う。uWSGIはpipで簡単にインストールが可能なのだが、事前に必要なライブラリ(Cコンパイラ関連)がインストールされていないとエラーになってしまうため、注意が必要である。

  1. 下記コマンドを実行して、必要なライブラリなどをインストールする。
    $ sudo yum groupinstall "Development Tools"
    $ sudo yum install python3-devel
    
  2. uWSGIをインストールする。
    $ pip install uwsgi
    

3.2. Flaskアプリケーションの作成及びuWSGIとの連携

以下のコマンドでFlaskをインストールします。
(Jinja2, itsdangerous, requests, WerkzeugはFlaskを動作させるために必要なパッケージです。)
$ pip install Flask==1.0.2 Jinja2==3.0.1 itsdangerous==2.0.1 requests==2.21.0 Werkzeug==2.0.1

正しくインストールされていることが確認できればOKです。($ pip show flask)

接続確認も含めて、ブラウザにHello World!を出力する簡単なアプリを開発する。

  1. 作業用ディレクトリ及びファイルの作成を行う。
    $ sudo mkdir -r /var/www/uwsgi/
    $ cd /var/www/uwsgi/
    $ touch app.py
    $ touch app.ini
    
  2. ファイル構成は下記のようになっている。
    /var/www/uwsgi/
    |-app.py
    |-app.ini
    
  3. app.pyファイルの中には下記コードを記述する。これを実行させることで、ブラウザにHello World!を出力することができる。
    from flask import Flask
    app = Flask(__name__)
    
    @app.route("/")
    def hello():
        return "Hello World!"
    
    if __name__ == "__main__":
        app.run()
    
  4. app.iniファイルの中には下記を記述する。uWSGIを起動させる際のパラメータを記述したものである。
    [uwsgi]
    module = app
    callable = app
    master = true
    processes = 1
    socket = /tmp/uwsgi.sock
    chmod-socket = 666
    vacuum = true
    die-on-term = true
    wsgi-file = /var/www/uwsgi/app.py
    logto = /var/www/uwsgi/app.log
    
    主要なものだけ簡単に説明しておく。
    • module: モジュールの指定
    • socket: ソケットの指定
    • chmod-socket: ソケットへのアクセス権
    • wsgi-file: アプリケーションファイルの指定
    • logto: ログの出力先
  5. iniファイルを作成したことで、接続状況は下記のようになっている。
    app <-> uWSGI
    

3.3. uWSGIとNginxの連携

本節ではNginxの設定ファイルを作成し、uWSGIとの連携を行う。本節の作業が完了すれば、ブラウザ上にHello World!が出力できるようになる。

  1. 下記コマンドを実行し、Nginxの設定ファイルを開く。
    $ cat /etc/nginx/nginx.conf
    
  2. 設定ファイル内に下記コードが記述されていることを確認する。
    include /etc/nginx/conf.d/*.conf
    
    これによって、Nginxがクライアントからリクエストを受けた際には、/etc/nginx/conf.d/直下のconfファイルに従う仕組みになっている。
  3. 下記コマンドを実行し、confファイルを作成する。
    sudo vi /etc/nginx/conf.d/uwsgi.conf
    
  4. confファイルに下記コードを記述する。
    server {
        listen       80;
    
        location / {
    	include uwsgi_params;
    	uwsgi_pass unix:///tmp/uwsgi.sock;
        }
    }
    
    これにより、サーバーのルートにHTTPリクエストがあった場合は、/tmp/uwsgi.sockに接続する仕組みになっている。これは3.2.の手順4で設定したsocketとも同じである。これによって、uWSGIとの接続が可能になる。
  5. confファイルを作成したことで、接続状況は下記のようになっている。
    app <-> uWSGI <-> socket <-> Nginx <-> Client
    

3.4. アプリの起動及び動作確認

3.3.までの作業で本章で目標としていたアプリの開発は完了している。本節では、実際にアプリを起動し、ブラウザに表示されるかどうか、確認を行う。

  1. 3.2.の手順4で作成したiniファイルをパラメータとして渡す形で、下記コマンドを実行する。
    $ uwsgi --ini /var/www/uwsgi/app.ini
    
  2. 3.1.2.の手順5と同様に、ブラウザにElastic IPを入力し、下記のようにHello World!が出力されていることを確認する。

※ 表示されない場合
Nginx, uWSGI, appのいずれかでエラーが起きている可能性がある。各種ログファイルなどを確認し、エラー原因を特定、解消する必要がある。

  • Nginx: /etc/nginx/nginx.conf # 手順3.1.2.のログファイルと同じディレクトリ
  • uWSGI及びapp: /var/www/uwsgi/app.log # 手順3.2.の手順4のlogtoの値参照