チュートリアル: Azure Container Apps と PostgreSQL を使用して Python Web アプリを構築してデプロイする
この記事は、Azure Container Appsを
このチュートリアルでは、次の操作を行います。
- クラウドでコンテナー イメージを構築して、Python サンプル Web アプリ (Django または Flask) をコンテナー化します。
- コンテナー イメージを Azure Container Apps にデプロイします。
- サンプル アプリがデータを格納する Azure Database for PostgreSQL - フレキシブル サーバー インスタンスにコンテナー アプリが接続できるようにする環境変数を定義します。
次の図は、このチュートリアルのタスクであるコンテナー イメージのビルドとデプロイを示しています。
前提 条件
Azure サブスクリプションをお持ちでない場合は、開始する前に 無料アカウント を作成してください。
Azure CLI コマンドは、Azure Cloud Shell
ローカルで実行している場合は、次の手順に従ってサインインし、このチュートリアルに必要なモジュールをインストールします。
必要に応じて、Azure にサインインして認証します。
az login
最新バージョンの Azure CLI を実行していることを確認します。
az upgrade
az extension add コマンドを使用して、containerapp と rdbms-connect の Azure CLI 拡張機能をインストールまたはアップグレードします。
az extension add --name containerapp --upgrade az extension add --name rdbms-connect --upgrade
Note
システムにインストールされている拡張機能を一覧表示するには、az extension list コマンドを使用します。 例えば:
az extension list --query [].name --output tsv
サンプル アプリを入手する
サンプル コードをフォークして開発者環境に複製します。
サンプル アプリの GitHub リポジトリ (Django または Flask) に移動し、[Fork] を選択します。
手順に従って、リポジトリを GitHub アカウントにフォークします。 フォークや GitHub アカウントを使用せずに、コード リポジトリをローカル コンピューターに直接ダウンロードすることもできます。 ただし、ダウンロード方法を使用する場合は、このシリーズの次のチュートリアルで継続的インテグレーションと継続的デリバリー (CI/CD) を設定することはできません。
git clone コマンドを使用して、フォークしたリポジトリを python-container フォルダーに複製します。
# Django git clone https://github.com/$USERNAME/msdocs-python-django-azure-container-apps.git python-container # Flask # git clone https://github.com/$USERNAME/msdocs-python-flask-azure-container-apps.git python-container
ディレクトリを変更します。
cd python-container
Web アプリ コードからコンテナー イメージをビルドする
これらの手順を実行すると、サンプル コードからビルドされた Docker コンテナー イメージを含む Azure Container Registry インスタンスが作成されます。
az group create コマンドを使用してリソース グループを作成します。
az group create \ --name pythoncontainer-rg \ --location <location>
<場所> を、コマンド
az account list-locations -o table
の出力の Azure の場所Name
値のいずれかに置き換えます。az acr create コマンドを使用して、コンテナー レジストリを作成します。
az acr create \ --resource-group pythoncontainer-rg \ --name <registry-name> \ --sku Basic \ --admin-enabled
レジストリ名
使用する名前は、Azure 内で一意である必要があり、5 から 50 文字の英数字を含める必要があります。 az acr login コマンドを使用してレジストリにサインインします。
az acr login --name <registry-name>
このコマンドは、名前に "azurecr.io" を追加して、完全修飾レジストリ名を作成します。 サインインに成功すると、"ログインに成功しました" というメッセージが表示されます。 レジストリを作成したサブスクリプションとは異なるサブスクリプションからレジストリにアクセスする場合は、
--suffix
スイッチを使用します。サインインに失敗した場合は、Docker デーモンがシステムで実行されていることを確認します。
az acr build コマンドを使用してイメージをビルドします。
az acr build \ --registry <registry-name> \ --resource-group pythoncontainer-rg \ --image pythoncontainer:latest .
次の考慮事項が適用されます。
コマンドの末尾にあるドット (
.
) は、ビルドするソース コードの場所を示します。 サンプル アプリのルート ディレクトリでこのコマンドを実行していない場合は、コードへのパスを指定します。Azure Cloud Shell でコマンドを実行している場合は、
git clone
を使用して、最初にリポジトリを Cloud Shell 環境にプルします。 次に、プロジェクトのルートにディレクトリを変更して、ドット (.
) が正しく解釈されるようにします。-t
(--image
と同じ) オプションを指定しなかった場合、このコマンドでは、ローカル コンテキスト ビルドがレジストリにプッシュされずにキューに入れられます。 プッシュなしのビルドは、イメージがビルドされるか確認する場合に便利です。
az acr repository list コマンドを使用して、コンテナー イメージが作成されたことを確認します。
az acr repository list --name <registry-name>
Note
このセクションの手順では、Basic サービス レベルでコンテナー レジストリを作成します。 このレベルはコスト最適化されており、機能セットとスループットは開発者シナリオを対象としており、このチュートリアルの要件に適しています。 運用環境のシナリオでは、Standard または Premium のいずれかのサービス レベルを使用する可能性が最も高くなります。 これらのレベルでは、強化されたレベルのストレージとスループットが提供されます。
詳細については、Azure Container Registry サービス レベル
PostgreSQL フレキシブル サーバー インスタンスを作成する
サンプル アプリ (Django または Flask) は、PostgreSQL データベースにレストランのレビュー データを格納します。 これらの手順では、データベースを含むサーバーを作成します。
az postgres flexible-server create コマンドを使用して、Azure に PostgreSQL サーバーを作成します。 このコマンドが完了する前に数分間実行することは珍しくありません。
az postgres flexible-server create \ --resource-group pythoncontainer-rg \ --name <postgres-server-name> \ --location <location> \ --admin-user demoadmin \ --admin-password <admin-password> \ --active-directory-auth Enabled \ --tier burstable \ --sku-name standard_b1ms \ --public-access 0.0.0.0
次の値を使用します。
pythoncontainer-rg
: このチュートリアルで使用するリソース グループ名。 別の名前を使用した場合は、この値を変更します。<postgres-server-name>: PostgreSQL データベース サーバー名。 この名前は、すべての Azure で一意である必要があります。 サーバー エンドポイントが
https://<postgres-server-name>.postgres.database.azure.com
。 使用できる文字は、A
からZ
、0
から9
、およびハイフン (-
) です。<場所>: Web アプリに使用したのと同じ場所を使用します。 <場所> は、コマンド
az account list-locations -o table
の出力からの Azure の場所Name
値の 1 つです。<admin-username>: 管理者アカウントのユーザー名。
azure_superuser
、admin
、administrator
、root
、guest
、またはpublic
することはできません。 このチュートリアルでは、demoadmin
を使用します。<admin-password>: 管理者ユーザーのパスワード。 これには、次のうちの 3 つのカテゴリの、8 から 128 文字が含まれている必要があります。英大文字、英小文字、数字、英数字以外の文字のうち、3 つのカテゴリの文字が含まれている必要があります。
重要
ユーザー名またはパスワードを作成するときは、ドル記号 ($) 文字を使用しないでください。 後でこれらの値を使用して環境変数を作成すると、その文字は、Python アプリの実行に使用する Linux コンテナー内で特別な意味を持ちます。
--active-directory-auth
: この値は、PostgreSQL サーバーで Microsoft Entra 認証を有効にするかどうかを指定します。Enabled
に設定します。--sku-name
: 価格レベルとコンピューティング構成の名前。たとえば、Standard_B1ms
します。 詳しくは、「Azure Database for PostgreSQL の価格」をご覧ください。 使用可能なレベルを一覧表示するには、az postgres flexible-server list-skus --location <location>
を使用します。--public-access
:0.0.0.0
を使用します。 これにより、Container Apps などの任意の Azure サービスからサーバーへのパブリック アクセスが許可されます。
Note
ツールを使用してローカル ワークステーションから PostgreSQL サーバーを操作する場合は、az postgres flexible-server firewall-rule create コマンド
使用して、ワークステーションの IP アドレスのファイアウォール規則を追加する必要があります。 ユーザー アカウントのオブジェクト ID を取得するには、az ad signed-in-user show コマンドを使用します。 この ID は、次のコマンドで使用します。
az ad signed-in-user show --query id --output tsv
az postgres flexible-server ad-admin create コマンドを使用して、PostgreSQL サーバーに Microsoft Entra 管理者としてユーザー アカウントを追加します。
az postgres flexible-server ad-admin create \ --resource-group pythoncontainer-rg \ --server-name <postgres-server-name> \ --display-name <your-email-address> \ --object-id <your-account-object-id>
アカウント オブジェクト ID には、前の手順で取得した値を使用します。
Note
このセクションの手順では、バースト可能価格レベルで単一の仮想コアと制限付きメモリを備えた PostgreSQL サーバーを作成します。 Burstable レベルは、完全な CPU を継続的に必要としないワークロードの低コストのオプションであり、このチュートリアルの要件に適しています。 運用環境のワークロードの場合は、General Purpose または Memory Optimized のいずれかの価格レベルにアップグレードできます。 これらのレベルでは、パフォーマンスは向上しますが、コストは増加します。
詳細については、Azure Database for PostgreSQL - フレキシブル サーバーのコンピューティング オプションの
サーバー上にデータベースを作成する
この時点で、PostgreSQL サーバーがあります。 このセクションでは、サーバー上にデータベースを作成します。
az postgres flexible-server db create コマンドを使用して、restaurants_reviewsという名前のデータベースを作成します。
az postgres flexible-server db create \
--resource-group pythoncontainer-rg \
--server-name <postgres-server-name> \
--database-name restaurants_reviews
次の値を使用します。
pythoncontainer-rg
: このチュートリアルで使用するリソース グループ名。 別の名前を使用した場合は、この値を変更します。<postgres-server-name>
: PostgreSQL サーバーの名前。
az postgres flexible-server connect コマンドを使用してデータベースに接続し、psql コマンドを操作することもできます。 psql を使用する場合、シェルにはすべての依存関係が含まれているため、Azure Cloud Shell
また、Azure Database for PostgreSQL フレキシブル サーバーに接続し、
ユーザー割り当てマネージド ID を作成する
Azure で実行されているときにコンテナー アプリの ID として使用するユーザー割り当てマネージド ID を作成します。
Note
ユーザー割り当てマネージド ID を作成するには、アカウントに マネージド ID 共同作成者 ロールの割り当てが必要です。
az identity create コマンドを使用して、ユーザー割り当てマネージド ID を作成します。
az identity create --name my-ua-managed-id --resource-group pythoncontainer-rg
PostgreSQL データベースでマネージド ID を構成する
PostgreSQL サーバーのロールとしてマネージド ID を構成し、restaurants_reviews データベースに必要なアクセス許可を付与します。 Azure CLI または psql のどちらを使用している場合でも、サーバー インスタンスで Microsoft Entra 管理者として構成されているユーザーを使用して Azure PostgreSQL サーバーに接続する必要があります。 サーバーでマネージド ID やその他の Microsoft 管理者ロールを構成できるのは、PostgreSQL 管理者として構成された Microsoft Entra アカウントのみです。
az account get-access-token コマンドを使用して、Azure アカウントのアクセス トークンを取得します。 アクセス トークンは、次の手順で使用します。
az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken
返されるトークンは長いです。 次の手順のコマンドで使用する環境変数にその値を設定します。
MY_ACCESS_TOKEN=<your-access-token>
PostgreSQL サーバーにユーザー割り当てマネージド ID をデータベース ロールとして追加するには、az postgres flexible-server execute コマンドを使用します。
az postgres flexible-server execute \ --name <postgres-server-name> \ --database-name postgres \ --querytext "select * from pgaadauth_create_principal('"my-ua-managed-id"', false, false);select * from pgaadauth_list_principals(false);" \ --admin-user <your-Azure-account-email> \ --admin-password $MY_ACCESS_TOKEN
次の値を使用します。
マネージド ID に別の名前を使用した場合は、
pgaadauth_create_principal
コマンドのmy-ua-managed-id
をマネージド ID の名前に置き換えます。--admin-user
値には、Azure アカウントの電子メール アドレスを使用します。--admin-password
値には、前のコマンドの出力からのアクセス トークンを引用符なしで使用します。データベース名が
postgres
されていることを確認します。
Note
ローカル ワークステーションで
az postgres flexible-server execute
コマンドを実行している場合は、ワークステーションの IP アドレスのファイアウォール規則を追加したことを確認します。 az postgres flexible-server firewall-rule create コマンド使用して、規則を追加できます。 次の手順では、コマンドにも同じ要件が存在します。 次の az postgres flexible-server execute コマンドを使用して、restaurants_reviews データベースに対する必要なアクセス許可をユーザー割り当てマネージド ID に付与します。
az postgres flexible-server execute \ --name <postgres-server-name> \ --database-name restaurants_reviews \ --querytext "GRANT CONNECT ON DATABASE restaurants_reviews TO \"my-ua-managed-id\";GRANT USAGE ON SCHEMA public TO \"my-ua-managed-id\";GRANT CREATE ON SCHEMA public TO \"my-ua-managed-id\";GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"my-ua-managed-id\";ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO \"my-ua-managed-id\";" \ --admin-user <your-Azure-account-email> \ --admin-password $MY_ACCESS_TOKEN
次の値を使用します。
マネージド ID に別の名前を使用した場合は、コマンド内のすべての
my-ua-managed-id
インスタンスをマネージド ID の名前に置き換えます。 クエリ文字列には 5 つのインスタンスがあります。--admin-user
値には、Azure アカウントの電子メール アドレスを使用します。--admin-password
値には、前の出力のアクセス トークンを引用符なしで使用します。データベース名が
restaurants_reviews
されていることを確認します。
この Azure CLI コマンドは、サーバー上の restaurants_reviews データベースに接続し、次の SQL コマンドを発行します。
GRANT CONNECT ON DATABASE restaurants_reviews TO "my-ua-managed-id"; GRANT USAGE ON SCHEMA public TO "my-ua-managed-id"; GRANT CREATE ON SCHEMA public TO "my-ua-managed-id"; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "my-ua-managed-id"; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "my-ua-managed-id";
Container Apps に Web アプリをデプロイする
Azure Container Apps 環境 は、セキュリティで保護された境界として機能し、そこにコンテナー アプリがデプロイされます。 次の手順では、環境内に環境とコンテナーを作成します。 次に、Web サイトが外部に表示されるようにコンテナーを構成します。
これらの手順には、azure Container Apps 拡張機能 containerappが必要です。
az containerapp env create コマンドを使用して Container Apps 環境を作成します。
az containerapp env create \ --name python-container-env \ --resource-group pythoncontainer-rg \ --location <location>
<場所> は、コマンド
az account list-locations -o table
の出力からの Azure の場所Name
値の 1 つです。az acr credential show コマンドを使用して、Azure Container Registry インスタンスのサインイン資格情報を取得します。
az acr credential show -n <registry-name>
手順 5 でコンテナー アプリを作成するときに、コマンドの出力から返されたユーザー名とパスワードの 1 つを使用します。
az identity show コマンドを使用して、ユーザー割り当てマネージド ID のクライアント ID とリソース ID を取得します。
az identity show --name my-ua-managed-id --resource-group pythoncontainer-rg --query "[clientId, id]" --output tsv
手順 5 でコンテナー アプリを作成するときに、コマンドの出力のクライアント ID (GUID) とリソース ID の値を使用します。 リソース ID の形式は次のとおりです:
/subscriptions/<subscription-id>/resourcegroups/pythoncontainer-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-ua-managed-id
。次のコマンドを実行して、秘密鍵の値を生成します。
python -c 'import secrets; print(secrets.token_hex())'
手順 5 でコンテナー アプリを作成するときに、秘密鍵の値を使用して環境変数を設定します。
Note
この手順で示すコマンドは、Bash シェル用です。 環境によっては、
python3
を使用して Python を呼び出す必要がある場合があります。 Windows では、コマンドを-c
パラメーターで単一引用符ではなく二重引用符で囲む必要があります。 また、環境によっては、py
またはpy -3
を使用して Python を呼び出す必要がある場合もあります。az containerapp create コマンドを使用して、環境内にコンテナー アプリを作成します。
az containerapp create \ --name python-container-app \ --resource-group pythoncontainer-rg \ --image <registry-name>.azurecr.io/pythoncontainer:latest \ --environment python-container-env \ --ingress external \ --target-port <5000 for Flask or 8000 for Django> \ --registry-server <registry-name>.azurecr.io \ --registry-username <registry-username> \ --registry-password <registry-password> \ --user-assigned <managed-identity-resource-id> \ --query properties.configuration.ingress.fqdn \ --env-vars DBHOST="<postgres-server-name>" \ DBNAME="restaurants_reviews" \ DBUSER="my-ua-managed-id" \ RUNNING_IN_PRODUCTION="1" \ AZURE_CLIENT_ID="<managed-identity-client-id>" \ AZURE_SECRET_KEY="<your-secret-key>"
山括弧内のすべての値を、このチュートリアルで使用しているものに置き換えてください。 コンテナー アプリの名前は Azure 全体で一意である必要があることに注意してください。
--env-vars
パラメーターの値は、次の値を持つ key="value" 形式のスペース区切り値で構成される文字列です。DBHOST="\<postgres-server-name>"
DBNAME="restaurants_reviews"
DBUSER="my-ua-managed-id"
RUNNING_IN_PRODUCTION="1"
AZURE_CLIENT_ID="\<managed-identity-client-id>"
AZURE_SECRET_KEY="\<your-secret-key>"
DBUSER
の値は、ユーザー割り当てマネージド ID の名前です。AZURE_CLIENT_ID
の値は、ユーザー割り当てマネージド ID のクライアント ID です。 前の手順でこの値を取得しました。AZURE_SECRET_KEY
の値は、前の手順で生成した秘密鍵の値です。Django の場合のみ、データベース スキーマを移行して作成します。 (Flask サンプル アプリでは自動的に実行されるため、この手順をスキップできます)。
az containerapp exec コマンドを使用して接続します。
az containerapp exec \ --name python-container-app \ --resource-group pythoncontainer-rg
次に、シェルのコマンド プロンプトで、「
python manage.py migrate
」と入力します。コンテナーのリビジョンについては、移行する必要はありません。
Web サイトをテストします。
入力した
az containerapp create
コマンドは、アプリの参照に使用できるアプリケーション URL を出力します。 URL はazurecontainerapps.io
で終わります。 ブラウザーで URL に移動します。 または、az containerapp browse コマンドを使用することもできます。
レストランと 2 つのレビューを追加した後のサンプル Web サイトの例を次に示します。
デプロイのトラブルシューティング
Web サイトにアクセスするためのアプリケーション URL を忘れた場合
Azure portal で次の手順を実行します。
- コンテナー アプリの
の [概要] ページに移動し、アプリケーション URL探します。
VS Code の場合:
- Azure ビュー (Ctrl + Shift + A) に移動し、作業中のサブスクリプションを展開します。
- Container Apps ノードを展開し、マネージド環境を展開します。python-container-app を右クリックして、[参照] を選択します。 VS Code は、アプリケーション URL を使用してブラウザーを開きます。
Azure CLI で次の手順を実行します。
- コマンド
az containerapp show -g pythoncontainer-rg -n python-container-app --query properties.configuration.ingress.fqdn
を使用します。
VS Code では、Azure のビルド イメージ タスクでエラーが返されます
"Error: failed to download context. VS Code 出力 ウィンドウで、URL が正しくないかどうかを確認してください。Docker 拡張機能でレジストリを更新します。 更新するには、Docker 拡張機能を選択し、レジストリ セクションに移動し、レジストリを見つけて選択します。
Azure タスクで
Azure portal で、コンテナー アプリの作成時にアクセス エラーが表示される
Azure Container Registry インスタンスで管理者資格情報が無効になっている際に、"ACR '<名>.azurecr.io' にアクセスできません" というアクセスエラーが発生します。
ポータルで管理者の状態を確認するには、Azure Container Registry インスタンスに移動し、リソース アクセス キー
コンテナー イメージが Azure Container Registry インスタンスに表示されない
- Azure CLI コマンドまたは VS Code 出力の出力を確認し、成功を確認するメッセージを探します。
- Azure CLI を使用したビルド コマンドまたは VS Code タスク プロンプトで、レジストリの名前が正しく指定されていることを確認します。
- 資格情報の有効期限が切れていないことを確認します。 たとえば、VS Code では、Docker 拡張機能でターゲット レジストリを見つけて更新します。 Azure CLI で、
az login
を実行します。
Web サイトから "Bad Request (400)" が返される
"Bad Request (400)" エラーが発生した場合は、コンテナーに渡された PostgreSQL 環境変数を確認します。 多くの場合、400 エラーは、Python コードが PostgreSQL インスタンスに接続できないことを示しています。
このチュートリアルで使用するサンプル コードでは、任意の値 (1
など) に設定できるコンテナー環境変数 RUNNING_IN_PRODUCTION
が存在するかどうかを確認します。
Web サイトから "Not Found (404)" が返されます
- コンテナーの [の概要] ページで、アプリケーション URL 値を確認します。 アプリケーション URL に "internal" という単語が含まれている場合、イングレスが正しく設定されていません。
- コンテナーのイングレスを確認します。 たとえば、Azure portal で、コンテナーの イングレス リソースに移動します。
HTTP イングレス が有効になっており、 どこからでもトラフィックを受け入れるが選択されていることを確認します。
Web サイトが起動しない、"ストリーム タイムアウト" が発生する、または何も返されない
- ログを確認します。
- Azure portal で、コンテナー アプリのリビジョン管理リソースに移動し、コンテナーのプロビジョニング状態
確認します。 - 状態が プロビジョニングの場合は、プロビジョニングが完了するまで待ちます。
- 状態が Failedの場合は、リビジョンを選択してコンソール ログを表示します。 列の順序を選択して、生成時刻、Stream_s、および Log_sを示します。 最新のログを並べ替え、Stream_s 列で Python
stderr
とstdout
メッセージを探します。 Pythonprint
出力はstdout
のメッセージです。
- Azure CLI で az containerapp logs show コマンドを使用します。
- Azure portal で、コンテナー アプリのリビジョン管理リソースに移動し、コンテナーのプロビジョニング状態
- Django フレームワークを使用している場合は、restaurants_reviews テーブルがデータベースに存在するかどうかを確認します。 存在しない場合は、コンソールを使用してコンテナーにアクセスして
python manage.py migrate
を実行します。
次のステップ
Azure Container Apps で Python Web アプリの継続的デプロイを構成する