PostgreSQL を使用した Python (Django または Flask) Web アプリを Azure にデプロイする
このチュートリアルでは、データドリブン Python Web アプリ (Django または Flask) を、Azure Database for PostgreSQL リレーショナル データベース サービスを使う Azure App Service にデプロイします。 Azure App Service は、Linux サーバー環境で Python をサポートしています。
このチュートリアルを完了するには、次のものが必要です。
- アクティブなサブスクリプションが含まれる Azure アカウント。 Azure アカウントがない場合は、無料で作成できます。
- Python と Flask による開発または Python と Django による開発に関する知識
- アクティブなサブスクリプションが含まれる Azure アカウント。 Azure アカウントがない場合は、無料で作成できます。
- Azure Developer CLI がインストールされていること。 Azure Developer CLI が既にインストールされているため、Azure Cloud Shell の手順に従うことができます。
- Python と Flask による開発または Python と Django による開発に関する知識
最後までスキップする
Azure Developer CLI がインストールされている場合、このチュートリアルで示されている完全に構成済みのサンプル アプリをデプロイし、Azure で実行されることを確認できます。 空の作業ディレクトリで次のコマンドを実行するだけで済みます。
azd auth login
azd init --template msdocs-flask-postgresql-sample-app
azd up
サンプル アプリケーション
Flask および Django フレームワークを使用したサンプルの Python アプリケーションがあり、このチュートリアルに沿って作業を進めるのに役立ちます。 ローカルで実行せずにデプロイする場合は、この部分をスキップしてください。
アプリケーションをローカルで実行するには、Python 3.7 以降と PostgreSQL をローカルにインストールしたことを確認します。 次に、サンプル リポジトリの starter-no-infra
ブランチをクローンして、リポジトリのルートに移動してください。
git clone -b starter-no-infra https://github.com/Azure-Samples/msdocs-flask-postgresql-sample-app
cd msdocs-flask-postgresql-sample-app
.env.sample ファイルをガイドとして、以下に示すような .env ファイルを作成します。 DBNAME
の値を、ローカルの PostgreSQL インスタンス内の既存データベースの名前に設定します。 ローカルの PostgreSQL インスタンスに応じて、DBHOST
、DBUSER
、DBPASS
の値を設定します。
DBNAME=<database name>
DBHOST=<database-hostname>
DBUSER=<db-user-name>
DBPASS=<db-password>
アプリの仮想環境を作成します。
py -m venv .venv
.venv\scripts\activate
依存関係をインストールする:
pip install -r requirements.txt
次のコマンドを使ってサンプル アプリケーションを実行します。
# Run database migration
flask db upgrade
# Run the app at http://127.0.0.1:5000
flask run
1. App Service と PostgreSQL を作成する
この手順では、Azure リソースを作成します。 このチュートリアルで使用する手順では、App Service と Azure Database for PostgreSQL を含む既定でセキュリティで保護された一連のリソースを作成します。 作成手順では、次のように指定します。
- 名前: Web アプリの名前。 Web アプリの DNS 名の一部として
https://<app-name>.azurewebsites.net
の形式で使われる名前です。 - 世界でアプリを物理的に実行するためのリージョン。
- アプリのランタイム スタック。 ここで、アプリに使う Python のバージョンを選びます。
- アプリのホスティング プラン。 これは、アプリの一連の機能と容量のスケーリングを含む価格レベルです。
- アプリのリソース グループ。 リソース グループを使うと、アプリケーションに必要なすべての Azure リソースを (論理コンテナーに) グループ化できます。
Azure portal にサインインし、以下の手順に従って Azure App Service リソースを作成します。
手順 1: Azure portal 内で次を実行します。
- Azure portal の上部にある検索バーに「Web app database」と入力します。
- [Marketplace] の見出しの下にある [Web アプリとデータベース] というラベルの付いた項目を選びます。 作成ウィザードに直接移動することもできます。
手順 2:[Web アプリとデータベースの作成] ページ内で、このフォームに次のように入力します。
- "リソース グループ" → [新規作成] を選び、msdocs-python-postgres-tutorial という名前を付けます。
- リージョン → 任意の近くの Azure リージョン。
- "名前" → msdocs-python-postgres-XYZ。XYZ は任意の 3 つのランダムな文字です。 この名前は Azure 全体で一意である必要があります。
- ランタイム スタック → Python 3.10。
- データベース → PostgreSQL - フレキシブル サーバーは、既定でデータベース エンジンとして選ばれています。 既定では、サーバー名とデータベース名も適切な値に設定されます。
- ホスティング プラン → Basic。 準備ができたら、後で運用価格レベルにスケールアップできます。
- [Review + create](レビュー + 作成) を選択します。
- 検証が完了した後、 [作成] を選択します。
手順 3: このデプロイは完了するまでに数分かかります。 デプロイが完了したら、[リソースに移動] ボタンを選択します。 App Service アプリに直接移動しますが、次のリソースが作成されます。
- リソース グループ → 作成されたすべてのリソースのコンテナーです。
- App Service プラン → App Service のコンピューティング リソースを定義します。 Basic レベルの Linux プランが作成されます。
- App Service → アプリを表し、App Service プランで実行されます。
- 仮想ネットワーク → App Service アプリと統合され、バックエンドのネットワーク トラフィックを分離します。
- Azure Database for PostgreSQL フレキシブル サーバー → 仮想ネットワーク内からのみアクセス可能です。 サーバー上にデータベースとユーザーが作成されます。
- プライベート DNS ゾーン → 仮想ネットワーク内の PostgreSQL サーバーの DNS 解決を有効にします。
2. 接続設定を編集する
作成ウィザードにより、接続変数がアプリの設定として自動的に生成されます。 アプリの設定は、接続のシークレットをコード リポジトリに残さないための 1 つの方法です。 シークレットをより安全な場所に移動する準備ができたら、Azure Key Vault への格納に関する記事を参照してください。
手順 1: [App Service] ページの左側メニューで、[構成] を選択します。
手順 2:[構成] ページの [アプリケーションの設定] タブで、AZURE_POSTGRESQL_CONNECTIONSTRING
が存在することを確認します。 これは、環境変数としてランタイム環境に挿入されます。
手順 3: ターミナルまたはコマンド プロンプトで Python スクリプト python -c 'import secrets; print(secrets.token_hex())'
を実行して、一意のシークレットを生成します。 次の手順で使用する出力値をコピーします。
3. サンプル コードのデプロイ
この手順では、GitHub Actions を使って GitHub のデプロイを構成します。 これは、App Service にデプロイする多くの方法の 1 つにすぎませんが、デプロイ プロセスで継続的インテグレーションを実現する優れた方法でもあります。 既定では、GitHub リポジトリに git push
があるたびにビルドとデプロイのアクションが起動されます。
手順 1: 新しいブラウザー ウィンドウ内で次を実行します。
- GitHub アカウントにサインインします。
- https://github.com/Azure-Samples/msdocs-flask-postgresql-sample-app に移動します。
- [Fork] を選択します。
- [Create fork] (フォークの作成) を選択します。
手順 2: GitHub のページで、.
キーを押して、ブラウザーで Visual Studio Code を開きます。
手順 3: ブラウザーの Visual Studio Code で、azureproject/production.py をエクスプローラーで開きます。 構成ページで確認したアプリの設定など、運用環境で使われている環境変数を確認します。
手順 4: [App Service] ページに戻り、左側のメニューから [デプロイ センター] を選びます。
手順 5: [デプロイ センター] ページで次のようにします。
- [ソース] で、[GitHub] を選びます。 既定では、ビルド プロバイダーとして GitHub Actions が選ばれます。
- GitHub アカウントにサインインし、プロンプトに従って Azure を承認します。
- [組織] で、自分のアカウントを選びます。
- [リポジトリ] で msdocs-flask-postgresql-sample-app を選びます。
- [ブランチ] で [main] を選びます。
- [ワークフローの追加] で既定のオプションを選択したままにします。
- [認証の種類] で、[ユーザー割り当て ID] を選択してください。
- 上部のメニューから、[保存] を選択します。 App Service は、選んだ GitHub リポジトリの
.github/workflows
ディレクトリに、ワークフロー ファイルをコミットします。
手順 6: [デプロイ センター] ページで次のようにします。
- [ログ] を選択します。 デプロイの実行は既に開始されています。
- デプロイの実行のログ項目で、[ビルドまたはデプロイ ログ] を選びます。
手順 7: GitHub リポジトリに移動したら、GitHub アクションが実行されていることを確認します。 ワークフロー ファイルでは、ビルドとデプロイという 2 つの異なるステージを定義します。 GitHub が実行されて、[完了] の状態が表示されるまで待ちます。 所要時間は約 5 分です。
問題がある場合は、 トラブルシューティング ガイドを確認してください。
4. データベース スキーマを生成する
PostgreSQL データベースは仮想ネットワークによって保護されているため、Flask データベースの移行を実行する最も簡単な方法は、SSH セッション内で App Service コンテナーを使うことです。
手順 1: [App Service] ページに戻り、左側のメニューで
- [SSH] を選択します。
- [Go] \(移動) を選択します。
手順 2: SSH ターミナルで、flask db upgrade
を実行します。 それに成功すると、App Service はデータベースに正常に接続した状態になります。
/home
内のファイルへの変更のみが、アプリの再起動後も保持されます。 /home
の外部の変更は永続化されません。
5.アプリの参照
手順 1: [App Service] ページ内で、次を実行します。
- 左側のメニューから [概要] を選びます。
- アプリの URL を選びます。 直接、
https://<app-name>.azurewebsites.net
に移動することもできます。
手順 2: 一覧にレストランをいくつか追加します。 おめでとうございます。Azure Database for PostgreSQL へのセキュリティで保護された接続を使用して、Azure App Service で Web アプリを実行できました。
6.診断ログをストリーミングする
Azure App Service では、アプリケーションに関する問題の診断に役立つように、コンソールに出力されたすべてのメッセージが収集されます。 次に示すように、サンプル アプリには、この機能を示す print()
ステートメントが含まれています。
@app.route('/', methods=['GET'])
def index():
print('Request for index page received')
restaurants = Restaurant.query.all()
return render_template('index.html', restaurants=restaurants)
手順 1: [App Service] ページ内で、次を実行します。
- 左側のメニューから、[App Service ログ] を選びます。
- [アプリケーション ログ記録] で [ファイル システム] を選びます。
- 上部のメニューから、[保存] を選択します。
手順 2:左側のメニューから [ログ ストリーム] を選択します。 プラットフォーム ログとコンテナー内のログを含む、アプリのログが表示されます。
Python アプリでのログ記録の詳細については、Python アプリケーション用の Azure Monitor の設定に関するシリーズを参照してください。
7.リソースをクリーンアップする
完了したら、リソース グループを削除することで、Azure サブスクリプションからすべてのリソースを削除できます。
手順 1: Azure portal の上部にある検索バーで次を行います。
- リソース グループ名を入力します。
- リソース グループを選択します。
手順 2: [リソース グループ] ページ内で、[リソース グループの削除] を選びます。
ステップ 3:
- リソース グループの名前を入力して、削除を確定します。
- [削除] を選択します。
1.Azure リソースを作成してサンプル アプリをデプロイする
このステップでは、Azure リソースを作成し、サンプル アプリを App Service on Linux にデプロイします。 このチュートリアルで使用する手順では、App Service と Azure Database for PostgreSQL を含む既定でセキュリティで保護された一連のリソースを作成します。
まだ行っていない場合は、サンプル リポジトリの
starter-no-infra
ブランチをローカル ターミナルにクローンします。git clone -b starter-no-infra https://github.com/Azure-Samples/msdocs-flask-postgresql-sample-app cd msdocs-flask-postgresql-sample-app
このクローンしたブランチから作業を始めます。 これには、簡単なデータ ドリブンの Flask アプリケーションが含まれます。
リポジトリのルートから、
azd init
を実行します。azd init --template python-app-service-postgresql-infra
メッセージが表示されたら、次の回答を入力します。
Question Answer The current directory is not empty. (現在のディレクトリが空ではありません。) Would you like to initialize a project here in '<your-directory>'? ('<ディレクトリ>' でプロジェクトを初期化しますか?) Y What would you like to do with these files? (これらのファイルをどうしますか?) Keep my existing files unchanged (既存のファイルを変更しないでそのままにする) Enter a new environment name (新しい環境の名前を入力してください) 一意の名前を入力します。 azd テンプレートは、Azure での Web アプリの DNS 名の一部としてこの名前を使います ( <app-name>.azurewebsites.net
)。 英数字とハイフンを使用できます。azd up
コマンドを実行して、必要な Azure リソースをプロビジョニングし、アプリ コードをデプロイします。 Azure にまだサインインしていない場合は、ブラウザーが起動してサインインを求めます。 また、azd up
コマンドでは、サブスクリプションとデプロイ先の場所を選択するように求められます。azd up
azd up
コマンドの完了には、数分かかることがあります。 また、アプリケーション コードのコンパイルとデプロイも行われますが、後でコードを変更して App Service で動作するようにします。 実行中、このコマンドは、Azure のデプロイへのリンクを含む、プロビジョニングとデプロイのプロセスに関するメッセージを提供します。 完了すると、コマンドはデプロイ アプリケーションへのリンクも表示します。この azd テンプレートには、次の Azure リソースを使って既定でセキュリティ保護されるアーキテクチャを生成するファイル (azure.yaml と infra ディレクトリ) が含まれています。
- リソース グループ → 作成されたすべてのリソースのコンテナーです。
- App Service プラン → App Service のコンピューティング リソースを定義します。 B1 レベルの Linux プランが指定されています。
- App Service → アプリを表し、App Service プランで実行されます。
- 仮想ネットワーク → App Service アプリと統合され、バックエンドのネットワーク トラフィックを分離します。
- Azure Database for PostgreSQL フレキシブル サーバー → 仮想ネットワーク内からのみアクセス可能です。 サーバー上にデータベースとユーザーが作成されます。
- プライベート DNS ゾーン → 仮想ネットワーク内の PostgreSQL サーバーの DNS 解決を有効にします。
- Log Analytics ワークスペース → アプリでログを配布するためのターゲット コンテナーとして機能します。ここで、ログのクエリを実行することもできます。
2.データベース接続文字列を使用する
使っている azd テンプレートにより、既に自動的にアプリ設定として生成されている接続変数が、便宜のためにターミナルに出力されます。 アプリの設定は、接続のシークレットをコード リポジトリに残さないための 1 つの方法です。
azd 出力で、アプリの設定を見つけて、設定
AZURE_POSTGRESQL_CONNECTIONSTRING
とAZURE_REDIS_CONNECTIONSTRING
を見つけます。 シークレットを安全に保つため、設定の名前のみが表示されます。 azd の出力では次のようになります。App Service app has the following settings: - AZURE_POSTGRESQL_CONNECTIONSTRING - AZURE_REDIS_CONNECTIONSTRING - FLASK_DEBUG - SCM_DO_BUILD_DURING_DEPLOYMENT - SECRET_KEY
AZURE_POSTGRESQL_CONNECTIONSTRING
には、Azure の Postgres データベースへの接続文字列が含まれており、AZURE_REDIS_CONNECTIONSTRING
には、Azure の Redis Cache への接続文字列が含まれています。 接続するには、それらにコードを使用する必要があります。 azureproject/production.py を開き、次の行をコメント解除して、ファイルを保存します。conn_str = os.environ['AZURE_POSTGRESQL_CONNECTIONSTRING'] conn_str_params = {pair.split('=')[0]: pair.split('=')[1] for pair in conn_str.split(' ')} DATABASE_URI = 'postgresql+psycopg2://{dbuser}:{dbpass}@{dbhost}/{dbname}'.format( dbuser=conn_str_params['user'], dbpass=conn_str_params['password'], dbhost=conn_str_params['host'], dbname=conn_str_params['dbname'] )
これで、アプリケーションのコードは Azure の PostgreSQL データベースに接続するように構成されました。 必要な場合は、
app.py
を開き、DATABASE_URI
環境変数の使用方法を確認します。ターミナルで
azd deploy
を実行します。azd deploy
4. データベース スキーマを生成する
PostgreSQL データベースは仮想ネットワークによって保護されているため、Flask データベースの移行を実行する最も簡単な方法は、SSH セッション内で App Service コンテナーを使うことです。
azd の出力で SSH セッションの URL を見つけて、ブラウザーでそこに移動します。 出力では次のようになります。
Open SSH session to App Service container at: https://<app-name>.scm.azurewebsites.net/webssh/host
SSH ターミナルで
flask db upgrade
を実行します。 それに成功すると、App Service はデータベースに正常に接続した状態になります。Note
/home
内のファイルへの変更のみが、アプリの再起動後も保持されます。/home
の外部の変更は永続化されません。
5.アプリの参照
azd の出力でアプリの URL を見つけて、ブラウザーでそこに移動します。 URL は、AZD の出力では次のようになります。
Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: https://<app-name>.azurewebsites.net/
一覧にいくつかのレストランを追加します。
おめでとうございます。Azure Database for PostgreSQL へのセキュリティで保護された接続を使用して、Azure App Service で Web アプリを実行できました。
6.診断ログをストリーミングする
Azure App Service はコンソール ログをキャプチャできるので、アプリケーションに関する問題の診断に役立ちます。 便宜のため、azd テンプレートでは、既にローカル ファイル システムへのログ記録が有効になっており、Log Analytics ワークスペースにも配布されるようになっています。
サンプル アプリには、次のスニペットに示すように、この機能を実際に行う print()
ステートメントが含まれています。
@app.route('/', methods=['GET'])
def index():
print('Request for index page received')
restaurants = Restaurant.query.all()
return render_template('index.html', restaurants=restaurants)
azd の出力で、App Service ログをストリーミングするためのリンクを見つけて、ブラウザーでそこに移動します。 リンクは、azd の出力では次のようになります。
Stream App Service logs at: https://portal.azure.com/#@/resource/subscriptions/<subscription-guid>/resourceGroups/<group-name>/providers/Microsoft.Web/sites/<app-name>/logStream
Python アプリでのログ記録の詳細については、Python アプリケーション用の Azure Monitor の設定に関するシリーズを参照してください。
7.リソースをクリーンアップする
現在のデプロイ環境のすべての Azure リソースを削除するには、azd down
を実行します。
azd down
トラブルシューティング
このチュートリアルの作業中に発生する可能性がある問題と、それらを解決する手順を次に示します。
SSH セッションに接続できません
SSH セッションに接続できない場合は、アプリ自体が起動に失敗しています。 詳細については、診断ログを確認してください。 たとえば、KeyError: 'AZURE_POSTGRESQL_CONNECTIONSTRING'
のようなエラーが表示された場合は、環境変数が存在しないことを意味する可能性があります (アプリの設定を削除した可能性があります)。
データベース移行の実行時にエラーを受け取ります
データベースへの接続に関連するエラーが発生する場合は、アプリの設定 (AZURE_POSTGRESQL_CONNECTIONSTRING
) が変更されていないかどうかを確認します。 接続文字列がないと、migrate コマンドでデータベースと通信できません。
よく寄せられる質問
- この設定にはいくらかかりますか。
- 仮想ネットワークの背後でセキュリティ保護されている PostgreSQL サーバーに他のツールで接続するにはどうすればよいですか?
- GitHub Actions でのローカル アプリの開発はどのように行いますか。
- Azure App Service 上で動作する Django サンプルはどのように構成されていますか?
この設定にはいくらかかりますか。
作成したリソースの価格は次のとおりです。
- App Service プランは Basic レベルで作成され、スケールアップまたはスケールダウンできます。 「App Service の価格」をご覧ください。
- PostgreSQL フレキシブル サーバーは、ストレージ サイズが最小な、最も低いバースト可能レベルである Standard_B1ms に作成されます。スケールアップまたはダウンすることができます。 Azure Database for PostgreSQL の価格に関するページを参照してください。
- 仮想ネットワークでは、ピアリングなどの追加機能を構成しない限り、料金は発生しません。 「Azure Virtual Network の価格」を参照してください。
- プライベート DNS ゾーンでは、少額の料金が発生します。 「Azure DNS の価格」を参照してください。
仮想ネットワークの背後でセキュリティ保護されている PostgreSQL サーバーに他のツールで接続するにはどうすればよいですか?
- コマンドライン ツールからの基本的なアクセスには、アプリの SSH ターミナルから
psql
を実行できます。 - デスクトップ ツールから接続するには、マシンが仮想ネットワーク内にある必要があります。 たとえば、サブネットの 1 つに接続されている Azure VM、または Azure 仮想ネットワークとサイト間 VPN で接続されているオンプレミス ネットワーク内のマシンが該当します。
- また、仮想ネットワークに Azure Cloud Shell を統合することもできます。
GitHub Actions でのローカル アプリの開発はどのように行いますか。
App Service から自動生成されたワークフロー ファイルを例として使用すると、git push
ごとに新しいビルドとデプロイの実行が起動されます。 GitHub リポジトリのローカル クローンから、必要な更新を行い、GitHub にプッシュします。 次に例を示します。
git add .
git commit -m "<some-message>"
git push origin main
Azure App Service 上で動作する Django サンプルはどのように構成されていますか?
注意
独自のアプリでこのチュートリアルに従っている場合は、各プロジェクトの README.md ファイル (Flask、Django) の requirements.txt ファイルの説明を参照して、必要なパッケージを確認します。
Azure App Service 内で動作するように、Django サンプル アプリケーションによって azureproject/production.py ファイル内の設定が構成されます。 このような変更は、Django を運用環境にデプロイする場合に一般的であり、App Service に固有のものではありません。
Django によって、受信要求の HTTP_HOST ヘッダーが検証されます。 このサンプル コードでは、App Service の
WEBSITE_HOSTNAME
環境変数を使って、アプリのドメイン名を Django の ALLOWED_HOSTS 設定に追加します。# Configure the domain name using the environment variable # that Azure automatically creates for us. ALLOWED_HOSTS = [os.environ['WEBSITE_HOSTNAME']] if 'WEBSITE_HOSTNAME' in os.environ else []
Django では、運用環境で静的ファイルを提供することはサポートされていません。 このチュートリアルでは、WhiteNoise を使用して、ファイルを提供できるようにします。 WhiteNoise パッケージは requirements.txt を使って既にインストールされ、そのミドルウェアが一覧に追加されています。
# WhiteNoise configuration MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', # Add whitenoise middleware after the security middleware 'whitenoise.middleware.WhiteNoiseMiddleware',
次に、Django のドキュメントに従って静的ファイル設定を構成します。
SESSION_ENGINE = "django.contrib.sessions.backends.cache" STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
詳細については、「Django アプリの運用設定」を参照してください。
次のステップ
次のチュートリアルに進み、カスタム ドメインと証明書を使用してアプリをセキュリティで保護する方法を学習してください。
App Service で Python アプリが実行される方法を確認する: