演習 - Azure Functions アプリを Azure にデプロイする

完了

プロジェクトには、ソリューション内にプロジェクトをビルドし、Web アプリを Azure App Service にデプロイするパイプラインが付属しています。 ここでは、そのパイプラインを、新しい Azure Functions プロジェクトもデプロイするように拡張します。

このパートでは、次のことを行います。

  • "ビルド" ステージを確認する。
  • 関数アプリをデプロイするタスクを追加する。
  • 発行済みの関数を使用するように発行済みの App Service を構成するタスクを追加する。
  • CI/CD ワークフローをトリガーする、パイプラインを保存する。

ビルド ステージを確認する

ここでは、azure-pipelines.yml で定義されている既存の CI/CD パイプラインを確認します。

  1. Azure DevOps から、[パイプライン] に移動します。

  2. パイプラインを選択します。

  3. [編集] を選択します。 ドロップダウン メニューから選択して、ブランチを main に設定しておきます。 これにより、既存の CI/CD パイプラインを定義する azure-pipelines.yml ファイルが表示されます。

    プロジェクトのパスにワイルドカードを使用するため、以下の強調表示されているタスクでは、新しい Azure Functions プロジェクトの復元、ビルド、および発行が自動的に行われます。

    stages:
    - stage: 'Build'
      displayName: 'Build the web application'
      jobs: 
      - job: 'Build'
        displayName: 'Build job'
        pool:
          vmImage: 'ubuntu-20.04'
          demands:
          - npm
    
        variables:
          wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot'
          dotnetSdkVersion: '6.0.x'
    
        steps:
        - task: UseDotNet@2
          displayName: 'Use .NET SDK $(dotnetSdkVersion)'
          inputs:
            version: '$(dotnetSdkVersion)'
    
        - task: Npm@1
          displayName: 'Run npm install'
          inputs:
            verbose: false
    
        - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)'
          displayName: 'Compile Sass assets'
    
        - task: gulp@1
          displayName: 'Run gulp tasks'
    
        - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt'
          displayName: 'Write build info'
          workingDirectory: $(wwwrootDir)
    
        - task: DotNetCoreCLI@2
          displayName: 'Restore project dependencies'
          inputs:
            command: 'restore'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Build the project - $(buildConfiguration)'
          inputs:
            command: 'build'
            arguments: '--no-restore --configuration $(buildConfiguration)'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Publish the project - $(buildConfiguration)'
          inputs:
            command: 'publish'
            projects: '**/*.csproj'
            publishWebProjects: false
            arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)'
            zipAfterPublish: true
    
        - publish: '$(Build.ArtifactStagingDirectory)'
          artifact: drop
    

Andy: これが以前のビルド ステージでした。 私はこれを元のプロジェクトから変更しませんでした。これらのタスクが、すべてのプロジェクトに対してワイルドカード一致パターンに基づいて実行されるように、あらかじめ構成されていたからです。

Mara: ええ、これはそのままで動作するはずです。 ここで変更を加える必要はないと思います。 このビルド タスクが実行されると、デプロイ ステージで使用するために、Web プロジェクトとランキング プロジェクトの両方の zip ファイルの成果物が発行されます。

Azure 関数をデプロイするタスクを追加する

Andy: App Service のデプロイ タスクをそのまま再利用することもできると思います。 うまくいけば、関数アプリをデプロイするために使用できる同じようなものがあります。

Mara: 良いニュースがあります。 少し調べてみたら、概念的には App Service のデプロイ タスクと似ていますが、AzureFunctions のデプロイ タスクがあるようです。 確認してみましょう。

Azure 関数アプリのタスク

この AzureFunctionApp@1 タスクは、関数アプリをデプロイするように設計されています。 概念的には AzureWebApp@1 タスクに似ていて、この関数アプリのシナリオに必要なすべてのものが含まれています。

  • azureSubscription は、お使いの Azure サービスの接続パイプライン変数名のことを示します。
  • appType は、アプリが Linux 用 (functionAppLinux) または Windows (functionApp) にデプロイされているかどうかを示します。
  • appName は、お使いの Azure アカウントの Azure Functions アプリ インスタンス名を指定します。
  • package は、デプロイするパッケージのパスを指定します。
  • runtimeStack は、関数を実行するイメージを指定します。これは、Linux のデプロイで必要です。
  • startUpCommand は、関数のデプロイ後に実行する起動コマンドを指定します。これは、Linux のデプロイで必要です。

このタスクの柔軟性の詳細については、Azure 関数アプリのタスクについてのドキュメントを参照してください。

強調表示されている次のコードをパイプラインの末尾に追加します。

