2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Azure Container Registry 上の Docker image を Function on Container にDeployして動かしたい

Last updated at Posted at 2023-06-08

はじめに

  • 下記のAzureリソースは作成してあるものとします
    • ContainerをデプロイできるFunctionApp
    • Azure Container Registry
  • Dockerイメージとしてビルドするアプリケーションおよび、Dockerfileはできているものとします

この記事の内容を執筆するにあたり、技術検証段階でAzureサポートのOさんに大きなご助力をいただきました。この場をお借りして感謝申し上げます💐

パイプラインを作成

yamlファイルを作成

AzurePipelinesで使用できるyamlファイルのテンプレートや、TIPSが紹介されているMicrosoft公式のリポジトリがあります。ご存じなかった方はスターしておくと良いかもしれません。
こちらで公開されてるテンプレートの中にこんなものがありました。

Build a Docker image, push it to an Azure Container Registry, and deploy it to an Azure Functions app.

まさにやりたいこととドンピシャ!
ありがたく参考にさせてもらいましょう🎉

参考にして作ったyaml

テンプレートにはAzureリソース作成も含まれてましたが、今回は作成済みの前提なので、以下のことだけに内容を変更します。

  • Dockerイメージをビルド
  • Azure Container Registryにイメージをpush
  • FunctionAppにデプロイするイメージを設定
長いので折りたたんでます🎬
functionapp-from-acr.yml
# Docker image, Azure Container Registry, and Azure Functions app
# Build a Docker image, push it to an Azure Container Registry, and deploy it to an Azure Functions app.
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

# Copy元: https://github.com/microsoft/azure-pipelines-yaml/blob/master/templates/docker-container-functionapp.yml

# A pipeline with no CI trigger
trigger: none

resources:
  - repo: self

variables:
  pool: 'ubuntu-latest'
  Azure.ServiceConnectionId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
  FunctionApp.Name: 'docker-func-sample'
  ACR.Name: 'sampleimage'
  ACR.ImageName: '$(ACR.Name):$(Build.BuildId)'
  ACR.FullName: 'acrqiitasample.azurecr.io'

jobs:
  - job: BuildAndPushImage
    displayName: Build And Push an Docker Image
    condition: succeeded()

    pool:
      vmImage: $(pool)

    steps:
      - task: Docker@1
        displayName: 'Build an image'
        inputs:
          azureSubscriptionEndpoint: '$(Azure.ServiceConnectionId)'
          azureContainerRegistry: '$(ACR.FullName)'
          imageName: '$(ACR.ImageName)'
          command: build
          dockerFile: '$(Build.SourcesDirectory)/Dockerfile'

      - task: Docker@1
        displayName: 'Push an image'
        inputs:
          azureSubscriptionEndpoint: '$(Azure.ServiceConnectionId)'
          azureContainerRegistry: '$(ACR.FullName)'
          imageName: '$(ACR.ImageName)'
          command: push

  - job: UpdateAppServiceConfiguration
    displayName: Update AppService Configuration to Deploy an Image
    dependsOn: BuildAndPushImage
    # See https://learn.microsoft.com/ja-jp/azure/devops/pipelines/process/expressions?view=azure-devops#job-to-job-dependencies-within-one-stage
    condition: or(succeeded(), eq(dependencies.BuildAndPushImage.result, 'Succeeded'))

    pool:
      vmImage: $(pool)

    steps:
      - task: AzureFunctionAppContainer@1
        displayName: 'Azure Function App on Container Deploy: $(FunctionApp.Name)'
        inputs:
          azureSubscription: '$(Azure.ServiceConnectionId)'
          appName: $(FunctionApp.Name)
          imageName: '$(ACR.FullName)/$(ACR.ImageName)'

パイプラインの中でやってることをざっくり説明

  • BuildAndPushImage Job
    • Dockerイメージをbuildする
    • Azure Container Registry にDockerイメージをpushする
  • UpdateAppServiceConfiguration Job
    • FunctionAppに使用するDockerイメージを設定
      • Trying to update App Service Configuration settings. Data: {"appCommandLine":null,"linuxFxVersion":"DOCKER|acrqiitasample.azurecr.io/sampleimage:1293"}

パイプラインを動かした後に、FunctionのBashから環境変数を見ると、Dockerイメージの情報が登録されています。

$ echo $LINUX_FX_VERSION
DOCKER|acrqiitasample.azurecr.io/sampleimage:1293

Azure DevOpsのPipelineを作成する

このあたりを参考に、functionapp-from-acr.ymlをPipelineとしてAzure DevOpsで実行できるようにします。たぶんGUI見ればできると思います👍🏻
最初のパイプラインの作成 - Azure Pipelines | Microsoft Learn

PipelineからAzureリソースへの接続に使用するサービスコネクション作成

