Ubuntu16.04でGunicornとNginxを使用してFlaskアプリケーションを提供する方法
序章
このガイドでは、Ubuntu16.04でFlaskマイクロフレームワークを使用して簡単なPythonアプリケーションをセットアップします。 この記事の大部分は、アプリケーションを起動するようにGunicornアプリケーションサーバーを設定し、フロントエンドのリバースプロキシとして機能するようにNginxを設定する方法について説明します。
前提条件
このガイドを開始する前に、サーバーでroot以外のユーザーを構成しておく必要があります。 このユーザーは、管理機能を実行できるように、sudo
特権を持っている必要があります。 これを設定する方法については、初期サーバー設定ガイドに従ってください。
アプリケーションサーバーがFlaskアプリとの通信に使用するWSGI仕様の詳細については、このガイドのリンクされたセクションをご覧ください。 これらの概念を理解すると、このガイドを理解しやすくなります。
続行する準備ができたら、読み進めてください。
Ubuntuリポジトリからコンポーネントをインストールします
最初のステップは、リポジトリから必要なすべてのピースをインストールすることです。 Pythonコンポーネントをインストールして管理するために、Pythonパッケージマネージャーであるpip
をインストールします。 また、Gunicornコンポーネントの一部を構築するために必要なPython開発ファイルも入手します。 Nginxもインストールします。
ローカルパッケージインデックスを更新してから、パッケージをインストールします。 必要な特定のパッケージは、プロジェクトで使用しているPythonのバージョンによって異なります。
Python 2 を使用している場合は、次のように入力します。
- sudo apt-get update
- sudo apt-get install python-pip python-dev nginx
代わりに、 Python 3 を使用している場合は、次のように入力します。
- sudo apt-get update
- sudo apt-get install python3-pip python3-dev nginx
Python仮想環境を作成する
次に、Flaskアプリケーションをシステム上の他のPythonファイルから分離するために、仮想環境をセットアップします。
pip
を使用してvirtualenv
パッケージをインストールすることから始めます。
Python 2 を使用している場合は、次のように入力します。
- sudo pip install virtualenv
Python 3 を使用している場合は、次のように入力します。
- sudo pip3 install virtualenv
これで、Flaskプロジェクトの親ディレクトリを作成できます。 作成後、ディレクトリに移動します。
- mkdir ~/myproject
- cd ~/myproject
次のように入力することで、FlaskプロジェクトのPython要件を保存する仮想環境を作成できます。
- virtualenv myprojectenv
これにより、Pythonとpip
のローカルコピーが、プロジェクトディレクトリ内のmyprojectenv
というディレクトリにインストールされます。
仮想環境内にアプリケーションをインストールする前に、それをアクティブ化する必要があります。 次のように入力してください。
- source myprojectenv/bin/activate
プロンプトが変わり、仮想環境内で操作していることを示します。 このようになります(myprojectenv)user@host:~/myproject$
。
Flaskアプリケーションをセットアップする
仮想環境にいるので、FlaskとGunicornをインストールして、アプリケーションの設計を開始できます。
FlaskとGunicornをインストールします
pip
のローカルインスタンスを使用して、FlaskとGunicornをインストールできます。 次のコマンドを入力して、これら2つのコンポーネントを取得します。
ノート
使用しているPythonのバージョンに関係なく、仮想環境がアクティブ化されている場合は、pip
コマンドを使用する必要があります(pip3
ではありません)。
- pip install gunicorn flask
サンプルアプリを作成する
Flaskが利用可能になったので、簡単なアプリケーションを作成できます。 Flaskはマイクロフレームワークです。 よりフル機能のフレームワークが持つ可能性のあるツールの多くは含まれていません。主に、Webアプリケーションの初期化を支援するためにプロジェクトにインポートできるモジュールとして存在します。
アプリケーションはもっと複雑かもしれませんが、Flaskアプリを単一のファイルで作成します。これをmyproject.py
と呼びます。
- nano ~/myproject/myproject.py
このファイル内に、アプリケーションコードを配置します。 基本的に、フラスコをインポートして、Flaskオブジェクトをインスタンス化する必要があります。 これを使用して、特定のルートが要求されたときに実行する必要がある関数を定義できます。
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を開きます。
- sudo ufw allow 5000
これで、次のように入力して、Flaskアプリをテストできます。
- python myproject.py
サーバーのドメイン名またはIPアドレスにアクセスし、続いてWebブラウザで:5000
にアクセスします。
http://server_domain_or_IP:5000
次のように表示されます。
終了したら、ターミナルウィンドウでCTRL-Cを数回押して、Flask開発サーバーを停止します。
WSGIエントリポイントを作成する
次に、アプリケーションのエントリポイントとして機能するファイルを作成します。 これにより、Gunicornサーバーがアプリケーションと対話する方法がわかります。
ファイルをwsgi.py
と呼びます。
- nano ~/myproject/wsgi.py
ファイルは非常にシンプルです。アプリケーションからFlaskインスタンスをインポートして、実行するだけです。
from myproject import app
if __name__ == "__main__":
app.run()
終了したら、ファイルを保存して閉じます。
プロジェクトにサービスを提供するGunicornの能力をテストする
先に進む前に、Gunicornが正しく機能することを確認する必要があります。
これを行うには、エントリポイントの名前を渡すだけです。 これは、モジュールの名前(通常、.py
拡張子を差し引いたもの)とアプリケーション内の呼び出し可能オブジェクトの名前で構成されます。 この場合、これはwsgi:app
になります。
また、公開されているインターフェイスで開始されるように、バインドするインターフェイスとポートを指定します。
- cd ~/myproject
- gunicorn --bind 0.0.0.0:5000 wsgi:app
サーバーのドメイン名またはIPアドレスにアクセスし、Webブラウザの末尾に:5000を追加します。
http://server_domain_or_IP:5000
アプリケーションの出力が再び表示されるはずです。
正常に機能していることを確認したら、ターミナルウィンドウでCTRL-Cを押します。
これで仮想環境が完成したので、非アクティブ化できます。
- deactivate
すべてのPythonコマンドは、システムのPython環境を再び使用するようになります。
systemdユニットファイルを作成する
次に注意する必要があるのは、systemdサービスユニットファイルです。 systemdユニットファイルを作成すると、Ubuntuのinitシステムが自動的にGunicornを起動し、サーバーが起動するたびにFlaskアプリケーションを提供できるようになります。
/ etc / systemd/systemディレクトリ内に.serviceで終わるユニットファイルを作成して開始します。
- sudo nano /etc/systemd/system/myproject.service
内部では、メタデータと依存関係を指定するために使用される[Unit]
セクションから始めます。 ここにサービスの説明を入力し、ネットワークターゲットに到達した後にのみこれを開始するようにinitシステムに指示します。
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
次に、[Service]
セクションを開きます。 プロセスを実行するユーザーとグループを指定します。 プロセスは関連するすべてのファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を付与します。 NginxがGunicornプロセスと簡単に通信できるように、www-data
グループにグループ所有権を付与します。
次に、作業ディレクトリをマップし、PATH
環境変数を設定して、プロセスの実行可能ファイルが(仮想環境内で)どこにあるかをinitシステムが認識できるようにします。 次に、サービスを開始するコマンドを指定します。 Systemdでは、仮想環境内にインストールされているGunicorn実行可能ファイルへのフルパスを指定する必要があります。
3つのワーカープロセスを開始するように指示します(必要に応じてこれを調整します)。 また、myproject.sock
というプロジェクトディレクトリ内にUnixソケットファイルを作成してバインドするように指示します。 007
のumask値を設定して、他のアクセスを制限しながら、所有者とグループへのアクセスを許可するソケットファイルが作成されるようにします。 最後に、WSGIエントリポイントのファイル名と呼び出し可能なPythonを次の場所に渡す必要があります。
[Unit]
Description=Gunicorn 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/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
最後に、[インストール]セクションを追加します。 これにより、起動時にサービスを開始できるようにした場合に、このサービスを何にリンクするかがsystemdに通知されます。 このサービスは、通常のマルチユーザーシステムが稼働しているときに開始する必要があります。
[Unit]
Description=Gunicorn 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/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
これで、systemdサービスファイルが完成しました。 今すぐ保存して閉じます。
これで、作成したGunicornサービスを開始し、起動時に開始するように有効にすることができます。
- sudo systemctl start myproject
- sudo systemctl enable myproject
リクエストをプロキシするためのNginxの構成
これで、Gunicornアプリケーションサーバーが稼働し、プロジェクトディレクトリのソケットファイルに対するリクエストを待機しているはずです。 構成ファイルにいくつかの小さな追加を行うことにより、そのソケットにWeb要求を渡すようにNginxを構成する必要があります。
Nginxのsites-available
ディレクトリに新しいサーバーブロック構成ファイルを作成することから始めます。 ガイドの残りの部分と一致させるために、これを単にmyproject
と呼びます。
- sudo nano /etc/nginx/sites-available/myproject
サーバーブロックを開き、デフォルトのポート80でリッスンするようにNginxに指示します。 また、サーバーのドメイン名またはIPアドレスのリクエストにこのブロックを使用するように指示する必要があります。
server {
listen 80;
server_name server_domain_or_IP;
}
追加する必要がある他の唯一のものは、すべてのリクエストに一致するロケーションブロックです。 このブロック内に、設定する必要のあるいくつかの一般的なプロキシパラメータを指定するproxy_params
ファイルを含めます。 次に、proxy_pass
ディレクティブを使用して定義したソケットにリクエストを渡します。
server {
listen 80;
server_name server_domain_or_IP;
location / {
include proxy_params;
proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
}
}
実際、アプリケーションを提供するために必要なのはこれだけです。 終了したら、ファイルを保存して閉じます。
作成したNginxサーバーブロック構成を有効にするには、ファイルをsites-enabled
ディレクトリにリンクします。
- sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
そのディレクトリにあるファイルを使用して、次のように入力して構文エラーをテストできます。
- sudo nginx -t
これが問題を示さずに戻った場合は、Nginxプロセスを再起動して、新しい構成を読み取ることができます。
- sudo systemctl restart nginx
最後に行う必要があるのは、ファイアウォールを再度調整することです。 ポート5000を介してアクセスする必要がなくなったため、そのルールを削除できます。 次に、Nginxサーバーへのアクセスを許可できます。
- sudo ufw delete allow 5000
- sudo ufw allow 'Nginx Full'
これで、Webブラウザでサーバーのドメイン名またはIPアドレスにアクセスできるようになります。
http://server_domain_or_IP
アプリケーションの出力が表示されます。
ノート
Nginxを構成したら、次のステップはSSL/TLSを使用してサーバーへのトラフィックを保護することです。 これがないと、パスワードを含むすべての情報がプレーンテキストでネットワーク経由で送信されるため、これは重要です。
トラフィックを保護するためにSSL証明書を取得する最も簡単な方法は、Let’sEncryptを使用することです。 このガイドに従って、Ubuntu16.04でLet’sEncryptwithNginxを設定します。
結論
このガイドでは、Python仮想環境内に単純なFlaskアプリケーションを作成しました。 WSGI対応のアプリケーションサーバーがWSGIエントリポイントとインターフェイスできるようにWSGIエントリポイントを作成し、この機能を提供するようにGunicornアプリサーバーを構成します。 その後、起動時にアプリケーションサーバーを自動的に起動するsystemdユニットファイルを作成しました。 Webクライアントトラフィックをアプリケーションサーバーに渡し、外部リクエストを中継するNginxサーバーブロックを作成しました。
Flaskは非常にシンプルですが、非常に柔軟なフレームワークであり、構造や設計をあまり制限することなく、アプリケーションに機能を提供することを目的としています。 このガイドで説明されている一般的なスタックを使用して、設計したフラスコアプリケーションにサービスを提供できます。