このチュートリアルでは、ショッピング カート アプリケーション Orleans サンプルを Azure Container Apps にデプロイする方法について説明します。 このチュートリアルでは、「Orleansを Azure App Service にデプロイする」で紹介したサンプル Orleansショッピング カート アプリの機能を拡張します。 サンプル アプリは、Azure Active Directory (AAD) の企業間 (B2C) 認証を追加し、Azure Container Apps にデプロイします。
GitHub Actions、.NET と Azure CLI、Azure Bicep を使用してデプロイする方法について説明します。 さらに、コンテナー アプリの HTTP イングレスを構成する方法について説明します。
このチュートリアルでは、以下の内容を学習します。
- Orleans アプリケーションを Azure Container Apps にデプロイする
- GitHub Actions と Azure Bicep を使用してデプロイを自動化する
- HTTP イングレスを構成する
[前提条件]
- GitHub アカウント
- 概要を読む Orleans
- .NET 6 SDK(.NET 6 Software Development Kit、ソフトウェア開発キット)
- Azure CLI
- .NET 統合開発環境 (IDE)
- Visual Studio または Visual Studio Code を自由に使用できます
アプリをローカルで実行する
アプリをローカルで実行するには、 Azure Samples: Orleans ショッピング カートを Azure Container Apps リポジトリに フォークし、ローカル コンピューターに複製します。 複製が完了したら、任意の IDE でソリューションを開きます。 Visual Studio を使用している場合は、Orleansを右クリックします。ShoppingCart.Silo プロジェクトで、[スタートアップ プロジェクトとして設定] を選択し、アプリを実行します。 それ以外の場合は、次の .NET CLI コマンドを使用してアプリを実行します。
dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj
詳細については、の "dotnet run" を参照してください。 アプリを実行すると、ランディング ページでアプリの機能について説明します。 右上隅にサインイン ボタンが表示されます。 アカウントにサインアップするか、既に存在する場合はサインインします。 サインインしたら、移動してその機能をテストします。 ローカルで実行するすべてのアプリ機能は、メモリ内の永続化とローカル クラスタリングに依存します。 また、 Bogus NuGet パッケージを使用して偽の製品を生成します。 Visual Studio で [デバッグの停止] オプションを選択するか、.NET CLI で Ctrl+キーを押して、アプリを停止します。
AAD B2C
認証の概念については、このチュートリアルでは説明していませんが、 Azure Active Directory B2C テナントを作成し、それを使用する Web アプリを登録 する方法について説明します。 このショッピング カートのサンプル アプリでは、結果としてデプロイされた Container Apps の URL を B2C テナントに登録します。 詳細については、「 ASP.NET Core Blazor の認証と承認」を参照してください。
Von Bedeutung
コンテナー アプリがデプロイされたら、B2C テナントにアプリの URL を登録します。 ほとんどの運用シナリオでは、アプリの URL は変更されないため、登録が必要なのは 1 回だけです。
Azure Container Apps 環境内でアプリがどのように分離されているかを視覚化するには、次の図を参照してください。
前の図では、アプリへの受信トラフィックはすべて、セキュリティで保護された HTTP イングレスを介してファネルされます。 Azure Container Apps 環境にはアプリ インスタンスが含まれており、アプリ インスタンスには ASP.NET Core ホストが含まれており、Blazor サーバーと Orleans アプリの機能が公開されています。
Azure Container Apps へのデプロイ
Azure Container Apps にアプリをデプロイするために、リポジトリでは GitHub Actions が使用されます。 このデプロイを行う前に、いくつかの Azure リソースが必要であり、GitHub リポジトリを正しく構成する必要があります。
アプリをデプロイする前に、Azure リソース グループを作成します (または、既存のものを使用できます)。 新しい Azure リソース グループを作成するには、次のいずれかの記事を使用します。
- Azure Portal
- Azure CLI
- Azure PowerShell
選択したリソース グループ名を書き留めます。後でアプリをデプロイするために必要になります。
サービス プリンシパルを作成する
アプリのデプロイを自動化するには、サービス プリンシパルを作成する必要があります。 これは、ユーザーに代わって Azure リソースを管理するアクセス許可を持つ Microsoft アカウントです。
az ad sp create-for-rbac --sdk-auth --role Contributor \
--name "<display-name>" --scopes /subscriptions/<your-subscription-id>
作成される JSON 資格情報は次のようになりますが、クライアント、サブスクリプション、テナントの実際の値を使用します。
{
"clientId": "<your client id>",
"clientSecret": "<your client secret>",
"subscriptionId": "<your subscription id>",
"tenantId": "<your tenant id>",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com/",
"resourceManagerEndpointUrl": "https://brazilus.management.azure.com",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com",
"managementEndpointUrl": "https://management.core.windows.net"
}
コマンドの出力をクリップボードにコピーし、次の手順に進みます。
GitHub シークレットを作成する
GitHub には、暗号化されたシークレットを作成するためのメカニズムが用意されています。 作成したシークレットは、GitHub Actions ワークフローで使用できます。 GitHub Actions を使用して、Azure Bicep と組み合わせてアプリのデプロイを自動化する方法について説明します。 Bicep は、宣言型の構文を使用して Azure リソースをデプロイするドメイン固有言語 (DSL) です。 詳細については、「Bicep とは」を参照してください。
サービス プリンシパルの作成手順の出力を使用して、JSON 形式の資格情報を使用して AZURE_CREDENTIALS
という名前の GitHub シークレットを作成する必要があります。
GitHub リポジトリ内で、[>>します。
AZURE_CREDENTIALS
名前を入力し、前の手順の JSON 資格情報を [値] フィールドに貼り付けます。
詳細については、「 GitHub: 暗号化されたシークレット」を参照してください。
Azure デプロイの準備
デプロイ用にアプリをパッケージ化します。
Orleans.ShoppingCart.Silos
プロジェクトでは、Target
ステップの後に実行されるPublish
要素が定義されます。 このターゲットは、発行ディレクトリを silo.zip ファイルに圧縮します。
<Target Name="ZipPublishOutput" AfterTargets="Publish">
<Delete Files="$(ProjectDir)\..\silo.zip" />
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>
.NET アプリを Azure Container Apps にデプロイする方法は多数あります。 このチュートリアルでは、GitHub Actions、Azure Bicep、および .NET と Azure の CLI を使用します。 GitHub リポジトリのルートにある ./github/workflows/deploy.yml ファイルについて考えてみましょう。
name: Deploy to Azure Container Apps
on:
push:
branches:
- main
env:
UNIQUE_APP_NAME: orleanscart
SILO_IMAGE_NAME: orleanscart-silo
AZURE_RESOURCE_GROUP_NAME: orleans-resourcegroup
AZURE_RESOURCE_GROUP_LOCATION: eastus
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET 6.0
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
- name: .NET publish shopping cart app
run: dotnet publish ./Silo/Orleans.ShoppingCart.Silo.csproj --configuration Release
- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Flex ACR Bicep
run: |
az deployment group create \
--resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
--template-file '.github/workflows/flex/acr.bicep' \
--parameters location=${{ env.AZURE_RESOURCE_GROUP_LOCATION }}
- name: Get ACR Login Server
run: |
ACR_NAME=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} -n acr \
--query properties.outputs.acrName.value | tr -d '"')
echo "ACR_NAME=$ACR_NAME" >> $GITHUB_ENV
ACR_LOGIN_SERVER=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} -n acr \
--query properties.outputs.acrLoginServer.value | tr -d '"')
echo "ACR_LOGIN_SERVER=$ACR_LOGIN_SERVER" >> $GITHUB_ENV
- name: Prepare Docker buildx
uses: docker/setup-buildx-action@v1
- name: Login to ACR
run: |
access_token=$(az account get-access-token --query accessToken -o tsv)
refresh_token=$(curl https://${{ env.ACR_LOGIN_SERVER }}/oauth2/exchange -v \
-d "grant_type=access_token&service=${{ env.ACR_LOGIN_SERVER }}&access_token=$access_token" | jq -r .refresh_token)
# The null GUID 0000... tells the container registry that this is an ACR refresh token during the login flow
docker login -u 00000000-0000-0000-0000-000000000000 \
--password-stdin ${{ env.ACR_LOGIN_SERVER }} <<< "$refresh_token"
- name: Build and push Silo image to registry
uses: docker/build-push-action@v2
with:
push: true
tags: ${{ env.ACR_LOGIN_SERVER }}/${{ env.SILO_IMAGE_NAME }}:${{ github.sha }}
file: Silo/Dockerfile
- name: Flex ACA Bicep
run: |
az deployment group create \
--resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
--template-file '.github/workflows/flex/main.bicep' \
--parameters location=${{ env.AZURE_RESOURCE_GROUP_LOCATION }} \
appName=${{ env.UNIQUE_APP_NAME }} \
acrName=${{ env.ACR_NAME }} \
repositoryImage=${{ env.ACR_LOGIN_SERVER }}/${{ env.SILO_IMAGE_NAME }}:${{ github.sha }} \
--debug
- name: Get Container App URL
run: |
ACA_URL=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
-n main --query properties.outputs.acaUrl.value | tr -d '"')
echo $ACA_URL
- name: Logout of Azure
run: az logout
上記の GitHub ワークフローでは、次の処理が行われます。
- dotnet publish コマンドを使用して、ショッピング カート アプリを zip ファイルとして発行します。
- サービス プリンシパルの作成手順の資格情報を使用して Azure にログインします。
- acr.bicep ファイルを評価し、az deployment group create を使用してデプロイ グループを開始します。
- デプロイ グループから Azure Container Registry (ACR) ログイン サーバーを取得します。
- リポジトリの
AZURE_CREDENTIALS
シークレットを使用して ACR にログインします。 - サイロ イメージをビルドして ACR に発行します。
- main.bicep ファイルを評価し、az deployment group create を使用してデプロイ グループを開始します。
- サイロをデプロイします。
- Azure からログアウトします。
ワークフローは、 main
ブランチへのプッシュでトリガーされます。 詳細については、 GitHub Actions と .NET を参照してください。
ヒント
ワークフローの実行時に問題が発生した場合は、サービス プリンシパルに必要なすべてのプロバイダー名前空間が登録されていることを確認する必要があります。 次のプロバイダー名前空間が必要です。
Microsoft.App
Microsoft.ContainerRegistry
Microsoft.Insights
Microsoft.OperationalInsights
Microsoft.Storage
詳細については、「リソース プロバイダー登録エラーの解決」を参照してください。
Azure では、リソースの名前付け制限と規則が適用されます。 次の環境変数の deploy.yml ファイル内の値を更新します。
UNIQUE_APP_NAME
SILO_IMAGE_NAME
AZURE_RESOURCE_GROUP_NAME
AZURE_RESOURCE_GROUP_LOCATION
これらの値を、一意のアプリ名と Azure リソース グループの名前と場所に設定します。
詳細については、「Azure リソースの名前付け規則と制限事項」を参照してください。
Bicep テンプレートを調べる
az deployment group create
コマンドを実行すると、指定された .bicep ファイル参照が評価されます。 このファイルには、デプロイする Azure リソースの詳細を示す宣言型情報が含まれています。 この手順は、デプロイのためにすべてのリソース をプロビジョニングすると 考えてください。
Von Bedeutung
Visual Studio Code を使用している場合、Bicep 拡張機能を使用すると 、Bicep 作成エクスペリエンスが向上します。
評価される最初の Bicep ファイルは acr.bicep ファイルです。 このファイルには、Azure Container Registry (ACR) ログイン サーバー リソースの詳細が含まれています。
param location string = resourceGroup().location
resource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' = {
name: toLower('${uniqueString(resourceGroup().id)}acr')
location: location
sku: {
name: 'Basic'
}
properties: {
adminUserEnabled: true
}
}
output acrLoginServer string = acr.properties.loginServer
output acrName string = acr.name
この Bicep ファイルは、ACR ログイン サーバーと対応する名前を出力します。 次に検出された Bicep ファイルには、単一の resource
以上のものが含まれています。 主に定義の委任で構成される module
ファイルについて考えてみましょう。
param appName string
param acrName string
param repositoryImage string
param location string = resourceGroup().location
resource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = {
name: acrName
}
module env 'environment.bicep' = {
name: 'containerAppEnvironment'
params: {
location: location
operationalInsightsName: '${appName}-logs'
appInsightsName: '${appName}-insights'
}
}
var envVars = [
{
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
value: env.outputs.appInsightsInstrumentationKey
}
{
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
value: env.outputs.appInsightsConnectionString
}
{
name: 'ORLEANS_AZURE_STORAGE_CONNECTION_STRING'
value: storageModule.outputs.connectionString
}
{
name: 'ASPNETCORE_FORWARDEDHEADERS_ENABLED'
value: 'true'
}
]
module storageModule 'storage.bicep' = {
name: 'orleansStorageModule'
params: {
name: '${appName}storage'
location: location
}
}
module siloModule 'container-app.bicep' = {
name: 'orleansSiloModule'
params: {
appName: appName
location: location
containerAppEnvironmentId: env.outputs.id
repositoryImage: repositoryImage
registry: acr.properties.loginServer
registryPassword: acr.listCredentials().passwords[0].value
registryUsername: acr.listCredentials().username
envVars: envVars
}
}
output acaUrl string = siloModule.outputs.acaUrl
上記の Bicep ファイルでは、次の処理が行われます。
-
existing
ACR リソースを参照します。 詳細については、「 Azure Bicep: 既存のリソース」を参照してください。 -
module env
定義ファイルに委任するを定義します。 -
module storageModule
定義ファイルに委任するを定義します。 - サイロ モジュールで使用される複数の共有
envVars
を宣言します。 -
module siloModule
定義ファイルに処理を委任するを定義します。 - ACA URL を出力します (既存の AAD B2C アプリ登録のリダイレクト URI を更新するために使用される可能性があります)。
main.bicep は、他のいくつかの Bicep ファイルにデリゲートします。 1 つ目は environment.bicep ファイルです。
param operationalInsightsName string
param appInsightsName string
param location string
resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
name: appInsightsName
location: location
kind: 'web'
properties: {
Application_Type: 'web'
WorkspaceResourceId: logs.id
}
}
resource logs 'Microsoft.OperationalInsights/workspaces@2021-06-01' = {
name: operationalInsightsName
location: location
properties: {
retentionInDays: 30
features: {
searchVersion: 1
}
sku: {
name: 'PerGB2018'
}
}
}
resource env 'Microsoft.App/managedEnvironments@2022-03-01' = {
name: '${resourceGroup().name}env'
location: location
properties: {
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logs.properties.customerId
sharedKey: logs.listKeys().primarySharedKey
}
}
}
}
output id string = env.id
output appInsightsInstrumentationKey string = appInsights.properties.InstrumentationKey
output appInsightsConnectionString string = appInsights.properties.ConnectionString
この Bicep ファイルでは、Azure Log Analytics リソースと Application Insights リソースを定義します。
appInsights
リソースはweb
の種類であり、logs
リソースはPerGB2018
の種類です。
appInsights
リソースとlogs
リソースの両方がリソース グループの場所にプロビジョニングされます。
appInsights
リソースは、logs
プロパティを使用してWorkspaceResourceId
リソースにリンクします。 この Bicep ファイルは、後で Container Apps module
によって使用される 3 つの出力を定義します。 次に、 storage.bicep ファイルについて考えてみましょう。
param name string
param location string
resource storage 'Microsoft.Storage/storageAccounts@2021-08-01' = {
name: name
location: location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
}
var key = listKeys(storage.name, storage.apiVersion).keys[0].value
var protocol = 'DefaultEndpointsProtocol=https'
var accountBits = 'AccountName=${storage.name};AccountKey=${key}'
var endpointSuffix = 'EndpointSuffix=${environment().suffixes.storage}'
output connectionString string = '${protocol};${accountBits};${endpointSuffix}'
上記の Bicep ファイルでは、次のものが定義されています。
- リソース グループ名とアプリ名の 2 つのパラメーター。
- ストレージ アカウントの
resource storage
定義。 - ストレージ アカウントの接続文字列を構築する 1 つの
output
。
最後の Bicep ファイルは container-app.bicep ファイルです。
param appName string
param location string
param containerAppEnvironmentId string
param repositoryImage string = 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
param envVars array = []
param registry string
param registryUsername string
@secure()
param registryPassword string
resource containerApp 'Microsoft.App/containerApps@2022-03-01' = {
name: appName
location: location
properties: {
managedEnvironmentId: containerAppEnvironmentId
configuration: {
activeRevisionsMode: 'multiple'
secrets: [
{
name: 'container-registry-password'
value: registryPassword
}
]
registries: [
{
server: registry
username: registryUsername
passwordSecretRef: 'container-registry-password'
}
]
ingress: {
external: true
targetPort: 80
}
}
template: {
revisionSuffix: uniqueString(repositoryImage, appName)
containers: [
{
image: repositoryImage
name: appName
env: envVars
}
]
scale: {
minReplicas: 1
maxReplicas: 1
}
}
}
}
output acaUrl string = containerApp.properties.configuration.ingress.fqdn
前述の Bicep 用 Visual Studio Code 拡張機能には、ビジュアライザーが含まれています。 これらすべての Bicep ファイルは、次のように視覚化されます。
概要
ソース コードが更新され、変更がリポジトリの push
ブランチにmain
されると、deploy.yml ワークフローが実行されます。 Bicep ファイルで定義されている Azure リソースをプロビジョニングし、アプリケーションをデプロイします。 リビジョンは、Azure Container Registry に自動的に登録されます。
Bicep 拡張機能のビジュアライザーに加えて、Azure portal のリソース グループ ページは、アプリケーションのプロビジョニングとデプロイ後の次の例のようになります。
こちらも参照ください
.NET