下記の接続に使用されます。

  • Pipeline→ACR
  • Pipeline→FunctionApp

AzureDevOpsでの作業

[ProjectSettings]-[Pipelines]-[Service connections]にて、「New service connection」をクリック

様々なAzureリソースに対し操作を行うことになるので、Azure Resource Managerを選択。

推奨設定の Service principal (automatic) を選択

ここで認証を求めるポップアップが出るので、ブロック設定になってると先に進めないので注意🧱
ARMで操作するスコープとなるサブスクリプションやリソースグループをプルダウンで選択し、サービスコネクション名を入力したら「Save」をクリック。

サービスコネクションが作成されます。

AzureADの「アプリの登録」画面におけるアプリケーション一覧に、作成したサービスコネクションが表示されます。隠してるところだらけで分かりづらくて申し訳ない......

作成したサービスコネクションの情報を、yamlパイプラインに反映

作成したサービスコネクション名をyamlのvariablesに記載します。

variables:
  pool: 'ubuntu-latest'
- Azure.ServiceConnectionId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+ Azure.ServiceConnectionId: 'DockerFuncPocServiceConnection'

なお、サービスコネクションの詳細ページURLにおけるクエリパラメータ(resourceId)として確認できるUUIDを記載してもOKです。

サービスコネクション名を頻繁に変更するニーズはあまりないと思いますが、UUIDは不変なので、そのへんの心配がいらないです。

FunctionAppがAzure Container Registryに接続するための設定

Azure Container Registry で管理者ユーザを有効化する

コンテナレジストリにログインする情報として使用します。

FunctionAppのアプリケーション設定に認証情報を追加

コンテナレジストリの管理者情報を、下記のアプリケーション設定に追加する。

  • DOCKER_REGISTRY_SERVER_PASSWORD
  • DOCKER_REGISTRY_SERVER_URLhttps://<acrname>.azurecr.io形式
  • DOCKER_REGISTRY_SERVER_USERNAME

ここまでの設定で、ACRのDockerイメージをPullしてきて、Functionsとして動かすことができるはず。

パイプラインを動かして動作確認

Azure DevOpsでRun Pipeline

「Run pipeline」をクリック

Pipelineの全てのJobがSuccessしていることを確認します。

Pipeline実行時にこのようなエラーが出力された場合は、以下いずれかの原因である可能性が高いです⚡️

There was a resource authorization issue: "The pipeline is not valid. Job BuildAndPushImage: Step Docker1 input azureSubscriptionEndpoint references service connection xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx which could not be found. The service connection does not exist or has not been authorized for use. For authorization details, refer to https://aka.ms/yamlauthz."

  1. サービスコネクション名かUUIDが間違っている
  2. Pipelineがサービスコネクションを使用するPermissionを持っていない

原因が2だと思われる場合、こちらの手順を参考に、PipelineにPermissionを与えてください。

ServiceConnectionの詳細ページより、メニュー内の「Security」をクリック

「Pipeline permission」セクションにおいて、許可を与えたいPipelineを選択

ACRにPushされているかチェック

ACRのリポジトリを見ると、Pipelineの中でBuildされたImageがpushされています。

AzurePortal上で関数として読み込まれているかチェック

関数アプリの「関数」ブレードより、関数としてAzure側が識別しているかをチェックします。Dockerコンテナが正常に起動できていないと、ここに何も表示されないんです😵

実際に動作確認

関数が期待する動作をしてたらOKです💪

$ curl -X GET "https://docker-func-poc.azurewebsites.net/api/HttpTriggerSample?name=YOS0602&code=ABCDEFG=="
Hello, YOS0602. This HTTP triggered function executed successfully.

関数が読み込めていない or Dockerコンテナがうまく起動していないなどの場合

どこでコケてるか次第ですが、FunctionがImageをPullできていない場合、後述しているマネージドID有効化とIAMロール付与を試してみると良いかもしれません。
なお、npmを利用したアプリケーションでDockerを使用していると、「ユーザー名前空間再割当てエラー」が発生して、Dockerコンテナが上手く起動しないことがあります。詳細および対策はこちらの記事を参考にしてみてください。
App Service における Docker User Namespace remapping issues について - Japan PaaS Support Team Blog - #NPM 利用プロジェクトにおける ユーザー名前空間再割当てエラー

FunctionAppのマネージドIDを有効化

システム割り当てマネージドIDを有効化し、「保存」します。

「はい」をクリック。

AcrPullのIAMロールを付与

コンテナレジストリのIAMより、ロールの割り当ての追加を行います。

AcrPullロールを選択して「次へ」

先ほど有効化したFunctionAppのマネージドIDを選択する。

「レビューと割り当て」を行う。

FunctionAppを再起動

az cliでも、Portalからでも良いです。設定が反映されるまで数分かかることもあるので待ちましょう⏱️

参考

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?