前書き
このガイドでは、Ubuntu 18.04でFlaskマイクロフレームワークを使用してPythonアプリケーションを構築します。 この記事の大部分は、Gunicorn application serverを設定する方法と、アプリケーションを起動し、フロントエンドのリバースプロキシとして機能するようにNginxを構成する方法について説明します。
前提条件
このガイドを開始する前に、次のものが必要です。
-
Ubuntu 18.04がインストールされたサーバーと、sudo特権を持つ非rootユーザー。 ガイダンスについては、initial server setup guideに従ってください。
-
How To Install Nginx on Ubuntu 18.04のステップ1と2に従って、Nginxがインストールされました。
-
サーバーを指すように構成されたドメイン名。 Namecheapで購入するか、Freenomで無料で入手できます。 関連するdocumentation on domains and DNSをたどることで、ドメインをDigitalOceanにポイントする方法を学ぶことができます。 次のDNSレコードを必ず作成してください。
-
サーバーのパブリックIPアドレスを指す
your_domain
を含むAレコード。 -
サーバーのパブリックIPアドレスを指す
www.your_domain
を含むAレコード。
-
-
GunicornサーバーがFlaskアプリケーションと通信するために使用するWSGI仕様に精通している。 This discussionはWSGIをより詳細にカバーしています。
[[step-1 -—- installing-the-components-from-the-ubuntu-repositories]] ==ステップ1—Ubuntuリポジトリからのコンポーネントのインストール
最初のステップは、Ubuntuリポジトリから必要なすべてのピースをインストールすることです。 これには、Pythonコンポーネントを管理するPythonパッケージマネージャーであるpip
が含まれます。 また、Gunicornコンポーネントの一部を構築するために必要なPython開発ファイルも入手します。
まず、ローカルパッケージインデックスを更新し、Python環境を構築できるパッケージをインストールしましょう。 これらには、堅牢なプログラミング環境に必要ないくつかのパッケージと開発ツールに加えて、python3-pip
が含まれます。
sudo apt update
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
これらのパッケージを用意したら、プロジェクトの仮想環境の作成に進みましょう。
[[step-2 -—- creating-a-python-virtual-environment]] ==ステップ2—Python仮想環境の作成
次に、Flaskアプリケーションをシステム上の他のPythonファイルから分離するために、仮想環境を設定します。
python3-venv
パッケージをインストールすることから始めます。これにより、venv
モジュールがインストールされます。
sudo apt install python3-venv
次に、Flaskプロジェクトの親ディレクトリを作成しましょう。 作成後、ディレクトリに移動します。
mkdir ~/myproject
cd ~/myproject
次を入力して、FlaskプロジェクトのPython要件を保存する仮想環境を作成します。
python3.6 -m venv myprojectenv
これにより、Pythonとpip
のローカルコピーがプロジェクトディレクトリ内のmyprojectenv
というディレクトリにインストールされます。
仮想環境内にアプリケーションをインストールする前に、アクティブ化する必要があります。 次のように入力してください:
source myprojectenv/bin/activate
プロンプトが変わり、仮想環境内で操作していることが示されます。 (myprojectenv)user@host:~/myproject$
のようになります。
[[step-3 -—- setting-up-a-flask-application]] ==ステップ3—Flaskアプリケーションのセットアップ
仮想環境になったので、FlaskとGunicornをインストールして、アプリケーションの設計を開始できます。
まず、pip
のローカルインスタンスを使用してwheel
をインストールし、ホイールアーカイブがない場合でもパッケージがインストールされるようにします。
pip install wheel
Note
[.note]#使用しているPythonのバージョンに関係なく、仮想環境をアクティブ化するときは、(pip3
ではなく)pip
コマンドを使用する必要があります。
#
次に、FlaskとGunicornをインストールしましょう。
pip install gunicorn flask
サンプルアプリの作成
Flaskが使用可能になったので、簡単なアプリケーションを作成できます。 フラスコはマイクロフレームワークです。 より多くのフル機能のフレームワークが提供するツールの多くは含まれておらず、主にプロジェクトにインポートしてWebアプリケーションの初期化を支援できるモジュールとして存在します。
アプリケーションはもっと複雑かもしれませんが、myproject.py
という単一のファイルにFlaskアプリを作成します。
nano ~/myproject/myproject.py
アプリケーションコードはこのファイルに保存されます。 Flaskをインポートし、Flaskオブジェクトをインスタンス化します。 これを使用して、特定のルートが要求されたときに実行する必要がある機能を定義できます。
~/myproject/myproject.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello There!
"
if __name__ == "__main__":
app.run(host='0.0.0.0')
これは基本的に、ルートドメインにアクセスしたときに表示するコンテンツを定義します。 完了したら、ファイルを保存して閉じます。
サーバーの初期セットアップガイドに従った場合、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)
WebブラウザでサーバーのIPアドレスに続いて:5000
にアクセスします。
http://your_server_ip:5000
このようなものが見えるはずです。
終了したら、ターミナルウィンドウでCTRL-C
を押して、Flask開発サーバーを停止します。
WSGIエントリポイントの作成
次に、アプリケーションのエントリポイントとして機能するファイルを作成しましょう。 これにより、Gunicornサーバーにアプリケーションとの対話方法が通知されます。
ファイルをwsgi.py
と呼びましょう:
nano ~/myproject/wsgi.py
このファイルでは、アプリケーションからFlaskインスタンスをインポートして実行します。
~/myproject/wsgi.py
from myproject import app
if __name__ == "__main__":
app.run()
完了したら、ファイルを保存して閉じます。
[[step-4 -—- configuring-gunicorn]] ==ステップ4—Gunicornの構成
これで、エントリポイントが確立されたアプリケーションが作成されました。 Gunicornの構成に進むことができます。
先に進む前に、Gunicornがアプリケーションを正しく提供できることを確認する必要があります。
これを行うには、エントリポイントの名前を渡すだけです。 これは、モジュールの名前(.py
拡張子を除く)と、アプリケーション内の呼び出し可能オブジェクトの名前として構成されます。 私たちの場合、これはwsgi:app
です。
また、公開するインターフェイスでアプリケーションが開始されるように、バインドするインターフェイスとポートを指定します。
cd ~/myproject
gunicorn --bind 0.0.0.0:5000 wsgi:app
次のような出力が表示されるはずです。
Output[2018-07-13 19:35:13 +0000] [28217] [INFO] Starting gunicorn 19.9.0
[2018-07-13 19:35:13 +0000] [28217] [INFO] Listening at: http://0.0.0.0:5000 (28217)
[2018-07-13 19:35:13 +0000] [28217] [INFO] Using worker: sync
[2018-07-13 19:35:13 +0000] [28220] [INFO] Booting worker with pid: 28220
Webブラウザの末尾に:5000
を追加して、サーバーのIPアドレスに再度アクセスします。
http://your_server_ip:5000
アプリケーションの出力が表示されます。
正常に機能していることを確認したら、ターミナルウィンドウでCTRL-C
を押します。
これで仮想環境が完成したので、非アクティブ化できます。
deactivate
Pythonコマンドはすべて、システムのPython環境を再び使用するようになります。
次に、systemdサービスユニットファイルを作成しましょう。 systemdユニットファイルを作成すると、Ubuntuの初期化システムがGunicornを自動的に起動し、サーバーが起動するたびにFlaskアプリケーションを提供できるようになります。
開始するには、/etc/systemd/system
ディレクトリ内に.service
で終わるユニットファイルを作成します。
sudo nano /etc/systemd/system/myproject.service
内部では、メタデータと依存関係を指定するために使用される[Unit]
セクションから始めます。 ここにサービスの説明を入れて、ネットワーキングターゲットに到達した後にのみ開始するようにinitシステムに伝えましょう。
/etc/systemd/system/myproject.service
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
次に、[Service]
セクションを開きます。 これにより、プロセスを実行するユーザーとグループを指定します。 関連するすべてのファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を与えましょう。 また、www-data
グループにグループの所有権を与えて、NginxがGunicornプロセスと簡単に通信できるようにします。 ここのユーザー名をユーザー名に置き換えてください:
/etc/systemd/system/myproject.service
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
次に、作業ディレクトリをマップし、PATH
環境変数を設定して、プロセスの実行可能ファイルが仮想環境内にあることをinitシステムが認識できるようにします。 サービスを開始するコマンドも指定しましょう。 このコマンドは次のことを行います。
-
3つのワーカープロセスを開始します(ただし、必要に応じて調整する必要があります)
-
プロジェクトディレクトリ内にUnixソケットファイル
myproject.sock
を作成してバインドします。007
のumask値を設定して、所有者とグループへのアクセスを許可するソケットファイルが作成され、他のアクセスは制限します。 -
WSGIエントリポイントのファイル名と、そのファイル内で呼び出し可能なPythonを指定します(
wsgi:app
)
Systemdでは、仮想環境内にインストールされているGunicorn実行可能ファイルへのフルパスを指定する必要があります。
ユーザー名とプロジェクトパスを独自の情報に置き換えることを忘れないでください。
/etc/systemd/system/myproject.service
[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]
セクションを追加しましょう。 これにより、起動時に起動できるようにした場合、このサービスをリンクする対象がsystemdに指示されます。 通常のマルチユーザーシステムが稼働しているときにこのサービスを開始する必要があります。
/etc/systemd/system/myproject.service
[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
ステータスを確認しましょう:
sudo systemctl status myproject
次のような出力が表示されます。
Output● myproject.service - Gunicorn instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2018-07-13 14:28:39 UTC; 46s ago
Main PID: 28232 (gunicorn)
Tasks: 4 (limit: 1153)
CGroup: /system.slice/myproject.service
├─28232 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
├─28250 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
├─28251 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
└─28252 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
エラーが表示された場合は、チュートリアルを続行する前にエラーを解決してください。
[[step-5 -—- configuring-nginx-to-proxy-requests]] ==ステップ5—Nginxからプロキシリクエストへの設定
これで、Gunicornアプリケーションサーバーが起動して実行され、プロジェクトディレクトリ内のソケットファイルに対する要求を待機するはずです。 Nginxを設定して、設定ファイルに少し追加して、そのソケットにWebリクエストを渡すようにします。
Nginxのsites-available
ディレクトリに新しいサーバーブロック構成ファイルを作成することから始めます。 ガイドの残りの部分と一致させるために、これをmyproject
と呼びましょう。
sudo nano /etc/nginx/sites-available/myproject
サーバーブロックを開き、デフォルトのポート80
でリッスンするようにNginxに指示します。 また、サーバーのドメイン名のリクエストにこのブロックを使用するように伝えましょう。
/etc/nginx/sites-available/myproject
server {
listen 80;
server_name your_domain www.your_domain;
}
次に、すべてのリクエストに一致する場所ブロックを追加しましょう。 このブロック内に、設定する必要のあるいくつかの一般的なプロキシパラメータを指定するproxy_params
ファイルを含めます。 次に、proxy_pass
ディレクティブを使用して定義したソケットにリクエストを渡します。
/etc/nginx/sites-available/myproject
server {
listen 80;
server_name your_domain www.your_domain;
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ブラウザでサーバーのドメイン名に移動できるはずです。
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アプリのGunicornログを確認します。
[[ステップ-6 ---アプリケーションの保護]] ==ステップ6—アプリケーションの保護
サーバーへのトラフィックを安全に保つために、ドメインのSSL証明書を取得しましょう。 これを行うには、Let’s Encrypt、generating a self-signed certificate、またはbuying one from another providerから無料の証明書を取得し、How to Create a Self-signed SSL Certificate for Nginx in Ubuntu 18.04の手順2から6に従って、それを使用するようにNginxを構成するなど、複数の方法があります。 。 便宜上、オプション1を使用します。
まず、Certbot Ubuntuリポジトリを追加します。
sudo add-apt-repository ppa:certbot/certbot
受け入れるには、ENTER
を押す必要があります。
CertbotのNginxパッケージをapt
でインストールします。
sudo apt install python-certbot-nginx
Certbotは、プラグインを介してSSL証明書を取得するさまざまな方法を提供します。 Nginxプラグインは、必要に応じてNginxの再構成と構成の再読み込みを処理します。 このプラグインを使用するには、次を入力します。
sudo certbot --nginx -d your_domain -d www.your_domain
これは、--nginx
プラグインでcertbot
を実行し、-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 2018-07-23. 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エントリポイントを作成し、この機能を提供するようにGunicornアプリサーバーを構成しました。 その後、systemdサービスファイルを作成して、起動時にアプリケーションサーバーを自動的に起動しました。 また、Let's Encryptを使用して、Webクライアントトラフィックをアプリケーションサーバーに渡し、外部リクエストを中継し、サーバーへのトラフィックを保護するNginxサーバーブロックを作成しました。
Flaskは非常にシンプルですが、非常に柔軟なフレームワークであり、構造や設計に制限をかけすぎることなく、アプリケーションに機能を提供することを目的としています。 このガイドで説明されている一般的なスタックを使用して、設計したフラスコアプリケーションを提供できます。