Visual Studio で作成した GitHub Actions ワークフローを使用してアプリケーションを Azure にデプロイする

Visual Studio 2019 バージョン 16.11 から、GitHub.com でホストされている .NET プロジェクト用に新しい GitHub Actions ワークフローを作成できるようになりました。

前提条件

GitHub Actions を使用して Azure に 1 つのプロジェクトをデプロイする

ソリューション エクスプローラーで、GitHub.com でホストされているプロジェクトを右クリックし、 [発行] を選択します。

右クリック > [発行]

次の画面で、 [Azure][次へ] の順に選択します。

[Azure] を選択します

プロジェクトの種類に応じて、選択できる Azure サービスの一覧が変わります。 サポートされている Azure サービスから、ニーズに合ったものを選択してください。

プロジェクトに適した Azure サービスを選択します

ウィザードの最後の手順で、 [CI/CD using GitHub Actions workflows (generates yml file)](GitHub Actions ワークフローを使用した CI/CD (yml ファイルの生成)) を選択し、 [完了] を選択します。

[CI/CD using GitHub Actions workflows (generates yml file)]\(GitHub Actions ワークフローを使用した CI/CD (yml ファイルの生成)\)

Visual Studio によって新しい GitHub Actions ワークフローが生成され、それをコミットして GitHub.com にプッシュするように求められます。

コミットしてプッシュ

組み込みの Git ツールを使用してこの手順を完了した場合、Visual Studio によってワークフローの実行が検出されます。

ワークフローの実行中

GitHub のシークレットの設定

生成したワークフローを Azure に正常にデプロイするには、発行プロファイルへのアクセスが必要になる場合があります。

1 つの GitHub シークレット

正常なデプロイには、サービス プリンシパルへのアクセスが必要になることもあります。

2 つの GitHub シークレット

いずれの場合も、Visual Studio により、自動的に GitHub シークレットが正しい値に設定されるように試行されます。 失敗した場合はその旨が通知され、もう一度試す機会が提供されます。

GitHub シークレットが見つからない

シークレットの設定に再び失敗した場合は、Visual Studio により、シークレットに手動でアクセスする機会が提供されるので、GitHub.com のリポジトリのページからプロセスを完了することができます。

見つからない GitHub シークレットを設定します

GitHub Actions を使用して Azure Container Apps に複数のプロジェクトをデプロイする

