はじめに
はじめまして、井村と申します。
本記事は公式ドキュメントの「クイック スタート: コマンド ラインから Azure で関数を作成する」を試した記事になります。
この記事ではローカル コマンド ライン ツールを使用して、HTTP 要求に応答する関数を作成します。
- コードをローカルで確認
- Azure Functions のサーバーレス Flex Consumption ホスティング プランにデプロイ
本記事のローカル環境はWindows端末になります。
コードをローカルで確認
前提条件
以下を準備します。
- Azureアカウントの新規作成。
- Pythonのインストール。
- AzureCLIのインストール。
-
jq command line JSON processorのインストール。
- JSON出力の解析に使用します。
各ツールのバージョンを確認します。
# Pythonのバージョン確認
py --version
Python 3.13.7 # 出力結果
# Azure CLIのバージョン確認
az version
# 出力結果
{
"azure-cli": "2.75.0",
"azure-cli-core": "2.75.0",
"azure-cli-telemetry": "1.1.0",
"extensions": {}
}
# jqのインストール
winget install jqlang.jq
# jqのバージョン確認
jq --version
jq-1.8.1 # 出力結果
Azure Functions Core Tools のインストール
Azure Functions Core Tools は、ローカル環境で Azure Functions を開発・テスト・デプロイするためのコマンドラインツールです。
主な機能
-
関数アプリの初期化
func init コマンドでプロジェクトを作成。言語(Python, JavaScript, C#, etc.)を指定可能。 -
関数の作成
func new コマンドでトリガー(HTTP, Timer, Blobなど)を指定して関数を追加。 -
ローカル実行とデバッグ
func start でローカル環境で関数を実行し、動作確認が可能。 -
Azureへのデプロイ
func azure functionapp publish <アプリ名> でAzure上に関数をデプロイ。 -
設定ファイルの管理
local.settings.json を使ってローカル環境の設定(環境変数など)を管理。
以下からインストールします。
バージョンを確認します。
# Azure Functions Core Toolsのバージョン確認
func --version
4.2.2 # 出力結果
仮想環境を作成してアクティブにする
デスクトップ上に作業フォルダを作成します。
# カレントディレクトリの確認
pwd
C:\Users\user\Desktop
# 作業フォルダの作成
mkdir Quickstart_Function_command_line
# 作業フォルダへの移動
cd .\Quickstart_Function_command_line\
Pythonの仮想環境(venv)を作成して有効化します。
# 仮想環境の作成
py -m venv .venv
# 仮想環境を有効化
.venv\Scripts\activate
# プロンプトが以下となります。
(.venv) PS C:\Users\user\Desktop\Quickstart_Function_command_line>
py -m venv .venv の意味
- py は Python ランチャー(Windows環境でよく使われます)
- -m venv は Python の標準モジュール venv を使って仮想環境を作成するという意味
- .venv は仮想環境のフォルダ名(慣例的に .venv や env が使われます)
このコマンドを実行すると、プロジェクトディレクトリ内に .venv フォルダが作成され、そこに独立した Python 環境が構築されます。
.venv\Scripts\activate の意味
これは、作成した仮想環境を有効化(activate)するコマンドです。
- Windows環境では Scripts\activate を使います
- 有効化すると、ターミナルのプロンプトが (venv) のように変わり、その環境内で Python や pip を使えるようになります
なぜ仮想環境を使うのか?
- 依存関係の分離
他のプロジェクトとライブラリのバージョンが混ざらないようにするため - 安全な開発環境
グローバル環境を汚さず、必要なライブラリだけをインストールできる - 再現性の確保
requirements.txt で環境を再構築しやすくなる
ローカル コード プロジェクトと関数を作成する
公式ドキュメントの翻訳。
Azure Functions では、コード プロジェクトは、
それぞれが特定のトリガーに応答する 1 つ以上の個別の関数を含むアプリです。
プロジェクト内のすべての関数は同じ構成を共有し、
ユニットとして Azure にデプロイされます。
Azure Functions の「コード プロジェクト」とは?
これは、1つのアプリケーション単位のフォルダ構成のことです。
このプロジェクトの中には、 複数の「関数(Function)」 を含めることができます。
「関数(Function)」とは?
Azure Functions では、 イベント駆動型の小さな処理単位 を「関数」と呼びます。
たとえば:
- HTTPリクエストを受け取って処理する関数
- 一定時間ごとに実行されるタイマー関数
- Blobストレージにファイルがアップロードされたときに動く関数
などがあります。
「プロジェクト内のすべての関数は同じ構成を共有」とは?
これは、以下のような 共通設定ファイル(例:host.json, local.settings.json) を、すべての関数が共有するという意味です。
つまり、1つのプロジェクト = 1つのFunction Appであり、その中に複数の関数を入れることができます。
「ユニットとして Azure にデプロイされます」とは?
これは、プロジェクト全体(Function App)をまとめてAzureにデプロイするという意味です。
関数ごとに個別にデプロイするのではなく、プロジェクト単位で一括デプロイされます。
フォルダのイメージは以下になります。
MyFunctionApp/
├── .venv/ ← Python仮想環境
├── HttpExample/ ← HTTPトリガー関数
│ ├── __init__.py
│ └── function.json
├── TimerExample/ ← タイマートリガー関数
│ ├── __init__.py
│ └── function.json
├── BlobTriggerExample/ ← Blobトリガー関数
│ ├── __init__.py
│ └── function.json
├── host.json ← 全関数共通の設定
├── local.settings.json ← ローカル環境用の設定
├── requirements.txt ← Python依存ライブラリ
└── .funcignore ← デプロイ時に除外するファイル
上記は初心者の私にとっては、用途ごとに分かれている構成が非常にわかりやすく感じました。上記はPython のプログラミング モデルの v1 となります。
Azure Functions Core Tools v4 では、Python プログラミングモデル v2 が導入されており、func init 実行時に function_app.py が生成されるのが標準仕様になっています。
詳細は「Azure Functions の Python 開発者向けガイド」に公開されています。
今回は1つの関数を含むコード プロジェクトを作成します。
- func init コマンドを実行して、現在のフォルダーに関数アプリ プロジェクトを作成します。
# プロジェクトの作成
func init --worker-runtime python
# 出力結果
Writing requirements.txt
Writing .funcignore
Writing function_app.py
Writing .gitignore
Writing host.json
Writing local.settings.json
Writing C:\Users\user\Desktop\Quickstart_Function_command_line\.vscode\extensions.json
function_app.py: すべての関数とそれに関連するトリガーとバインドの標準の配置場所です。
- func new コマンドを使用して、プロジェクトに関数を追加します。
func new --name HttpExample --template "HTTP trigger" --authlevel "anonymous"
# 出力結果
Appending to C:\Users\user\Desktop\Quickstart_Function_command_line\function_app.py
The function "HttpExample" was created successfully from the "HTTP trigger" template.
関数をローカルで実行する
- プロジェクト フォルダーのルートにあるローカル Azure Functions ランタイム ホストを開始します。
func start
# 出力結果
Found Python version 3.13.7 (py).
Azure Functions Core Tools
Core Tools Version: 4.2.2+78afd8b84c8e31f0ddac570ba9e8128eefbd3d4a (64-bit)
Function Runtime Version: 4.1041.200.25360
[2025-09-07T08:40:49.020Z] Worker process started and initialized.
Functions:
HttpExample: http://localhost:7071/api/HttpExample
For detailed output, run func with --verbose flag.
HttpExample関数の URL 出力結果をブラウザにコピーし、関数の URL を参照すると、"hello world" というメッセージが表示された成功応答が表示されます。
プロンプト上に Succeeded が表示されると成功です。
[2025-09-07T08:41:29.006Z] Executing 'Functions.HttpExample' (Reason='This function was programmatically called via the host APIs.', Id=c302c3d1-8976-4f38-be70-d28c4fbe267e)
[2025-09-07T08:41:29.155Z] Executed 'Functions.HttpExample' (Succeeded, Id=c302c3d1-8976-4f38-be70-d28c4fbe267e, Duration=187ms)
関数用の関連 Azure リソースを作成する
関数コードを Azure にデプロイする前に次のリソースを作成します。
- リソース グループ:関連リソースの論理コンテナーです。
- 既定のストレージ アカウント:関数の状態とその他の情報を維持するために、関数ホストによって使用されます。
- ユーザーが割り当てたマネージドID:Functions ホストが既定のストレージ アカウントに接続するためのリソースになります。
- 関数アプリ。関数コードを実行するための環境となります。 関数アプリは、ローカルの関数プロジェクトと対応関係にあります。
1 . Azure にサインインします。
az login
2 . az extension add コマンドを使用して Application Insights 拡張機能をインストールします
az extension add --name application-insights
3 . リソースグループを作成します。
az group create --name "AzureFunctionsQuickstart-rg" --location "japaneast"
4 . az storage account create コマンドを使用して、リソース グループとリージョンに汎用ストレージ アカウントを作成します。
# az storage account create --name <STORAGE_NAME> --location "<REGION>" --resource-group "AzureFunctionsQuickstart-rg" --sku "Standard_LRS" --allow-blob-public-access false --allow-shared-key-access false
az storage account create --name st20250907func --location "japaneast" --resource-group "AzureFunctionsQuickstart-rg" --sku "Standard_LRS" --allow-blob-public-access false --allow-shared-key-access false
ストレージ アカウントの名前は注意する必要があります。
- 一意の名前である必要があります。
- 名前は 3 文字から 24 文字とし、小文字のみを使用する必要があります。
5 . ユーザー割り当てマネージド ID を作成し、 jqを使用してオブジェクトの返された JSON プロパティを解析し、既定のストレージ アカウントで Storage Blob Data Owner アクセス許可を付与します。
# マネージドIDの作成
output=$(az identity create --name "func-host-storage-user" --resource-group "AzureFunctionsQuickstart-rg" --location japaneast --query "{userId:id, principalId: principalId, clientId: clientId}" -o json)
userId=$(echo $output | jq -r '.userId')
principalId=$(echo $output | jq -r '.principalId')
clientId=$(echo $output | jq -r '.clientId')
# ストレージアカウントの作成
# storageId=$(az storage account show --resource-group "AzureFunctionsQuickstart-rg" --name <STORAGE_NAME> --query 'id' -o tsv)
storageId=$(az storage account show --resource-group "AzureFunctionsQuickstart-rg" --name st20250907func --query 'id' -o tsv)
# ロールの割り当て
az role assignment create --assignee-object-id $principalId --assignee-principal-type ServicePrincipal --role "Storage Blob Data Owner" --scope $storageId
私の環境の都合でロールの割り当てが失敗するのでポータルから設定しました。
6 . az functionapp create コマンドを使用して、Azure で関数アプリを作成します。
# az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name <APP_NAME> --flexconsumption-location <REGION> --runtime python --runtime-version <LANGUAGE_VERSION> --storage-account <STORAGE_NAME> --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name func20250907 --flexconsumption-location japaneast --runtime python --runtime-version "3.12" --storage-account st20250907func --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
Python 関数アプリでサポートされている言語バージョンは3.13はプレビューでしたので3.12を利用します。
各リソースが作成されました。
Azure Functionにマネージド IDが設定されました。
7 . Application Insights インスタンスの Monitoring Metrics Publisher ロールにユーザー割り当てマネージド ID を追加します。
appInsights=$(az monitor app-insights component show --resource-group "AzureFunctionsQuickstart-rg" --app func20250907 --query "id" --output tsv)
principalId=$(az identity show --name "func-host-storage-user" --resource-group "AzureFunctionsQuickstart-rg" --query principalId -o tsv)
az role assignment create --role "Monitoring Metrics Publisher" --assignee $principalId --scope $appInsights
※ストレージ Blob データ所有者同様にポータルから設定しました。
アプリケーション設定を更新する
これから行う一連のコマンドは、 Azure Functions アプリがユーザー割り当てマネージド IDを使って安全にストレージと Application Insights に接続できるようにするための設定 です。
- Azure Functions は、System-Assigned Managed Identity を持っており、Entra ID によって認証されます。
- このマネージド ID を使って、以下のリソースにアクセスします:
- Application Insights:ログやメトリクスの送信に使用。
- Storage Account:Blob や Queue などのストレージ操作に使用。
補足:
- Microsoft Entra ID は、Azure のリソースに対するアクセス制御や認証を担う IDaaS(Identity as a Service) 型の認証プラットフォームです。
- Azure Functions の マネージド ID(System-Assigned または User-Assigned)は、Entra ID によって認証され、他の Azure リソース(例:Storage Account や Application Insights)にアクセスするためのトークンを取得します。
1 . このスクリプトを使用して、ユーザー割り当てマネージド ID のクライアント ID を取得し、それを使用してストレージと Application Insights の両方へのマネージド ID 接続を定義します。
# clientId を取得する
clientId=$(az identity show --name func-host-storage-user --resource-group AzureFunctionsQuickstart-rg --query 'clientId' -o tsv)
何をしている?
事前に作成した ユーザー割り当てマネージド ID(func-host-storage-user)の clientId を取得して、変数 clientId に代入しています。
なぜ必要?
この clientId を使って、Azure Functions アプリがストレージや Application Insights にアクセスできるようにするためです。
# アプリ設定を追加する
az functionapp config appsettings set --name func20250907 --resource-group "AzureFunctionsQuickstart-rg" --settings AzureWebJobsStorage__accountName=st20250907func AzureWebJobsStorage__credential=managedidentity AzureWebJobsStorage__clientId=$clientId APPLICATIONINSIGHTS_AUTHENTICATION_STRING="ClientId=$clientId;Authorization=AAD"
何をしている?
Azure Functions アプリに、マネージド ID を使ってストレージと Application Insights に接続するための設定を追加しています。
なぜ必要?
通常は「接続文字列」を使ってストレージに接続しますが、マネージド ID を使うことでセキュリティが向上します。
Application Insights も同様に、AAD 認証を使うことで 接続文字列不要で安全にログ送信できます。
2 . az functionapp config appsettings delete コマンドを実行して、共有秘密鍵を含む既存のAzureWebJobsStorage接続文字列設定を削除します。
# 古い接続文字列を削除する
az functionapp config appsettings delete --name func20250907 --resource-group "AzureFunctionsQuickstart-rg" --setting-names AzureWebJobsStorage
何をしている?
以前設定されていた AzureWebJobsStorage の接続文字列を削除しています。
なぜ必要?
接続文字列とマネージド ID の設定が 両方あると競合する可能性があるため、古い設定を削除しておく必要があります。
この時点で、Functions ホストは共有シークレットではなく、マネージド ID を使用して安全にストレージ アカウントへ接続できるようになります。
Functions の環境変数は以下の通りです。
Azure Functions のサーバーレス Flex Consumption ホスティング プランにデプロイ
Azure に関数プロジェクトをデプロイする
Azure 内に関数アプリを作成することに成功したら、func azure functionapp publish コマンドを使用してローカル関数プロジェクトをデプロイする準備が整います。
1 . ルート プロジェクト フォルダーで、次の func azure functionapp publish コマンドを実行します。
func azure functionapp publish func20250907
正常にアップロードされたら以下ログが出力されます。
[2025-09-07T11:32:13.380Z] The deployment was successful!
Functions in func20250907:
HttpExample - [httpTrigger]
Invoke url: https://func20250907.azurewebsites.net/api/httpexample
ブラウザにURLを貼り付けます。
この関数をローカルで実行したときと同様の出力がブラウザに表示されました。
以上で検証は完了です。
リソースをクリーンアップする
リソース グループとそこに含まれるすべてのリソースを削除します。
az group delete --name AzureFunctionsQuickstart-rg
補足
Application Insights を確認するとアクセス履歴があります。
アップロードした関数はブラウザで確認できます。
import azure.functions as func
import datetime
import json
import logging
app = func.FunctionApp()
@app.route(route="HttpExample", auth_level=func.AuthLevel.ANONYMOUS)
def HttpExample(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
)
HttpExample が確認できます。
終わりに
今回、Azure CLIとPythonを使ってAzure Functionsのサーバーレス開発を一通り体験してみました。
ローカル環境での関数作成から、Flex Consumptionプランへのデプロイ、マネージドIDによる安全な接続設定まで、公式ドキュメントをベースにしながらも自分の手で構築できたことで、Azureの理解が一段と深まりました。
特に、マネージドIDを活用したセキュアな構成や、Application Insightsによる監視の仕組みは、実運用を意識した設計に近づけたと感じています。
最初は手順が多くて戸惑いましたが、1つ1つのステップを丁寧に追うことで、Azureのリソース間の関係性や役割が自然と見えてきました。
今後は、BlobトリガーやTimerトリガーなど、より実用的な関数の作成にも挑戦してみたいと思います。
この記事が、これからAzure Functionsを始める方の参考になれば嬉しいです!









