Ubuntu20.04でuWSGIとNginxを使用してFlaskアプリケーションを提供する方法
このチュートリアルの以前のバージョンは、 JustinEllingwoodによって作成されました。
序章
このガイドでは、Ubuntu20.04でFlaskマイクロフレームワークを使用してPythonアプリケーションを構築します。 この記事の大部分は、 uWSGIアプリケーションサーバーをセットアップする方法と、アプリケーションを起動し、フロントエンドリバースプロキシとして機能するようにNginxを構成する方法について説明します。
前提条件
このガイドを開始する前に、次のものが必要です。
-
Ubuntu 20.04がインストールされ、sudo権限を持つ非rootユーザーのサーバー。 ガイダンスについては、初期サーバーセットアップガイドに従ってください。
-
Ubuntu 20.04にNginxをインストールする方法のステップ1から3に従って、Nginxをインストールしました。
-
サーバーを指すように構成されたドメイン名。 Namecheap で購入するか、Freenomで無料で入手できます。 ドメインとDNSに関する関連するドキュメントに従うことで、ドメインをDigitalOceanにポイントする方法を学ぶことができます。 このチュートリアルは、次のDNSレコードを作成したことを前提としています。
- とのAレコード
your_domain
サーバーのパブリックIPアドレスを指します。 - とのAレコード
www.your_domain
サーバーのパブリックIPアドレスを指します。
- とのAレコード
さらに、uWSGI、このガイドでセットアップするアプリケーションサーバー、およびWSGI仕様についてある程度理解しておくと役立つ場合があります。 定義と概念に関するこのディスカッションでは、両方について詳しく説明します。
ステップ1—Ubuntuリポジトリからコンポーネントをインストールする
最初のステップは、Ubuntuリポジトリから必要なすべての部分をインストールすることです。 インストールする必要のあるパッケージには次のものが含まれます pip
、Pythonパッケージマネージャー。Pythonコンポーネントを管理します。 また、uWSGIのビルドに必要なPython開発ファイルも入手できます。
まず、ローカルパッケージインデックスを更新します。
- sudo apt update
次に、Python環境を構築できるようにするパッケージをインストールします。 これらには以下が含まれます python3-pip
、堅牢なプログラミング環境に必要ないくつかのパッケージと開発ツールとともに:
- sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
これらのパッケージを配置すると、プロジェクトの仮想環境の作成に進む準備が整います。
ステップ2—Python仮想環境を作成する
Python仮想環境は、特定のバージョンのPythonと特定のプロジェクトに必要なPythonモジュールを含む自己完結型のプロジェクトディレクトリです。 これは、それぞれの依存関係を個別に管理することにより、同じシステム上の他のアプリケーションから1つのアプリケーションを分離するのに役立ちます。 このステップでは、Flaskアプリケーションを実行するPython仮想環境をセットアップします。
インストールすることから始めます python3-venv
パッケージ、インストールします venv
モジュール:
- sudo apt install python3-venv
次に、Flaskプロジェクトの親ディレクトリを作成します。
- mkdir ~/myproject
作成後、ディレクトリに移動します。
- cd ~/myproject
次のように入力して、FlaskプロジェクトのPython要件を保存する仮想環境を作成します。
- python3.8 -m venv myprojectenv
これにより、Pythonのローカルコピーがインストールされ、 pip
と呼ばれるディレクトリに myprojectenv
プロジェクトディレクトリ内。
仮想環境内にアプリケーションをインストールする前に、それをアクティブ化する必要があります。 次のように入力してください。
- source myprojectenv/bin/activate
プロンプトが変わり、仮想環境内で操作していることを示します。 次のようになります。 (myprojectenv)user@host:~/myproject$
.
ステップ3—Flaskアプリケーションのセットアップ
これで仮想環境ができたので、FlaskとuWSGIをインストールして、アプリケーションの設計を開始できます。
まず、インストールします wheel
のローカルインスタンスで pip
ホイールアーカイブがない場合でもパッケージが確実にインストールされるようにするには、次のようにします。
- pip install wheel
注:使用しているPythonのバージョンに関係なく、仮想環境がアクティブ化されている場合は、 pip
コマンド(ではない pip3
).
次に、FlaskとuWSGIをインストールします。
- pip install uwsgi flask
サンプルアプリの作成
Flaskを使用できるようになったので、サンプルアプリケーションを作成できます。 Flaskはマイクロフレームワークです。 よりフル機能のフレームワークが持つ可能性のあるツールの多くは含まれていません。主に、Webアプリケーションの初期化を支援するためにプロジェクトにインポートできるモジュールとして存在します。
アプリケーションはもっと複雑かもしれませんが、この例では、Flaskアプリを1つのファイルで作成します。 myproject.py
:
- nano ~/myproject/myproject.py
アプリケーションコードはこのファイルに存在します。 Flaskをインポートし、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')
基本的に、これはルートドメインにアクセスする人に提示するコンテンツを定義します。 終了したら、ファイルを保存して閉じます。 使用した場合 nano
前の例のようにファイルを編集するには、を押して編集します CTRL + X
, Y
、 その後 ENTER
.
サーバーの初期設定ガイドに従っている場合は、UFWファイアウォールを有効にする必要があります。 アプリケーションをテストするには、ポートへのアクセスを許可する必要があります 5000
:
- sudo ufw allow 5000
これで、次のように入力して、Flaskアプリをテストできます。
- python myproject.py
このサーバー設定を本番環境で使用しないように注意を促す便利な警告を含む、次のような出力が表示されます。
Output* Serving Flask app "myproject" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
サーバーのIPアドレスにアクセスしてから :5000
Webブラウザで:
http://your_server_ip:5000
次のようなものが表示されます。
終了したら、 CTRL + C
ターミナルウィンドウでFlask開発サーバーを停止します。
WSGIエントリポイントの作成
次に、アプリケーションのエントリポイントとして機能するファイルを作成します。 これにより、uWSGIサーバーとの対話方法がわかります。
ファイルを呼び出す wsgi.py
:
- nano ~/myproject/wsgi.py
このファイルで、アプリケーションからFlaskインスタンスをインポートして、実行します。
from myproject import app
if __name__ == "__main__":
app.run()
終了したら、ファイルを保存して閉じます。
ステップ4—uWSGIを構成する
これで、アプリケーションはエントリポイントが確立された状態で作成されました。 uWSGIの構成に進むことができます。
uWSGIがアプリケーションにサービスを提供できるかどうかのテスト
最初のステップとして、uWSGIがアプリケーションにエントリポイントの名前を渡して、アプリケーションを正しく提供できることを確認するためのテストを行います。 これは、モジュールの名前で構成されます(マイナス .py
拡張機能)に加えて、アプリケーション内の呼び出し可能オブジェクトの名前。 このチュートリアルのコンテキストでは、エントリポイントの名前は次のとおりです。 wsgi:app
.
また、公開されているインターフェイスとプロトコルで開始されるようにソケットを指定して、ソケットの代わりにHTTPを使用するようにします。 uwsgi
バイナリプロトコル。 同じポート番号を使用し、 5000
、以前に開いたこと:
- uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app
でサーバーのIPアドレスにアクセスします :5000
Webブラウザの最後に再び追加されます:
http://your_server_ip:5000
アプリケーションの出力が再び表示されます。
正常に機能していることを確認したら、を押します CTRL + C
ターミナルウィンドウで。
これで仮想環境の使用が完了したので、仮想環境を非アクティブ化できます。
- deactivate
すべてのPythonコマンドは、システムのPython環境を再び使用するようになります。
uWSGI構成ファイルの作成
uWSGIがアプリケーションに対応できることをテストしましたが、最終的には、長期間使用するためにより堅牢なものが必要になります。 これに関連するオプションを使用して、uWSGI構成ファイルを作成できます。
そのファイルをプロジェクトディレクトリに配置し、それを呼び出します myproject.ini
:
- nano ~/myproject/myproject.ini
内部で、ファイルを開始します [uwsgi]
uWSGIが設定を適用することを認識できるようにヘッダー。 その下で、モジュール自体を指定します— wsgi.py
ファイルから拡張子を引いたもの—およびファイル内の呼び出し可能ファイル app
:
[uwsgi]
module = wsgi:app
次に、uWSGIにマスターモードで起動し、実際の要求を処理するために5つのワーカープロセスを生成するように指示します。
[uwsgi]
module = wsgi:app
master = true
processes = 5
テストしているときに、ネットワークポートでuWSGIを公開しました。 ただし、実際のクライアント接続を処理するためにNginxを使用することになります。これにより、リクエストがuWSGIに渡されます。 これらのコンポーネントは同じコンピューター上で動作するため、Unixソケットの方が高速で安全です。 ソケットを呼び出す myproject.sock
このディレクトリに配置します。
次に、ソケットの権限を変更します。 後でuWSGIプロセスの所有権をNginxグループに付与するので、ソケットのグループ所有者がソケットから情報を読み取ったり書き込んだりできることを確認する必要があります。 また、を追加します vacuum
オプションを選択し、trueに設定します。 これにより、プロセスが停止したときにソケットがクリーンアップされます。
[uwsgi]
module = wsgi:app
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true
最後にすべきことは、 die-on-term
オプション。 これは、initシステムとuWSGIが各プロセス信号の意味について同じ仮定を持つことを保証するのに役立ちます。 これを設定すると、2つのシステムコンポーネントが調整され、期待される動作が実装されます。
[uwsgi]
module = wsgi:app
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true
die-on-term = true
これらの行は、コマンドラインから行ったようにプロトコルを指定していないことに気付いたかもしれません。 これは、デフォルトでは、uWSGIが uwsgi
プロトコル、他のサーバーと通信するように設計された高速バイナリプロトコル。 Nginxはこのプロトコルをネイティブに話すことができるため、HTTPによる通信を強制するよりもこれを使用する方が適切です。
終了したら、ファイルを保存して閉じます。
これで、uWSGIがシステムに構成されます。 Flaskアプリケーションの管理方法をより柔軟にするために、systemdサービスとして実行するようにアプリケーションを構成できるようになりました。
ステップ5—systemdユニットファイルを作成する
Systemdは、システムサービスを管理するための高速で柔軟なinitモデルを提供するツールスイートです。 systemdユニットファイルを作成すると、Ubuntuのinitシステムが自動的にuWSGIを起動し、サーバーが起動するたびにFlaskアプリケーションを提供できるようになります。
で終わるユニットファイルを作成します .service
以内 /etc/systemd/system
開始するディレクトリ:
- sudo nano /etc/systemd/system/myproject.service
内部では、 [Unit]
セクション。メタデータと依存関係を指定するために使用されます。 次に、ここにサービスの説明を入力し、ネットワークターゲットに到達した後にのみこれを開始するようにinitシステムに指示します。
[Unit]
Description=uWSGI instance to serve myproject
After=network.target
次に、 [Service]
セクション。 これにより、プロセスを実行するユーザーとグループが指定されます。 プロセスは関連するすべてのファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を与えます。 次に、 www-data グループにグループの所有権を付与して、NginxがuWSGIプロセスと簡単に通信できるようにします。 ここでのユーザー名を自分のユーザー名に置き換えることを忘れないでください。
[Unit]
Description=uWSGI instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
次に、作業ディレクトリをマップし、 PATH
プロセスの実行可能ファイルが仮想環境内にあることをinitシステムが認識できるようにするための環境変数。 また、サービスを開始するコマンドを指定してください。 Systemdでは、仮想環境内にインストールされているuWSGI実行可能ファイルへのフルパスを指定する必要があります。 ここでは、の名前を渡します .ini
プロジェクトディレクトリに作成した構成ファイル。
ユーザー名とプロジェクトパスを独自の情報に置き換えることを忘れないでください。
[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に通知されます。 この場合、通常のマルチユーザーシステムが稼働しているときにサービスを開始するように設定します。
[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サービスを開始できます。
- sudo systemctl start myproject
次に、起動時に開始するように有効にします。
- sudo systemctl enable myproject
ステータスを確認します。
- sudo systemctl status myproject
次のような出力が表示されます。
Output● myproject.service - uWSGI instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-05-20 13:21:39 UTC; 8h ago
Main PID: 22146 (uwsgi)
Tasks: 6 (limit: 2345)
Memory: 25.5M
CGroup: /system.slice/myproject.service
├─22146 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
├─22161 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
├─22162 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
├─22163 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
├─22164 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
└─22165 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
エラーが表示された場合は、チュートリアルを続行する前に必ず解決してください。 それ以外の場合は、リクエストをに渡すようにNginxインストールの構成に進むことができます myproject.sock
ソケット。
ステップ6—リクエストをプロキシするためのNginxの設定
これで、uWSGIアプリケーションサーバーが稼働し、プロジェクトディレクトリのソケットファイルに対する要求を待機しています。 このステップでは、を使用してそのソケットにWebリクエストを渡すようにNginxを構成します uwsgi
プロトコル。
Nginxで新しいサーバーブロック構成ファイルを作成することから始めます sites-available
ディレクトリ。 ガイドの残りの部分と一致させるために、次の例ではこれを次のように参照しています。 myproject
:
- sudo nano /etc/nginx/sites-available/myproject
サーバーブロックを開き、Nginxにデフォルトポートでリッスンするように指示します 80
. さらに、サーバーのドメイン名のリクエストにこのブロックを使用するように指示します。
server {
listen 80;
server_name your_domain www.your_domain;
}
次に、すべてのリクエストに一致するロケーションブロックを追加します。 このブロック内に、 uwsgi_params
設定する必要のあるいくつかの一般的なuWSGIパラメータを指定するファイル。 次に、を使用して定義したソケットにリクエストを渡します。 uwsgi_pass
指令:
server {
listen 80;
server_name your_domain www.your_domain;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/sammy/myproject/myproject.sock;
}
}
終了したら、ファイルを保存して閉じます。
作成したNginxサーバーブロック構成を有効にするには、ファイルをにリンクします sites-enabled
ディレクトリ:
- sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Nginxをインストールすると、プロセスは次の名前のサーバーブロック構成ファイルを自動的にセットアップします。 default
の中に sites-available
ディレクトリを作成し、そのファイルと sites-enabled
ディレクトリ。 このシンボリックリンクをそのままにしておくと、 default
構成により、サイトの読み込みがブロックされます。 次のコマンドを使用して、リンクを削除できます。
- sudo unlink /etc/nginx/sites-enabled/default
その後、次のように入力して構文エラーをテストできます。
- sudo nginx -t
これが問題を示さずに戻った場合は、Nginxプロセスを再起動して、新しい構成を読み取ります。
- sudo systemctl restart nginx
最後に、ファイアウォールをもう一度調整します。 ポート経由でアクセスする必要がなくなりました 5000
、そのため、そのルールを削除できます。 次に、Nginxサーバーへのアクセスを許可できます。
- sudo ufw delete allow 5000
- sudo ufw allow 'Nginx Full'
これで、Webブラウザでサーバーのドメイン名に移動できるようになります。
http://your_domain
アプリケーションの出力が表示されます。
エラーが発生した場合は、以下を確認してください。
sudo less /var/log/nginx/error.log
:Nginxエラーログをチェックします。sudo less /var/log/nginx/access.log
:Nginxアクセスログをチェックします。sudo journalctl -u nginx
:Nginxプロセスログをチェックします。sudo journalctl -u myproject
:FlaskアプリのuWSGIログを確認します。
ステップ7—アプリケーションの保護
サーバーへのトラフィックを確実に保護するには、ドメインのSSL証明書を取得します。 これを行うには、 Let’s Encrypt から無料の証明書を取得する、自己署名証明書を生成する、商用プロバイダーから証明書を購入するなど、複数の方法があります。 便宜上、このチュートリアルではLet’sEncryptから無料の証明書を取得する方法について説明します。
まず、CertbotとそのNginxプラグインをインストールします apt
:
- sudo apt install certbot python3-certbot-nginx
Certbotは、プラグインを介してSSL証明書を取得するためのさまざまな方法を提供します。 Nginxプラグインは、Nginxの再構成と、必要に応じて構成の再読み込みを処理します。 このプラグインを使用するには、次のように入力します。
- sudo certbot --nginx -d your_domain -d www.your_domain
これは実行されます certbot
とともに --nginx
プラグイン、使用 -d
証明書を有効にする名前を指定します。
初めてのランニングの場合 certbot
このサーバーでは、メールアドレスを入力して利用規約に同意するよう求められます。 そうした後、 certbot
Let’s Encryptサーバーと通信し、チャレンジを実行して、証明書を要求しているドメインを制御していることを確認します。
それが成功した場合、 certbot
HTTPS設定をどのように構成するかを尋ねられます。
OutputPlease choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):
選択してからヒット ENTER
. 構成が更新され、Nginxがリロードして新しい設定を取得します。 certbot
プロセスが成功し、証明書が保存されている場所を通知するメッセージで締めくくられます。
OutputIMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/your_domain/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/your_domain/privkey.pem
Your cert will expire on 2020-08-18. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
前提条件でNginxのインストール手順に従った場合、冗長なHTTPプロファイルの許容量は不要になります。
- sudo ufw delete allow 'Nginx HTTP'
構成を確認するには、を使用してもう一度ドメインに移動します https://
:
https://your_domain
アプリケーションの出力が、サイトが保護されていることを示すブラウザのセキュリティインジケータとともにもう一度表示されます。
結論
このガイドでは、Python仮想環境内で基本的なFlaskアプリケーションを作成して保護しました。 次に、WSGI対応のアプリケーションサーバーがWSGIエントリポイントとインターフェイスできるようにWSGIエントリポイントを作成し、この機能を提供するようにuWSGIアプリサーバーを構成しました。 その後、起動時にアプリケーションサーバーを自動的に起動するsystemdサービスファイルを作成しました。 また、Webクライアントトラフィックをアプリケーションサーバーに渡すNginxサーバーブロックを作成して、外部リクエストを中継し、Let’sEncryptを使用してサーバーへのトラフィックを保護しました。
Flaskは、構造や設計をあまり制限することなく、アプリケーションに機能を提供することを目的とした、シンプルでありながら柔軟なフレームワークです。 このガイドで説明されている一般的なスタックを使用して、設計したフラスコアプリケーションを提供できます。