これらの手順は、Docker コンテナーを使用しているプロジェクトが複数あり、それらをマルチプロジェクト アプリとしてデプロイする場合に適しています。 Azure Container AppsAzure Kubernetes Service (AKS) にマイクロサービスを実装するアプリなどのマルチプロジェクト アプリをデプロイできます。 この記事では、Azure Container Apps について説明します。

  1. ソリューション エクスプローラーで GitHub Actions ノードを右クリックして、[New workflow] (新しいワークフロー) を選択します。 GitHub Actions ワークフロー ウィザードが表示されます。

    GitHub Actions ノード メニューのスクリーンショット。

  2. GitHub Actions ワークフローのターゲット スクリーンで、[Azure] を選択します。

  3. 特定のターゲットであれば、[Azure Container Apps] を選択します。 ウィザードが [Container App] の画面に進みます。

    既存の Azure Container Apps を示すスクリーンショット。

  4. 既存の Azure Container App を選択するか、[新規作成] を選択します。

    既存の Azure Container Apps を示すスクリーンショット。

    新しく作成する場合は、この画面が表示されます。 一般に、テストまたは学習の場合には、新しいリソース グループを作成することをお勧めします。これは、後ですべてを簡単に削除できるためです。 Container Apps 環境とは、同じ仮想ネットワークを共有し、同じログの出力先にログを記録する Container Apps のグループを囲む、セキュリティで保護された境界です。 「Azure Container Apps 環境」を参照してください。 内容がわからなかったり、まだ作成したことがない場合は、このインスタンス用に新しく作成します。

    新しい Azure Container Apps インスタンスの作成を示すスクリーンショット。

    作成すると、新しい Azure Container Apps インスタンスが表示されます。

    新しく作成された Azure Container Apps インスタンスを示すスクリーンショット。

  5. [次へ] を選択して [レジストリ] 画面に進みます。 既存の Azure Container Registry を選択するか、新規作成します。

    Azure Container Registry 画面のスクリーンショット。

    新しく作成する場合は、この画面が表示されます。 リソース グループと SKU を指定して、可能であれば以前と同じリージョンを選択します。 Azure Container Registry の SKU について詳しくは、「Azure Container Registry のサービス レベル」を参照してください。

    作成されたばかりの新しい Azure Container Registry を示すスクリーンショット。

    作成すると、新しいレジストリが画面に表示されます。

    新しい Azure Container Registry の作成を示すスクリーンショット。

  6. ご自分のソリューションのデプロイ可能なプロジェクトが表示されます。同じ Azure Container Apps インスタンス内に一緒にデプロイするプロジェクトを選択します。

    デプロイするプロジェクトの選択を示すスクリーンショット。

  7. [完了] を選択します。 Azure 内に資産を作成し、認証を設定するために発行されたコマンドを表示できます。 エラーが発生した場合は、CLI から再度試すことができるよう、使用したコマンド ラインをメモします。 この段階で認証に失敗したとしても、あまり気にしないでください。 認証は後から Visual Studio で設定することもできます。

  8. 完了すると、概要の画面が表示されます。 概要の画面には、Visual Studio によって GitHub Actions シークレットの GitHub リポジトリに作成されたエントリと一致する資格情報が表示されます。 警告を表す黄色の表示を確認します。 作成プロセス中に認証手順でエラーが発生した場合は、このタイミングでそれを修正できます。これを行うには、警告表示のリンクをクリックして、いくつかの手順を実行します。

  9. ワークフロー ファイルを開いて、Visual Studio によって生成された内容を確認します。 Visual Studio では可能な限りユーザーの状況に合わせたワークフローが生成されますが、それぞれのアプリとリポジトリは固有であるため、多くの場合、正常に実行する前に、Visual Studio によって生成されたワークフローの YML ファイルを手動で編集する必要があります。 これを開くには、ソリューション エクスプローラーで GitHub Actions ノードを展開し、作成したワークフローを右クリックして、[編集] を選択します。

WebAPI と WebFrontEnd の 2 つデプロイ可能なプロジェクトを持つソリューション用に Visual Studio によって作成されたワークフロー ファイルの例を次に示します。

on:
push:
  branches:
  - main
env:
CONTAINER_REGISTRY_LOGIN_SERVER: registry20230810121555.azurecr.io
CONTAINER_APP_NAME: containerapp20230810121017
CONTAINER_APP_RESOURCE_GROUP_NAME: webfrontend-container-app-1234
CONTAINER_APP_CONTAINER_NAME: containerapp
jobs:
WebApi_buildImageAndDeploy:
  runs-on: ubuntu-latest
  steps:
  - name: Checkout source code
    uses: actions/checkout@v3
  - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v2
  - name: Login to Docker registry
    uses: docker/login-action@v2
    with:
      registry: ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }}
      username: ${{ secrets.registry20230810121555_USERNAME_6891 }}
      password: ${{ secrets.registry20230810121555_PASSWORD_6891 }}
  - name: Build and push Docker image to Azure container registry
    uses: docker/build-push-action@v4
    with:
      push: true
      tags: ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }}/webapi:${{ github.sha }}
      file: WebApi\Dockerfile
  - name: Azure login
    uses: azure/login@v1
    with:
      creds: ${{ secrets.containerapp20230810121017_SPN }}
  - name: Deploy to Azure container app
    uses: azure/CLI@v1
    with:
      inlineScript: >-
        az config set extension.use_dynamic_install=yes_without_prompt
        az containerapp registry set --name ${{ env.CONTAINER_APP_NAME }} --resource-group ${{ env.CONTAINER_APP_RESOURCE_GROUP_NAME }} --server ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }} --username ${{ secrets.registry20230810121555_USERNAME_2047 }} --password ${{ secrets.registry20230810121555_PASSWORD_2047 }}
        az containerapp update --name ${{ env.CONTAINER_APP_NAME }} --container-name ${{ env.CONTAINER_APP_CONTAINER_NAME }} --resource-group ${{ env.CONTAINER_APP_RESOURCE_GROUP_NAME }} --image ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }}/webapi:${{ github.sha }}
  - name: Azure logout
    run: az logout
