序章

このガイドでは、Ubuntu16.04でFlaskマイクロフレームワークを使用して簡単なPythonアプリケーションをセットアップします。 この記事の大部分は、アプリケーションを起動するようにuWSGIアプリケーションサーバーを設定し、フロントエンドのリバースプロキシとして機能するようにNginxを設定する方法について説明します。

前提条件

このガイドを開始する前に、サーバーでroot以外のユーザーを構成しておく必要があります。 このユーザーは、管理機能を実行できるように、sudo特権を持っている必要があります。 これを設定する方法については、初期サーバー設定ガイドに従ってください。

uWSGI、アプリケーションサーバー、およびWSGI仕様の詳細については、このガイドのリンクされたセクションを参照してください。 これらの概念を理解すると、このガイドを理解しやすくなります。

続行する準備ができたら、読み進めてください。

Ubuntuリポジトリからコンポーネントをインストールします

最初のステップは、リポジトリから必要なすべてのピースをインストールすることです。 Pythonコンポーネントをインストールして管理するために、Pythonパッケージマネージャーであるpipをインストールします。 また、uWSGIのビルドに必要なPython開発ファイルを入手し、Nginxもインストールします。

ローカルパッケージインデックスを更新してから、パッケージをインストールする必要があります。 必要なパッケージは、プロジェクトでPython2とPython3のどちらを使用しているかによって異なります。

Python 2 を使用している場合は、次のように入力します。

  1. sudo apt-get update
  2. sudo apt-get install python-pip python-dev nginx

代わりに、 Python 3 を使用している場合は、次のように入力します。

  1. sudo apt-get update
  2. sudo apt-get install python3-pip python3-dev nginx

Python仮想環境を作成する

次に、Flaskアプリケーションをシステム上の他のPythonファイルから分離するために、仮想環境をセットアップします。

pipを使用してvirtualenvパッケージをインストールすることから始めます。

Python 2 を使用している場合は、次のように入力します。

  1. sudo pip install virtualenv

Python 3 を使用している場合は、次のように入力します。

  1. sudo pip3 install virtualenv

これで、Flaskプロジェクトの親ディレクトリを作成できます。 作成後、ディレクトリに移動します。

  1. mkdir ~/myproject
  2. cd ~/myproject

次のように入力することで、FlaskプロジェクトのPython要件を保存する仮想環境を作成できます。

  1. virtualenv myprojectenv

これにより、Pythonとpipのローカルコピーが、プロジェクトディレクトリ内のmyprojectenvというディレクトリにインストールされます。

仮想環境内にアプリケーションをインストールする前に、それをアクティブ化する必要があります。 次のように入力してください。

  1. source myprojectenv/bin/activate

プロンプトが変わり、仮想環境内で操作していることを示します。 このようになります(myprojectenv)user@host:~/myproject$

Flaskアプリケーションをセットアップする

仮想環境にいるので、FlaskとuWSGIをインストールして、アプリケーションの設計を開始できます。

FlaskとuWSGIをインストールします

pipのローカルインスタンスを使用して、FlaskとuWSGIをインストールできます。 次のコマンドを入力して、これら2つのコンポーネントを取得します。

ノート

使用しているPythonのバージョンに関係なく、仮想環境がアクティブ化されている場合は、pipコマンドを使用する必要があります(pip3ではありません)。

  1. pip install uwsgi flask

サンプルアプリを作成する

Flaskが利用可能になったので、簡単なアプリケーションを作成できます。 Flaskはマイクロフレームワークです。 よりフル機能のフレームワークが持つ可能性のあるツールの多くは含まれていません。主に、Webアプリケーションの初期化を支援するためにプロジェクトにインポートできるモジュールとして存在します。

アプリケーションはもっと複雑かもしれませんが、Flaskアプリを単一のファイルで作成します。これをmyproject.pyと呼びます。

  1. nano ~/myproject/myproject.py

このファイル内に、アプリケーションコードを配置します。 基本的に、Flaskをインポートし、Flaskオブジェクトをインスタンス化する必要があります。 これを使用して、特定のルートが要求されたときに実行する必要がある関数を定義できます。

〜/ myproject / myproject.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

これは基本的に、ルートドメインにアクセスしたときに表示するコンテンツを定義します。 終了したら、ファイルを保存して閉じます。

サーバーの初期設定ガイドに従っている場合は、UFWファイアウォールを有効にする必要があります。 アプリケーションをテストするには、ポート5000へのアクセスを許可する必要があります。

次のように入力して、ポート5000を開きます。

  1. sudo ufw allow 5000

これで、次のように入力して、Flaskアプリをテストできます。

  1. python myproject.py

サーバーのドメイン名またはIPアドレスにアクセスし、続いてWebブラウザで:5000にアクセスします。

http://server_domain_or_IP:5000

次のように表示されます。

Flask sample app