- stage: 'Deploy'
  displayName: 'Deploy the web application'
  dependsOn: Build
  jobs:
  - deployment: Deploy
    pool:
      vmImage: 'ubuntu-20.04'
    environment: spike
    variables:
    - group: Release
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: drop
          - task: AzureWebApp@1
            displayName: 'Azure App Service Deploy: website'
            inputs:
              azureSubscription: 'Resource Manager - Tailspin - Space Game'
              appName: '$(WebAppName)'
              appType: webAppLinux
              package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/Tailspin.SpaceGame.Web.zip'

          - task: AzureFunctionApp@1
            displayName: 'Azure Function Deploy: leaderboard'
            inputs:
              azureSubscription: 'Resource Manager - Tailspin - Space Game'
              appType: functionAppLinux
              appName: '$(LeaderboardAppName)'
              package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/Tailspin.SpaceGame.LeaderboardFunction.zip'
              runtimeStack: DOCKER|microsoft/azure-functions-dotnet:4
              startUpCommand: 'func azure functionapp publish $(functionAppName) --no-bundler'

ヒント

YAML ファイルでは、空白が重要です。 ここで追加するタスクでは、必ず前のタスクと同じインデントを使用してください。

App Service のアプリ設定を更新するタスクを追加する

Andy: 次にやるべきことは、発行済みのランキング API を使用するように Web アプリを構成することです。 通常はポータルで変数を構成しますが、ここでそれができる方がよいでしょう。 これは LeaderboardFunctionUrl という名前の AppSettings パラメーターを想定しています。

Mara: 賛成です。 そのためのタスクをパイプラインに追加すると、いずれかのサービスを変更した場合に、将来の偶発的な見落としを回避するのに役立ちます。 最後に修正することができます。

強調表示されている次のコードをパイプラインの末尾に追加します。 必ずその上のタスクのインデントに合わせてください。 このタスクの詳細については、Azure App Service の設定タスクに関するドキュメントを確認してください。

- task: AzureFunctionApp@1
  displayName: 'Azure Function Deploy: leaderboard'
  inputs:
    azureSubscription: 'Resource Manager - Tailspin - Space Game'
    appType: functionAppLinux
    appName: '$(LeaderboardAppName)'
    package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/Tailspin.SpaceGame.LeaderboardFunction.zip'
    runtimeStack: DOCKER|microsoft/azure-functions-dotnet:4
    startUpCommand: 'func azure functionapp publish $(functionAppName) --no-bundler'

- task: AzureAppServiceSettings@1
  displayName: 'Update web app settings'
  inputs:
    azureSubscription: 'Resource Manager - Tailspin - Space Game'
    appName: $(WebAppName)
    resourceGroupName: $(ResourceGroupName)
    appSettings: |
      [
        {
          "name": "AppSettings__LeaderboardFunctionUrl",
          "value": "http://$(LeaderboardAppName).azurewebsites.net/api/LeaderboardFunction",
          "slotSetting": false
        }
      ]

パイプラインを保存してビルドとリリースをトリガーする

  1. ページの右上隅で、[Save] を選択します。 [Save] を確認して、実行をトリガーします。

  2. Azure Pipelines でビルドに移動します。 実行中に、ビルドをトレースします。

  3. ビルドが正常に完了したら、Web サイトのデプロイ タスクを選択し、URL を選択して、デプロイされたサイトを表示します。

    A screenshot of Azure Pipelines, showing the location of the web site URL.

  4. App Service で実行されているサイトを含むページが表示されます。 下にスクロールして、ランキングに実際のデータが含まれていることを確認します。 これは、関数アプリを利用しています。

    A screenshot of the Space Game web site.

    Note

    ランキングの読み込み中にエラーが発生した場合は、このモジュールで実行した手順を再確認してください。 "アクセス許可で禁止されている方法でソケットにアクセスしようとしました" という例外メッセージが表示された場合は、App Service の AppSettings__LeaderboardFunctionUrl 設定が正しく設定されていることを確認してください。

  5. 関数アプリを直接テストすることもできます。 次の形式を使用して URL に移動するだけです。 応答は JSON です。これは、ブラウザーにテキストとしてレンダリングされるだけです。

    http://<leaderboard function name>.azurewebsites.net/api/LeaderboardFunction?pageSize=10
    

    例を以下に示します。

    http://tailspin-space-game-leaderboard-4692.azurewebsites.net/api/LeaderboardFunction?pageSize=10
    

    A screenshot of a web browser showing the JSON response from the leaderboard API Azure Functions app.

Andy: これはすばらしい結果になりました! 私たちがここに示した可能性に、誰もがかなり感銘を受けるはずです。