いしぐめも

プログラミングとかしたことを書きます。

【Azure Functions】ローカル開発でもカスタムコンテナーを使いたい!

Azure Functionsを利用するアプリ開発(≠Azure Functionsの開発)において、どのようにローカル開発を行うかというのは大きな課題です。

一番ベタなのは azure-functions-core-tools を使用しての開発かなと思いますが、Functions自体はコンテナ化しておきたいと考えると、ローカル開発とデプロイされるものが異なってしまうのが難点かなと個人的には思います。

というわけで、今回はローカル環境で本番と同じコンテナイメージを使って開発してしまおうという内容になります。

はじめに: カスタムコンテナーとは?

そもそも、Azure Functionsにはソースコードをコンテナに配置して、そのイメージをデプロイするというオプションがあります。

カスタム イメージを使用して Linux 上で Azure Functions を作成する | Microsoft Learn

これをドキュメントでは「カスタムコンテナー」として扱っているんですが、クラウドにデプロイして使う方法しかドキュメントには載っていません。ローカルでも使えたらきっと便利ですよね。

カスタムコンテナーで内部的に使用されているのは azure-functions-host

上記の手順に従ってカスタムコンテナーを作って動かしてみると、どうも内部的に使用されているのは azure-functions-host というものらしいです。詳細は以下のリポジトリを参照。

GitHub - Azure/azure-functions-host: The host/runtime that powers Azure Functions

これはどうやらAzure Functionsで使用されているランタイムのようで、これ公開してるのすごいなと思いつつ、仕様がオープンになっているのでありがたく使わせていただきましょう。

カスタムコンテナーをローカル開発で使用する手順

では、ここからはAzure Functionsで使用するカスタムコンテナーをローカル開発で使用するにあたって必要な手順を書いていきたいと思います。

カスタムコンテナーを作る

まずはドキュメントに従ってカスタムコンテナーを作ります。

mcr.microsoft.com/azure-functions/python などをベースに、requirementsをインストールしてソースコード/home/site/wwwroot に配置するという感じになるかなと思います。(pythonのばあい)

起動用のdocker-composeを書く

次に、起動用にdocker-composeを書いていきます。

version: '3.7'

services:
  functions:
    build: .
    environment:
      AzureWebJobsStorage: DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000/devstoreaccount1;QueueEndpoint=http://azurite:10001/devstoreaccount1;
      AZURE_FUNCTIONS_ENVIRONMENT: Development
    ports:
      - 80:80

  azurite:
    image: mcr.microsoft.com/azure-storage/azurite
    hostname: azurite
    restart: always
    ports:
      - 10000
      - 10001
      - 10002

ローカルでキューストレージのトリガを使ったりするために Azurite というストレージアカウントのエミュレータを同時に動かすようにしています。(なくても動くかも。)

(Optional)ローカル開発時の認証を消す

azure-functions-core-toolsでは、実行時にauthLevelがanonymousになるという仕様があるんですが、このカスタムコンテナーだとそれがありません(本番環境にも同じものがデプロイされるので当然)。なので、本番はauthLevelでfunction で使うことを想定している場合にカスタムコンテナーではローカル開発では使用できないという問題が発生してしまいます。

というわけで、私は起動時の実行コマンドで以下のようにsedでauthLevelをanonymousに変更して起動するようにしてみました。

    command: >-
      bash -c '
      sed -i -e "s/\"authLevel\":.*/\"authLevel\": \"anonymous\",/" /home/site/wwwroot/hogefunc/function.json
      && /azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost
      '

実行する

作ったdocker-compose.ymlファイルを通常通り起動すればOKです。

docker-compose up

終わりに

以上、ローカル開発でAzure Functionsのカスタムコンテナーを使用するという話でした。

ユースケースとしては、

「Azure Functionsに直接乗っかるものを開発するのには azure-functions-core-tools を使用して、ある程度固まったらカスタムコンテナー化して今度はそのFunctionsを利用する側のアプリを書く」

そんな感じでうまく使い分けられると良いんじゃないかと思いました。

今回作ったdocker-compose.ymlをベースにdevcontainersで使用したりするのもGOODですね。