azure-functions について
Azure Functions でサーバーレスアプリを構築する開発者向けの開発・デプロイガイドです。Python と Node.js の例、トリガーやバインディングの設定、本番環境へのデプロイ手順を扱います。
主な機能
- 01Function App の作成と設定
- 02HTTP、Blob、タイマーなどのトリガー例
- 03Python と Node.js のコード例
- 04ローカル開発とデプロイの手順
- 05デプロイスロット、セキュリティ設定、トラブルシューティング
活用シーン
- 01API と Webhook の構築
- 02Blob や Service Bus のイベント処理
- 03定期タスクやバックグラウンド処理の実行
- 04Azure Functions アプリのデプロイ
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill azure-functionsインストール後、Claude Code で/azure-functionsを入力して読み込まれたか確認します。
詳細
Azure Functions
Azure Functions を使用して、サーバーレスアプリケーションを構築およびデプロイします。関数アプリの作成、トリガーとバインディングの構成、デプロイ戦略、Python と Node.js の実際のコード例、本番環境でのベストプラクティスを網羅しています。
使用する場面
- 自動的にゼロまでスケールするイベント駆動型のコンピューティングが必要な場合。
- API、Webhook、バックグラウンド処理パイプラインを構築する場合。
- サーバーを管理せずに、実行ごとの課金を利用したい場合。
- Azure サービスのイベント(Blob Storage、Service Bus、Cosmos DB の変更)に応答する必要がある場合。
- 軽量なマイクロサービスやスケジュールされたタスクを実装する場合。
前提条件
# Install Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Install Azure Functions Core Tools v4
npm install -g azure-functions-core-tools@4
# Verify installation
func --version
# Login
az login
az account set --subscription "my-subscription-id"
# Create supporting resources
az group create --name functions-rg --location eastus
az storage account create \
--name myfuncstorageacct \
--resource-group functions-rg \
--location eastus \
--sku Standard_LRS
関数アプリの作成
従量課金プラン(実行ごとの課金)
# Python function app on Consumption plan
az functionapp create \
--resource-group functions-rg \
--consumption-plan-location eastus \
--runtime python \
--runtime-version 3.11 \
--functions-version 4 \
--name myapp-func \
--storage-account myfuncstorageacct \
--os-type Linux
# Node.js function app
az functionapp create \
--resource-group functions-rg \
--consumption-plan-location eastus \
--runtime node \
--runtime-version 20 \
--functions-version 4 \
--name myapp-node-func \
--storage-account myfuncstorageacct \
--os-type Linux
Premium プラン(VNet 統合、コールドスタートなし)
# Create Premium plan
az functionapp plan create \
--resource-group functions-rg \
--name myapp-premium-plan \
--location eastus \
--sku EP1 \
--is-linux true
# Create function app on Premium plan
az functionapp create \
--resource-group functions-rg \
--plan myapp-premium-plan \
--runtime python \
--runtime-version 3.11 \
--functions-version 4 \
--name myapp-premium-func \
--storage-account myfuncstorageacct
トリガーとバインディングの例
HTTP トリガー -- Python
# function_app.py (v2 programming model)
import azure.functions as func
import json
import logging
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)
@app.route(route="users/{userId}", methods=["GET"])
def get_user(req: func.HttpRequest) -> func.HttpResponse:
user_id = req.route_params.get("userId")
logging.info(f"Fetching user: {user_id}")
if not user_id:
return func.HttpResponse(
json.dumps({"error": "userId is required"}),
status_code=400,
mimetype="application/json"
)
user = {"id": user_id, "name": "Jane Doe", "email": "[email protected]"}
return func.HttpResponse(
json.dumps(user),
status_code=200,
mimetype="application/json"
)
@app.route(route="users", methods=["POST"])
def create_user(req: func.HttpRequest) -> func.HttpResponse:
try:
body = req.get_json()
except ValueError:
return func.HttpResponse(
json.dumps({"error": "Invalid JSON"}),
status_code=400,
mimetype="application/json"
)
logging.info(f"Creating user: {body.get('name')}")
return func.HttpResponse(
json.dumps({"id": "new-id", **body}),
status_code=201,
mimetype="application/json"
)
HTTP トリガー -- Node.js
// src/functions/httpTrigger.js (v4 programming model)
const { app } = require("@azure/functions");
app.http("getUser", {
methods: ["GET"],
authLevel: "function",
route: "users/{userId}",
handler: async (request, context) => {
const userId = request.params.userId;
context.log(`Fetching user: ${userId}`);
if (!userId) {
return { status: 400, jsonBody: { error: "userId is required" } };
}
const user = { id: userId, name: "Jane Doe", email: "[email protected]" };
return { status: 200, jsonBody: user };
},
});
app.http("createUser", {
methods: ["POST"],
authLevel: "function",
route: "users",
handler: async (request, context) => {
const body = await request.json();
context.log(`Creating user: ${body.name}`);
return { status: 201, jsonBody: { id: "new-id", ...body } };
},
});
Blob トリガー -- Python
@app.blob_trigger(arg_name="blob", path="uploads/{name}",
connection="AzureWebJobsStorage")
def process_upload(blob: func.InputStream):
logging.info(f"Processing blob: {blob.name}, Size: {blob.length} bytes")
content = blob.read()
# Process file content here
Timer トリガー -- Python
@app.timer_trigger(schedule="0 */5 * * * *", arg_name="timer",
run_on_startup=False)
def cleanup_job(timer: func.TimerRequest):
if timer.past_due:
logging.warning("Timer is past due")
logging.info("Running scheduled cleanup")
# Cleanup logic here
Service Bus トリガー -- Python
@app.service_bus_queue_trigger(arg_name="msg", queue_name="orders",
connection="ServiceBusConnection")
@app.cosmos_db_output(arg_name="doc", database_name="mydb",
container_name="processed-orders",
connection="CosmosDBConnection")
def process_order(msg: func.ServiceBusMessage, doc: func.Out[func.Document]):
order = json.loads(msg.get_body().decode("utf-8"))
logging.info(f"Processing order: {order['id']}")
processed = {
"id": order["id"],
"status": "processed",
"items": order["items"],
"total": sum(item["price"] for item in order["items"])
}
doc.set(func.Document.from_dict(processed))
Cosmos DB Change Feed トリガー -- Python
@app.cosmos_db_trigger_v3(arg_name="documents", database_name="mydb",
container_name="orders",
connection="CosmosDBConnection",
lease_container_name="leases",
create_lease_container_if_not_exists=True)
def on_order_change(documents: func.DocumentList):
for doc in documents:
logging.info(f"Document changed: {doc['id']}")
ローカル開発
# Initialize a new Python function project
func init MyFunctionProject --python
cd MyFunctionProject
# Create a new function from template
func new --name HttpExample --template "HTTP trigger" --authlevel function
# Run locally
func start
# Run locally with specific port
func start --port 7072
# Test locally
curl http://localhost:7071/api/HttpExample?name=World
デプロイ
# Deploy using Core Tools
func azure functionapp publish myapp-func
# Deploy with build step for Python
func azure functionapp publish myapp-func --build remote
# Deploy using ZIP package
zip -r function.zip . -x ".git/*" ".venv/*" "__pycache__/*"
az functionapp deployment source config-zip \
--resource-group functions-rg \
--name myapp-func \
--src function.zip
# Deploy via CI/CD with GitHub Actions
az functionapp deployment github-actions add \
--resource-group functions-rg \
--name myapp-func \
--repo "myorg/myrepo" \
--branch main \
--runtime python \
--login-with-github
デプロイスロット
# Create a staging slot
az functionapp deployment slot create \
--resource-group functions-rg \
--name myapp-func \
--slot staging
# Deploy to staging slot
func azure functionapp publish myapp-func --slot staging
# Test staging slot
curl https://myapp-func-staging.azurewebsites.net/api/health
# Swap staging to production
az functionapp deployment slot swap \
--resource-group functions-rg \
--name myapp-func \
--slot staging \
--target-slot production
# Roll back by swapping again
az functionapp deployment slot swap \
--resource-group functions-rg \
--name myapp-func \
--slot staging \
--target-slot production
アプリケーション設定とセキュリティ
# Set application settings
az functionapp config appsettings set \
--resource-group functions-rg \
--name myapp-func \
--settings \
ServiceBusConnection="Endpoint=sb://..." \
CosmosDBConnection="AccountEndpoint=https://..." \
CUSTOM_SETTING="my-value"
# Set settings as slot-specific
az functionapp config appsettings set \
--resource-group functions-rg \
--name myapp-func \
--slot-settings \
ENVIRONMENT="staging"
# Enable managed identity
az functionapp identity assign \
--resource-group functions-rg \
--name myapp-func
# Configure CORS
az functionapp cors add \
--resource-group functions-rg \
--name myapp-func \
--allowed-origins "https://myapp.example.com"
# Set minimum TLS version
az functionapp config set \
--resource-group functions-rg \
--name myapp-func \
--min-tls-version 1.2
# Enable Application Insights
az functionapp config appsettings set \
--resource-group functions-rg \
--name myapp-func \
--settings APPINSIGHTS_INSTRUMENTATIONKEY="your-key"
Terraform の構成
resource "azurerm_service_plan" "functions" {
name = "myapp-func-plan"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
os_type = "Linux"
sku_name = "Y1" # Consumption plan
}
resource "azurerm_linux_function_app" "main" {
name = "myapp-func"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
service_plan_id = azurerm_service_plan.functions.id
storage_account_name = azurerm_storage_account.func.name
storage_account_access_key = azurerm_storage_account.func.primary_access_key
identity {
type = "SystemAssigned"
}
site_config {
application_stack {
python_version = "3.11"
}
cors {
allowed_origins = ["https://myapp.example.com"]
}
}
app_settings = {
FUNCTIONS_WORKER_RUNTIME = "python"
WEBSITE_RUN_FROM_PACKAGE = "1"
APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.main.instrumentation_key
}
tags = var.tags
}
トラブルシューティング
| 症状 | 原因 | 対処法 |
|---|---|---|
| コールドスタートの遅延が 10 秒を超える | 従量課金プランのコールドスタート | Premium プラン(EP1 以上)を使用するか、WEBSITE_RUN_FROM_PACKAGE=1 を有効にします |
| 関数がトリガーされない | 接続文字列の設定ミス | az functionapp config appsettings list を実行して、バインディング値が正しいことを確認します |
Python で ModuleNotFoundError が発生する | デプロイ時に依存関係がインストールされていない | --build remote フラグを使用するか、パッケージに requirements.txt を含めます |
| HTTP 401 Unauthorized | 認証レベルの不一致、または関数キーがない | コード内の認証レベルが想定と一致していることを確認し、x-functions-key ヘッダーを渡します |
| Blob トリガーが起動しない | ストレージアカウントの接続先が誤っている | AzureWebJobsStorage が正しいアカウントを指していることを確認します |
| Timer トリガーが 2 回実行される | Premium プランで複数のインスタンスが動作している | WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT=1 を設定するか、シングルトンロックを使用します |
| デプロイスロットのスワップに失敗する | スロットの設定が構成されていない | スロット固有の設定が --slot-settings で指定されていることを確認します |
| メモリ不足エラーが発生する | ペイロードが大きい、またはメモリリークがある | データをすべて読み込まずにストリーミングし、プランのティアを引き上げます |
関連スキル
azure-networking-- プライベートリソースにアクセスする Premium プランの関数での VNet 統合。azure-sql-- 関数バインディングからのデータベース接続。terraform-azure-- 関数アプリのプロビジョニングに使用する Infrastructure as Code。arm-templates-- Bicep ベースの関数アプリのデプロイ。
コメント
Markdown 対応