WebFrontEnd_buildImageAndDeploy:
  runs-on: ubuntu-latest
  needs: WebApi_buildImageAndDeploy
  steps:
  - name: Checkout source code
    uses: actions/checkout@v3
  - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v2
  - name: Login to Docker registry
    uses: docker/login-action@v2
    with:
      registry: ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }}
      username: ${{ secrets.registry20230810121555_USERNAME_2047 }}
      password: ${{ secrets.registry20230810121555_PASSWORD_2047 }}
  - name: Build and push Docker image to Azure container registry
    uses: docker/build-push-action@v4
    with:
      push: true
      tags: ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }}/webfrontend:${{ github.sha }}
      file: WebFrontEnd\Dockerfile
  - name: Azure login
    uses: azure/login@v1
    with:
      creds: ${{ secrets.containerapp20230810121017_SPN }}
  - name: Deploy to Azure container app
    uses: azure/CLI@v1
    with:
      inlineScript: >-
        az config set extension.use_dynamic_install=yes_without_prompt
        az containerapp registry set --name ${{ env.CONTAINER_APP_NAME }} --resource-group ${{ env.CONTAINER_APP_RESOURCE_GROUP_NAME }} --server ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }} --username ${{ secrets.registry20230810121555_USERNAME_2047 }} --password ${{ secrets.registry20230810121555_PASSWORD_2047 }}
        az containerapp update --name ${{ env.CONTAINER_APP_NAME }} --container-name ${{ env.CONTAINER_APP_CONTAINER_NAME }} --resource-group ${{ env.CONTAINER_APP_RESOURCE_GROUP_NAME }} --image ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }}/webfrontend:${{ github.sha }}
  - name: Azure logout
    run: az logout

ワークフローの主な機能は、適切な認証方法を使用して Azure サービスにサインインすることと、コマンドを実行してアプリを構築、デプロイすることです。

ワークフローの編集とテスト

上記の手順を実行するとワークフロー YML ファイルが生成されます。ただし、これは通常、デプロイに使用する前に確認してカスタマイズする必要があります。 ワークフロー アクションの記述に関して GitHub のガイダンスを参照する必要がある場合は、「カスタム アクションについて」を参照してください。 ワークフロー ファイルには、環境変数の設定やシークレット名など、構成可能な要素が多く含まれています。 Dockerfile の場所への参照、Azure Container App の名前、ワークフローの実行をトリガーするのに使用するリポジトリ内のブランチ、および GitHub のシークレットへの参照を確認できます。 シークレットは構文 ${{ secrets.SECRET_NAME }} を使用して参照されます。 「GitHub Actions のシークレット」を参照してください。

プロジェクトがリポジトリのルートにない場合は、ワークフローを変更して、Dockerfile を見つけるためのパスを指定する必要があります。 両方のプロジェクトの Dockerfile への相対パス用に環境変数を追加します。

DOCKER_FILEPATH_WEBAPI: docker/ComposeSample/WebApi/Dockerfile
DOCKER_FILEPATH_WEBFRONTEND: docker/ComposeSample/WebFrontend/Dockerfile

次のようにして、これらの環境変数の値を file パラメータに使用します。

- name: Build and push Docker image to Azure container registry
  uses: docker/build-push-action@v4
  with:
    push: true
    tags: ${{ env.CONTAINER_REGISTRY_LOGIN_SERVER }}/webfrontend:${{ github.sha }}
    file: ${{ env.DOCKER_FILEPATH_WEBFRONTEND }}

Dockerfile に変更を加える必要がある場合は、変更を加えて保存し、コミットして、リモート リポジトリにプッシュします。 Visual Studio によって生成されるワークフローには、特定のブランチで更新された場合にワークフローを実行するトリガーが含まれています。 working ブランチにプッシュしている場合は、次のコードのようになります。

on:
  push:
  branches:
  - working

変更をテストするには、変更をコミットして、トリガー コードに指定されているリポジトリのブランチにプッシュします。 リクエストのプル (PR) を作成する必要はありません。 push トリガーが適切なブランチに設定されている限り、ワークフローが実行されます。

