しばやん雑記

Azure Serverless とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Functions (Windows / Linux) へのデプロイを行う方法と挙動の違いをまとめた

最近は Visual Studio 2022 + C# 以外で Azure Functions を作成することが増えてきました。その場合は主に Visual Studio Code を使ってプロジェクト作成からデプロイまで行うのですが、Azure Functions を実行する OS とデプロイに利用する方法で若干挙動が変わるので簡単にまとめました。

環境毎に確認した結果は以下の通りになるので、ここだけ読めば大体は問題ありません。ちなみに言語は全て Node.js (TypeScript) で試しています。

Windows ASP Windows FP Linux ASP Linux FP
Visual Studio Code Run From Package Run From Package Zip Deploy Zip Deploy
Azure Functions Core Tools Run From Package Run From Package Run From Package Run From Package (URL)
Azure CLI Zip Deploy Zip Deploy Zip Deploy Zip Deploy
GitHub Actions (Publish Profile) Zip Deploy Zip Deploy Zip Deploy Zip Deploy
GitHub Actions (RBAC) Run From Package Run From Package Zip Deploy Zip Deploy

言語によっては多少変わりますが、基本はこのような挙動になります。ASP は App Service Plan で FP は Functions Premium のことを指しています。Consumption Plan に関しては実質的に Run From Package 強制なので省略しています。

一目で分かるように Windows の場合は安定して Run From Package が使われますが、Linux ではまちまちになっているので注意が必要です。Run From Package は Azure Functions では公式に推奨される方法となっていますし、アトミックなデプロイが行えパフォーマンス的にもメリットも多いです。

Zip Deploy と Run From Package といった Azure Functions が提供するデプロイ API については、何回か書いているので説明は必要ないと思いますが、公式ドキュメントが良い感じにまとまっているので紹介します。

Visual Studio Code や GitHub Actions からデプロイする際には、基本的にアプリケーションを ZIP にしたものをプッシュする Zip Deploy が使われます。

ここで若干わかりにくい部分があって、Zip Deploy には以下の 3 つのバリエーションが存在しています。

  • Zip Deploy
    • Remote Build (Kudu / Oryx でビルド)
    • Local Build (開発環境 / GitHub Actions でビルド)
      • Run From Package

実際には Remote Build でも一部の OS と言語の組み合わせでは、自動的に ZIP が作成されて Run From Package として実行されるケースもありますが、複雑になるので扱っていません。

Zip Deploy を行っていても、実際にはリモートでビルドが行われる場合があります。Python の場合はパッケージにプラットフォームに依存するものが含まれている可能性があるので、デフォルトで大体この挙動です。

ドキュメントにあるように Zip Deploy + Run From Package は全ての App Service Plan と OS の組み合わせで推奨されています。ただし App Service Plan と OS の組み合わせでは自動で無効化されています。

Local Build を行っていても明示的に WEBSITE_RUN_FROM_PACKAGE を設定していない限りは、デプロイ時に unzip されて wwwroot に展開されます。Node.js では unzip 後に npm install が実行されます。Run From Package では追加の処理を必要としないポータブルな形で ZIP を作成する必要があります。

ここから先はデプロイ方法毎での詳細になるので、興味のある方のみ読んでもらえれば良いです。

Visual Studio Code

Azure Functions へのデプロイを Visual Studio Code の拡張機能で行うと、Windows 向けの場合は自動的に Run From Package が有効になりますが、Linux 向けでは普通の Zip Deploy のままになります。

Windows とは異なり Linux では自動で WEBSITE_RUN_FROM_PACKAGE は追加されません。

Linux の App Service Plan と Functions Premium の場合は、Visual Studio Code からのデプロイ前に WEBSITE_RUN_FROM_PACKAGE の設定を追加しておくと、VS Code が自動的に設定を読み取って Run From Package としてデプロイしてくれます。

Windows と同じ感覚でいると Run From Package になっていないことが多いので注意が必要です。

Azure Functions Core Tools (func コマンド)

挙動に若干癖があるのが Azure Functions Core Tools を利用したデプロイです。通称 func コマンドを使ったデプロイには Azure CLI などで事前にログインしておく必要があります。

Azure Functions 専用ツールなのでオプションが非常に豊富ですが、デプロイ時の動作を理解しておかないと混乱してしまうと思います。Remote / Local Build を明示的に指定できるのが特徴です。

出来る限り Run From Package を使うようになっていますが、Linux の Functions Premium へのデプロイ時には何故か URL を指定した Run From Package になってしまいます。Functions Premium で URL 指定を使うメリットは無いため、明示的に 1 を設定してからデプロイするのがお勧めです。

Azure CLI

Azure CLI の Web Apps / Azure Functions コマンドに Zip Deploy 機能が用意されています。このコマンドは Azure Functions Core Tools の一部機能を持っていて、Remote / Local Build が指定可能です。

Remote / Local Build の設定は SCM_DO_BUILD_DURING_DEPLOYMENT が追加されるかどうかぐらいの差になっています。未指定の場合でも Linux の場合は追加されます。

それ以外の設定は特に変更されないため、Run From Package を行う場合には WEBSITE_RUN_FROM_PACKAGE 設定を事前に追加しておく必要があります。

Azure CLI だけあれば良いので、Cloud Shell からもデプロイ出来るお手軽さがあります。GitHub Actions や Azure Pipelines には Azure CLI が大体入っているので、CI/CD でも利用可能です。

GitHub Actions (functions-action@v1)

GitHub Actions を使ったデプロイでは認証情報は Publish Profile と RBAC (Service Principal) のどちらかで渡しているかによって挙動が変わります。理由としては Publish Profile には ARM レベルでの書き込み権限が無く、Kudu 経由のデプロイか設定の読み込みしか行えないためです。

Publish Profile ではなく RBAC (Service Principal) を使うと設定変更が行えるので、Windows 向けの場合は自動的に WEBSITE_RUN_FROM_PACKAGE 設定が追加されます。

実際の挙動としては Visual Studio Code を使ったデプロイと同じになるので、開発立ち上げ時には Visual Studio Code からデプロイを行い、実際の本格的な開発フェーズでは GitHub Actions から RBAC を使ってデプロイというのが整合性が取れていてわかりやすいです。

最近は GitHub Actions の OpenID Connect を使って、シークレットの管理無しに Service Principal が使えるようになっているので、多くのアプリケーションを管理する必要がある場合は Service Principal を作成して、RBAC で権限管理を行う方が簡単です。