終了したら、ターミナルウィンドウでCTRL-Cを数回押して、Flask開発サーバーを停止します。

WSGIエントリポイントを作成する

次に、アプリケーションのエントリポイントとして機能するファイルを作成します。 これにより、uWSGIサーバーがアプリケーションと対話する方法がわかります。

ファイルをwsgi.pyと呼びます。

  1. nano ~/myproject/wsgi.py

ファイルは非常にシンプルです。アプリケーションからFlaskインスタンスをインポートして、実行するだけです。

〜/ myproject / wsgi.py
from myproject import app

if __name__ == "__main__":
    app.run()

終了したら、ファイルを保存して閉じます。

uWSGIを構成する

これでアプリケーションが作成され、エントリポイントが確立されました。 これで、uWSGIに進むことができます。

uWSGIサービングのテスト

最初に行うことは、uWSGIがアプリケーションを提供できることを確認するためのテストです。

これを行うには、エントリポイントの名前を渡すだけです。 これは、モジュールの名前(通常、.py拡張子を差し引いたもの)とアプリケーション内の呼び出し可能オブジェクトの名前で構成されます。 この場合、これはwsgi:appになります。

また、公開されているインターフェイスで開始されるようにソケットを指定し、uwsgiバイナリプロトコルの代わりにHTTPを使用するようにプロトコルを指定します。 以前に開いたのと同じポート番号を使用します。

  1. uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

サーバーのドメイン名またはIPアドレスにアクセスし、Webブラウザの末尾に:5000を追加します。

http://server_domain_or_IP:5000

アプリケーションの出力が再び表示されるはずです。

Flask sample app

正常に機能していることを確認したら、ターミナルウィンドウでCTRL-Cを押します。

これで仮想環境が完成したので、非アクティブ化できます。

  1. deactivate

すべてのPythonコマンドは、システムのPython環境を再び使用するようになります。

uWSGI構成ファイルの作成

uWSGIがアプリケーションに対応できることをテストしましたが、長期的な使用に対してより堅牢なものが必要です。 必要なオプションを使用してuWSGI構成ファイルを作成できます。

これをプロジェクトディレクトリに配置して、myproject.iniと呼びましょう。

  1. nano ~/myproject/myproject.ini

内部では、[uwsgi]ヘッダーから始めて、uWSGIが設定を適用できるようにします。 wsgi.pyファイルから拡張子を引いたものを参照してモジュールを指定し、ファイル内の呼び出し可能ファイルを「アプリ」と呼びます。

〜/ myproject / myproject.ini
[uwsgi]
module = wsgi:app

次に、uWSGIにマスターモードで起動し、実際のリクエストを処理するために5つのワーカープロセスを生成するように指示します。

〜/ myproject / myproject.ini
[uwsgi]
module = wsgi:app

master = true
processes = 5

テスト中に、ネットワークポートでuWSGIを公開しました。 ただし、実際のクライアント接続を処理するためにNginxを使用します。これにより、リクエストがuWSGIに渡されます。 これらのコンポーネントは同じコンピューター上で動作するため、より安全で高速なUnixソケットが推奨されます。 ソケットをmyproject.sockと呼び、このディレクトリに配置します。

また、ソケットのアクセス許可を変更する必要があります。 後でuWSGIプロセスの所有権をNginxグループに与えるので、ソケットのグループ所有者がソケットから情報を読み取ったり書き込んだりできることを確認する必要があります。 また、「バキューム」オプションを追加して、プロセスが停止したときにソケットをクリーンアップします。

