📝

Azure Functions Core ToolsでAzure FunctionsをローカルのVSCode上で開発・テストできるようにする

2024/06/22に公開

執筆日

2024/06/22

概要

Azure Functionsは、Azure上で実行されるサーバーレスコンピュートサービスです。様々なイベントに基づいてコードを自動的に実行できます。HTTPリクエストへの応答、定期的なスケジュールでのタスク実行、または他のAzureサービスや外部サービスからのイベントに応じた処理などが可能です。
ですが、開発のデバッグ時点でリソースを作成してコストがかかってしまうのは相当お金に余裕のある人でなければ避けたいと思います。そこで今回はローカルのVSCode上で開発・テストを行う方法を紹介したいと思います。

動作環境

Windows, Mac, Linuxで問題なく動きます。(サポート切れOSでなければ)
言語は、Python, JavaScript, TypeScript, C#, Java, Ballerina, Powershell, Custom Handlerなどに対応しているようです。
筆者はWindows11, Python3.11環境で動作確認しています。(執筆時点で最新のpython3.12には対応していなかったので常に最新のバージョンが使えるわけではないようです)

インストール

Azure Functions Core Tools

Azure Functions Core Toolsを利用することでローカルでAzure Functionsを開発・テストできます。 Core Toolsで作成したプロジェクトをAzureにデプロイし、アプリケーション設定を操作することもできます。

  • インストーラーを使う場合
  • npmでインストールする場合
    • https://nodejs.org/en からNode.js, npmのLTSバージョンのインストール
    • npm install -g azure-functions-core-tools@4 --unsafe-perm true
    • ※ @4は、使用するAzure Functionsのバージョンを指定しています。適宜最新バージョンに合わせてください。

VSCodeの拡張機能インストール

以下の拡張機能をインストールします。

  • Azure
  • Azure Functions

プロジェクトの作成

必要なインストール作業が完了したら、VSCode上でプロジェクトのテンプレート作成を行います。
以下の画像のようにAzure拡張機能のWORKSPACEタブのAzure Functionsのアイコンを出します。

  1. Azure Functionsのアイコンをクリックし、Create New Projectを選択
  2. VSCode上部に表示される指示に従って設定
    • Functionsを作成するフォルダを選択
    • 使用する言語を選択
      • Pythonを選択するとプログラミングモデルのバージョン選択が出る(推奨されているバージョンを選択すればいい)
    • 作成する関数が何をトリガーに実行されるかを選択
    • 関数に名前を付ける
    • 認証レベルの選択
      • 認証レベルは、機能がAPIキーを必要とするかどうか、どのキーを使用するかを制御します。FUNCTIONSはファンクションキー、ADMINはマスターキーを使用します。これらが選択されると、ポータルの「キー」管理パネルに表示されます。

以上を実行することで、プロジェクトが作成され画像のようにファイルと仮想環境が用意されます。

PythonでHTTP triggerを選択、認証レベルをANOYMOUSにした場合以下のようなテンプレートスクリプトが作成されます。(関数名は仮で<関数名>としています)

function_app.py
import azure.functions as func
import logging

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="<関数名>")
def <関数名>(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )

実行テスト

  • テストの開始
    VSCode上でF5、またはターミナルでfunc host startでスタート
    以下のようなログが出ればHTTPリクエストを受け付ける状態になっています
$ func host start
Found Python version 3.10.11 (py).

Azure Functions Core Tools
Core Tools Version:       4.0.5801 Commit hash: N/A +5ac2f09758b98257e728dd1b5576ce5ea9ef68ff (64-bit)
Function Runtime Version: 4.34.1.22669

[2024-06-22T02:23:53.735Z] Worker process started and initialized.

Functions:

        <関数名>:  http://localhost:7071/api/<関数名>

For detailed output, run func with --verbose flag.
[2024-06-22T02:23:58.618Z] Host lock lease acquired by instance ID '<instance_id>'.

HTTPリクエストを送る場合、新しいターミナルを開いて以下のように実行します。

  • unix系
curl -X POST http://localhost:7071/api/req/<関数名> -H "Content-Type: application/json" -d "{"name":"なまえ"}"
  • windows Powershell
$body = @{
    name = "なまえ"
} | ConvertTo-Json

$response = Invoke-WebRequest -Uri "http://localhost:7071/api/req/<関数名>" -Method POST -Body $body -ContentType "application/json"
Write-Output $response.Content

以下のようにレスポンスが返ってくれば成功です。
Hello, なまえ. This HTTP triggered function executed successfully.

Tips

pythonライブラリの追加

requirements.txtにライブラリを追加しておけばテスト実行・デプロイ時に自動でインストールしてくれます。

ローカル開発時の環境変数

テンプレート作成時にできるlocal.settings.jsonValuesが環境変数の一覧になります。ここで環境変数を設定すればpythonであればos.getenvで取得が可能になります。本番環境ではPortal上でアプリケーション設定の追加から環境変数を設定することができます。

local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
    "TEST": "test000" # 追加した環境変数
  }
}

Dockerコンテナ上で実行できるようにビルドする

Azure Functions実行サーバーOSにインストールされていないライブラリが必要な場合はDockerコンテナ内で実行することもできます。
以下の方法でローカルで実行できますが、認証キーが必要な設定にしている場合はHTTPリクエストが送れないので注意してください。function_app.pyのapp定義で、

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

とすることで認証を不要にできますが、デプロイする際に元の認証設定に戻すことを忘れないように工夫してください。

$ func init --worker-runtime python --docker # Dockerfileが作成される
$ docker build -t <app name> . # イメージのビルド
$ docker run -p 7071:80 -it azurefuncapp # コンテナ起動

参考

https://learn.microsoft.com/ja-jp/azure/azure-functions/
https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-develop-vs-code?tabs=node-v4%2Cpython-v2%2Cisolated-process&pivots=programming-language-python
https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=windows%2Cisolated-process%2Cnode-v4%2Cpython-v2%2Chttp-trigger%2Ccontainer-apps&pivots=programming-language-python#install-the-azure-functions-core-tools

あとがき

HTTPリクエスト以外のトリガーや、Azureへのデプロイ方法についても紹介しようと思いましたが、タイトルに直接関係のないことまで書きたいこと全部書くのは悪い癖だと思ったのでここまでにしました。偉い。
また時間を作って関連する記事を書きたいと思います。

関連記事

https://zenn.dev/headwaters/articles/f343dbf79c8de9

ヘッドウォータース

Discussion