Open1

Azure Functionsの開発環境を整える

Yuki YamadaYuki Yamada

Azure Functionsとは?

Azure FunctionsはAzureのサーバレスソリューションで特にイベント駆動型の処理を記述するのに適したソリューションです。

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-overview?pivots=programming-language-csharp

なおAzure Functionsで実現できる処理のシナリオのサンプルは公式ドキュメントにまとまっているのでそちらをみることで実現できることを把握できるかと思います。

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-scenarios?pivots=programming-language-csharp

PythonでAzure Functionsのプロジェクトを作成する

ここからはPythonでAzure Functionsのプロジェクトを作成してみようと思います。

開発環境のセットアップ

開発エディタにはVSCodeを利用します。
VSCodeにAzure Functionsの拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions

他にAzure Functions Core Toolsをインストールします。
私はWSLを使って開発をしているので以下のコマンドでインストールします。

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-get update
sudo apt-get install azure-functions-core-tools-4

PythonのAzure Functionsプロジェクトの作成

拡張機能インストール後にctrl+shift+pよりAzure Functions: Create New Project...から対話形式でPythonのプロジェクトを作成します。

なおお今回はBlobトリガーで関数を一つだけ存在するプロジェクトを作成しています。

作成後は以下のようの構造のプロジェクトが作成されます。

.
├── function_app.py
├── host.json
├── local.settings.json
└── requirements.txt

依存関係を管理するrequirements.txtは以下のようになっており、azure-functionsだけが依存関係に存在します。

# DO NOT include azure-functions-worker in this file
# The Python Worker is managed by Azure Functions platform
# Manually managing azure-functions-worker may cause unexpected issues

azure-functions

Pythonの仮想環境の作成

依存関係のインストールなどを実行する前にPythonの仮想環境を作成します。

# 仮想環境の作成
python -m venv .venv
# 作成した仮想環境に入る
source .venv/bin/activate

仮想環境のセットアップが完了したので、依存関係をインストールします。

pip install -r requirements.txt 

依存関係のインストールが完了したら、Azure Functionsを起動してみます。

func start

しかしこの状態だと以下のようなエラーになります。

Found Python version 3.11.2 (python3).

Azure Functions Core Tools
Core Tools Version:       4.0.5455 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.27.5.21554

[2024-02-07T11:46:39.362Z] Customer packages not in sys path. This should never happen! 
[2024-02-07T11:46:39.904Z] A host error has occurred during startup operation 'ac98da8c-6ad3-414e-9429-757b77d29686'.
[2024-02-07T11:46:39.904Z] Microsoft.Azure.WebJobs.Script.WebHost: Secret initialization from Blob storage failed due to missing both an Azure Storage connection string and a SAS connection uri. For Blob Storage, please provide at least one of these. If you intend to use files for secrets, add an App Setting key 'AzureWebJobsSecretStorageType' with value 'Files'.
Value cannot be null. (Parameter 'provider')
[2024-02-07T11:46:39.940Z] Host startup operation has been canceled

これはAuzre Functionsで接続する先にStorageアカウントの情報が設定されていないからになります。

そこでローカルでStorageアカウントを動かすためのエミュレータAzuriteを立ち上げて設定していきます。

AzuriteをDockerで立ち上げる

azuriteのDockerイメージをpullします。

# azuriteのDockerイメージのpull
docker pull mcr.microsoft.com/azure-storage/azurite

イメージをpullしたら、コンテナを起動します。

docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 \
    mcr.microsoft.com/azure-storage/azurite

Azure Functionsの接続先をAzuriteに設定する

次にlocal.settings.jsonを更新して、Azure FunctionsからAzuriteに変更します。
Azuriteを利用する際に接続文字列を以下のように設定する必要があります。

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;

https://learn.microsoft.com/ja-jp/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage

こちらをlocal.settings.jsonAzureWebJobsStorageに設定します。

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;",
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
    "d4ab46_STORAGE": "UseDevelopmentStorage=true"
  }
}

この状態で再度、Azue Functionsを起動します。

func start

今度は起動に成功し、Blobトリガーの関数が1つ読み込まれていることがわかります。

Found Python version 3.11.2 (python3).

Azure Functions Core Tools
Core Tools Version:       4.0.5455 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.27.5.21554

[2024-02-07T12:48:01.492Z] Customer packages not in sys path. This should never happen! 
[2024-02-07T12:48:02.336Z] Worker process started and initialized.

Functions:

        blob_trigger: blobTrigger

For detailed output, run func with --verbose flag.
[2024-02-07T12:48:07.307Z] Host lock lease acquired by instance ID '000000000000000000000000817FFB67'.

Blobにファイルをアップロードして挙動を確かめる

Azuriteで起動しているBlobのエミュレータにアクセスするためにAzure Storage Explorerをインストールします。

https://azure.microsoft.com/ja-jp/products/storage/storage-explorer

インストールして起動したら、エミュレータのBlobストレージに新規コンテナ「mycontainer」を作成します。

作成したコンテナ「mycontainer」に適当にファイルをアップロードします。

アップロードが完了し、Azure Functions側のコンソールを確認するときちんとBlobトリガーの関数の処理が行われていることが確認できます。

[2024-02-07T13:17:23.446Z] Executing 'Functions.blob_trigger' (Reason='New blob detected(LogsAndContainerScan): mycontainer/sample.png', Id=d81fb6a8-71bd-4375-bd68-295c7a76c90d)
[2024-02-07T13:17:23.447Z] Trigger Details: MessageId: 2ee292bf-e2bb-4ce9-a88e-c1ea8643afc8, DequeueCount: 1, InsertedOn: 2024-02-07T13:17:23.000+00:00, BlobCreated: 2024-02-07T13:17:22.000+00:00, BlobLastModified: 2024-02-07T13:17:22.000+00:00
[2024-02-07T13:17:23.501Z] Python blob trigger function processed blobName: mycontainer/sample.pngBlob Size: None bytes
[2024-02-07T13:17:23.515Z] Executed 'Functions.blob_trigger' (Succeeded, Id=d81fb6a8-71bd-4375-bd68-295c7a76c90d, Duration=126ms)