GitHub.com のお使いのリポジトリの [Actions] タブで、ワークフローが実行されるのを確認します。 このタブには、Visual Studio の GitHub Actions の概要タブを使用して直接アクセスすることもできます。 GitHub では、ワークフローの実行を開いてログを表示できます。

トラブルシューティング

次のトラブルシューティングのヒントは、ワークフローが正常に実行されない場合に役立つ可能性があります。

問題: ビルド ステージでビルドされない

Dockerfile で発生する可能性のある問題の 1 つは、ビルド ステージが Visual Studio でのように機能しないことです。 Visual Studio によってプロジェクト用に生成される既定の Dockerfile で、この問題が発生します。 このような Dockerfile がある場合は、ビルド ステージに次のような変更を加えることも考慮します。 プロジェクトがリポジトリ内の docker/ComposeSample/WebApi にある場合の例を次に示します。 ワークフロー ビルド コンテナーの Dockerfile コンテキストがリポジトリのルートに設定されているため、完全なパスが指定されています。ただし Visual Studio では、これはプロジェクト フォルダーの上のフォルダーに設定されています。 ここでは、ビルド フォルダーを作成するためにサフィックス _build が追加され、プロジェクト ファイルのみをコピーするのではなく、フォルダー全体がコピーされます。 Visual Studio によって生成された既定の Dockerfile と比較すると、COPY コマンドの最初の引数のファイルの部分が削除されています。これにより、プロジェクト ファイルのみではなく、フォルダー全体がコピーされます。 これらの変更を行わない場合、このステージで MSBuild エラーが発生します。

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["docker/ComposeSample/WebApi/", "WebApi_build/"]
RUN dotnet restore "WebApi_build/WebApi.csproj"
COPY . .
WORKDIR "/src/WebApi_build"
RUN dotnet build "WebApi.csproj" -c Release -o /app/build

問題: 認証資格情報

ワークフローにより、Azure アクセスを設定するための正しいユーザー名とパスワードのシークレットが要求されます。 Visual Studio では、Azure アセットを作成するとき、またはMicrosoft Visual Studio IDEの GitHub Actions 画面から、これの実行を自動的に試みます。 GitHub のシークレットが正しい場所にあるかを確認するか、必要な場合はリポジトリの [Settings] セクションを使用して、シークレットを再生成し、再度 GitHub に追加することができます。 シークレット ID を、ワークフローの各セクションで参照されている内容と照合して確認します。 必要に応じて、Azure portal のコンテナー レジストリにアクセスし、コンテナー レジストリ用のユーザー名とパスワードを取得して、それらの値を使用して GitHub のシークレットを更新できます。

az ad sp create-for-rbac コマンドを実行してサービス プリンシパルを設定し、クライアント ID、クライアント シークレット、およびテナント ID を取得した場合は、クライアント ID とクライアント シークレットをシークレットとして、お使いの GitHub リポジトリの [GitHub Actions Secrets] セクションに追加します。 Azure Container App の認証には、ユーザー名 (アプリのクライアント ID) とパスワード (クライアント シークレット) の形式で Azure のログイン資格情報を指定することができます。 これを行うには、手順 Azure login を次のコードに置き換えます。 クライアント ID とクライアント シークレット用に作成した独自の GitHub シークレット名を使用し、テナント ID は同じコマンドの出力から使用します。

- name: Azure login
  uses: azure/CLI@v1
  with:
    inlineScript: |
      az login --service-principal -u ${{ secrets.GITHUB_SECRETID_FOR_USERNAME }} -p ${{ secrets.GITHUB_SECRETID_FOR_PASSWORD }} --tenant {your tenant ID}
      az account list

Dockerfile が正常に機能し、認証が正しい場合に、ワークフローで引き続き問題が発生する場合は、次のリソースを検討してください。

どのプロジェクトの種類がサポートされていますか?

  • ASP.NET Core
  • ASP.NET 5 以降
  • Azure Functions

どの Azure サービスがサポートされていますか?

  • Azure Web Apps
  • Azure Functions
  • Azure API Management