〜/ myproject / myproject.ini
[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

最後に行う必要があるのは、die-on-termオプションを設定することです。 これは、initシステムとuWSGIが各プロセス信号の意味について同じ仮定を持つことを保証するのに役立ちます。 これを設定すると、2つのシステムコンポーネントが調整され、期待される動作が実装されます。

〜/ myproject / myproject.ini
[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

die-on-term = true

コマンドラインから行ったようにプロトコルを指定しなかったことにお気づきかもしれません。 これは、デフォルトでは、uWSGIがuwsgiプロトコルを使用して通信するためです。これは、他のサーバーと通信するように設計された高速バイナリプロトコルです。 Nginxはこのプロトコルをネイティブに話すことができるため、HTTPによる通信を強制するよりもこれを使用する方が適切です。

終了したら、ファイルを保存して閉じます。

systemdユニットファイルを作成する

次に注意する必要があるのは、systemdサービスユニットファイルです。 systemdユニットファイルを作成すると、Ubuntuのinitシステムが自動的にuWSGIを起動し、サーバーが起動するたびにFlaskアプリケーションを提供できるようになります。

/ etc / systemd/systemディレクトリ内に.serviceで終わるユニットファイルを作成して開始します。

  1. sudo nano /etc/systemd/system/myproject.service

内部では、メタデータと依存関係を指定するために使用される[Unit]セクションから始めます。 ここにサービスの説明を入力し、ネットワークターゲットに到達した後にのみこれを開始するようにinitシステムに指示します。

/etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

次に、[Service]セクションを開きます。 プロセスを実行するユーザーとグループを指定します。 プロセスは関連するすべてのファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を付与します。 NginxがuWSGIプロセスと簡単に通信できるように、www-dataグループにグループ所有権を付与します。

次に、作業ディレクトリをマップし、PATH環境変数を設定して、プロセスの実行可能ファイルが(仮想環境内で)どこにあるかをinitシステムが認識できるようにします。 次に、サービスを開始するコマンドを指定します。 Systemdでは、仮想環境内にインストールされているuWSGI実行可能ファイルへのフルパスを指定する必要があります。 プロジェクトディレクトリに作成した.ini構成ファイルの名前を渡します。

/etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

最後に、[Install]セクションを追加します。 これにより、起動時にサービスを開始できるようにした場合に、このサービスを何にリンクするかがsystemdに通知されます。 このサービスは、通常のマルチユーザーシステムが稼働しているときに開始する必要があります。

/etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

これで、systemdサービスファイルが完成しました。 今すぐ保存して閉じます。

これで、作成したuWSGIサービスを開始し、起動時に開始するように有効にすることができます。

  1. sudo systemctl start myproject
  2. sudo systemctl enable myproject

リクエストをプロキシするためのNginxの構成

これで、uWSGIアプリケーションサーバーが稼働し、プロジェクトディレクトリのソケットファイルに対する要求を待機しているはずです。 uwsgiプロトコルを使用してそのソケットにWebリクエストを渡すようにNginxを構成する必要があります。

Nginxのsites-availableディレクトリに新しいサーバーブロック構成ファイルを作成することから始めます。 ガイドの残りの部分と一致させるために、これを単にmyprojectと呼びます。

  1. sudo nano /etc/nginx/sites-available/myproject

サーバーブロックを開き、デフォルトのポート80でリッスンするようにNginxに指示します。 また、サーバーのドメイン名またはIPアドレスのリクエストにこのブロックを使用するように指示する必要があります。

/ etc / nginx / sites-available / myproject
server {
    listen 80;
    server_name server_domain_or_IP;
}

追加する必要がある他の唯一のものは、すべてのリクエストに一致するロケーションブロックです。 このブロック内に、設定が必要ないくつかの一般的なuWSGIパラメーターを指定するuwsgi_paramsファイルを含めます。 次に、uwsgi_passディレクティブを使用して定義したソケットにリクエストを渡します。

/ etc / nginx / sites-available / myproject
server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/sammy/myproject/myproject.sock;
    }
}

実際、アプリケーションを提供するために必要なのはこれだけです。 終了したら、ファイルを保存して閉じます。

作成したNginxサーバーブロック構成を有効にするには、ファイルをsites-enabledディレクトリにリンクします。

  1. sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

そのディレクトリにあるファイルを使用して、次のように入力して構文エラーをテストできます。

  1. sudo nginx -t

これが問題を示さずに戻った場合は、Nginxプロセスを再起動して、新しい構成を読み取ることができます。

  1. sudo systemctl restart nginx

最後に行う必要があるのは、ファイアウォールを再度調整することです。 ポート5000を介してアクセスする必要がなくなったため、そのルールを削除できます。 次に、Nginxサーバーへのアクセスを許可できます。

  1. sudo ufw delete allow 5000
  2. sudo ufw allow 'Nginx Full'

これで、Webブラウザでサーバーのドメイン名またはIPアドレスにアクセスできるようになります。

http://server_domain_or_IP

アプリケーションの出力が表示されます。

Flask sample app

ノート

Nginxを構成したら、次のステップはSSL/TLSを使用してサーバーへのトラフィックを保護することです。 これがないと、パスワードを含むすべての情報がプレーンテキストでネットワーク経由で送信されるため、これは重要です。

トラフィックを保護するためにSSL証明書を取得する最も簡単な方法は、Let’sEncryptを使用することです。 このガイドに従って、Ubuntu16.04でLet’sEncryptwithNginxを設定します。

結論

このガイドでは、Python仮想環境内に単純なFlaskアプリケーションを作成しました。 WSGI対応のアプリケーションサーバーがWSGIエントリポイントとインターフェイスできるようにWSGIエントリポイントを作成し、この機能を提供するようにuWSGIアプリサーバーを構成します。 その後、起動時にアプリケーションサーバーを自動的に起動するsystemdサービスファイルを作成しました。 Webクライアントトラフィックをアプリケーションサーバーに渡し、外部リクエストを中継するNginxサーバーブロックを作成しました。

Flaskは非常にシンプルですが、非常に柔軟なフレームワークであり、構造や設計をあまり制限することなく、アプリケーションに機能を提供することを目的としています。 このガイドで説明されている一般的なスタックを使用して、設計したフラスコアプリケーションにサービスを提供できます。