Function Apps
Introduction
Section titled “Introduction”Azure Function Apps are serverless compute resources that host and execute Azure Functions in response to events. They support multiple runtime environments including Python, Node.js, and .NET, and integrate with a wide range of trigger sources such as HTTP requests, queues, and timers. Function Apps are commonly used to build event-driven microservices, scheduled background jobs, and lightweight API backends. For more information, see Introduction to Azure Functions.
LocalStack for Azure provides a local environment for building and testing applications that make use of Azure Function Apps. The supported APIs are available on our API Coverage section, which provides information on the extent of Function Apps’ integration with LocalStack.
Getting started
Section titled “Getting started”This guide walks you through creating a Function App on an App Service plan, backed by a Storage Account, deploying a Python HTTP-trigger function, invoking it, and managing its keys.
Launch LocalStack using your preferred method. For more information, see Introduction to LocalStack for Azure. Once the container is running, enable Azure CLI interception by running:
lstk az start-interceptionThis command points the az CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API.
To revert this configuration, run:
lstk az stop-interceptionThis reconfigures the az CLI to send commands to the official Azure management REST API.
Create a resource group
Section titled “Create a resource group”Create a resource group to hold all resources created in this guide:
az group create --name rg-func-demo --location westeurope{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-func-demo", "location": "westeurope", "name": "rg-func-demo", "properties": { "provisioningState": "Succeeded" }, "type": "Microsoft.Resources/resourceGroups"}Create a storage account
Section titled “Create a storage account”Function Apps require a Storage Account for internal bookkeeping.
az storage account create \ --name safuncdoc89 \ --resource-group rg-func-demo \ --location westeurope \ --sku Standard_LRS{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-func-demo/providers/Microsoft.Storage/storageAccounts/safuncdoc89", "kind": "StorageV2", "location": "westeurope", "name": "safuncdoc89", "provisioningState": "Succeeded", "resourceGroup": "rg-func-demo", "sku": { "name": "Standard_LRS", "tier": "Standard" }, "type": "Microsoft.Storage/storageAccounts", ...}Create an App Service plan
Section titled “Create an App Service plan”Create a Linux App Service plan to host the function app:
az appservice plan create \ --name asp-func-doc89 \ --resource-group rg-func-demo \ --location westeurope \ --sku B1 \ --is-linux{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-func-demo/providers/Microsoft.Web/serverfarms/asp-func-doc89", "kind": "linux", "name": "asp-func-doc89", "provisioningState": "Succeeded", "reserved": true, "sku": { "capacity": 1, "family": "B", "name": "B1", "size": "B1", "tier": "Basic" }, ...}Create a function app
Section titled “Create a function app”Create a function app on the plan, backed by the storage account:
az functionapp create \ --name ls-func-doc89 \ --resource-group rg-func-demo \ --plan asp-func-doc89 \ --runtime python \ --runtime-version 3.13 \ --functions-version 4 \ --os-type linux \ --storage-account safuncdoc89{ "defaultHostName": "ls-func-doc89.azurewebsites.azure.localhost.localstack.cloud:4566", "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-func-demo/providers/Microsoft.Web/sites/ls-func-doc89", "kind": "functionapp,linux", "name": "ls-func-doc89", "resourceGroup": "rg-func-demo", "state": "Running", "type": "Microsoft.Web/sites", ...}Configure app settings
Section titled “Configure app settings”Add environment variables as application settings on the function app:
az functionapp config appsettings set \ --name ls-func-doc89 \ --resource-group rg-func-demo \ --settings \ FUNCTIONS_WORKER_RUNTIME=python \ MY_CUSTOM_SETTING=hello-worldThe command hides the values of the settings:
[ ... { "name": "FUNCTIONS_WORKER_RUNTIME", "slotSetting": false, "value": null }, { "name": "FUNCTIONS_EXTENSION_VERSION", "slotSetting": false, "value": null }, { "name": "AzureWebJobsStorage", "slotSetting": false, "value": null }, ... { "name": "MY_CUSTOM_SETTING", "slotSetting": false, "value": null }]List application settings
Section titled “List application settings”List all application settings currently configured on the function app:
az functionapp config appsettings list \ --name ls-func-doc89 \ --resource-group rg-func-demo[ ... { "name": "FUNCTIONS_WORKER_RUNTIME", "slotSetting": false, "value": "python" }, { "name": "FUNCTIONS_EXTENSION_VERSION", "slotSetting": false, "value": "~4" }, { "name": "AzureWebJobsStorage", "slotSetting": false, "value": "DefaultEndpointsProtocol=https;..." }, ... { "name": "MY_CUSTOM_SETTING", "slotSetting": false, "value": "hello-world" }]Create the function package
Section titled “Create the function package”Create a directory for the function source and add the required files:
mkdir my_func && cd my_funcCreate function_app.py with an HTTP-triggered function:
import azure.functions as func
app = func.FunctionApp()
@app.function_name(name="HelloWorld")@app.route(route="public", methods=["GET"], auth_level=func.AuthLevel.ANONYMOUS)def public(req: func.HttpRequest) -> func.HttpResponse: name = req.params.get("name", "World") return func.HttpResponse(f"Hello, {name}!")Create host.json:
{ "version": "2.0"}Create requirements.txt:
azure-functionsPackage everything into a zip archive and return to the parent directory:
zip my_func.zip function_app.py host.json requirements.txtcd ..Deploy function code
Section titled “Deploy function code”Deploy the zip package to the function app. With --async true, the command uploads the package and then polls the deployment until it completes:
az functionapp deploy \ --resource-group rg-func-demo \ --name ls-func-doc89 \ --src-path ./my_func/my_func.zip \ --type zip \ --async true{ "active": true, "complete": true, "deployer": "OneDeploy", "message": "OneDeploy", "site_name": "ls-func-doc89", "status": 4, ...}Invoke an HTTP-trigger function
Section titled “Invoke an HTTP-trigger function”Read the function app’s host name and invoke the function:
export FUNCTION_APP_HOST=$(az functionapp show --name ls-func-doc89 --resource-group rg-func-demo --query defaultHostName --output tsv)curl "http://$FUNCTION_APP_HOST/api/public?name=LocalStack"Hello, LocalStack!On Azure, the function host can take a minute to start after a deployment, and requests answer with an empty body until it does.
List the functions
Section titled “List the functions”List the functions the app defines:
az functionapp function list \ --name ls-func-doc89 \ --resource-group rg-func-demo[ { "config": { "bindings": [ { "authLevel": "ANONYMOUS", "direction": "IN", "methods": ["GET"], "name": "req", "route": "public", "type": "httpTrigger" }, ... ], ... }, "invokeUrlTemplate": "https://ls-func-doc89.azurewebsites.azure.localhost.localstack.cloud:4566/api/public", "language": "python", "name": "ls-func-doc89/HelloWorld", "type": "Microsoft.Web/sites/functions", ... }]Manage function keys
Section titled “Manage function keys”List the app’s host keys. The master key and the default function key are created on first use:
az functionapp keys list \ --name ls-func-doc89 \ --resource-group rg-func-demo{ "functionKeys": { "default": "..." }, "masterKey": "...", "systemKeys": {}}List the keys of the HelloWorld function:
az functionapp function keys list \ --name ls-func-doc89 \ --resource-group rg-func-demo \ --function-name HelloWorld{ "default": "..."}Add a host key named ci, with a generated value:
az functionapp keys set \ --name ls-func-doc89 \ --resource-group rg-func-demo \ --key-type functionKeys \ --key-name ci{ "name": "ci", "value": null}Delete it again:
az functionapp keys delete \ --name ls-func-doc89 \ --resource-group rg-func-demo \ --key-type functionKeys \ --key-name ciInspect the function app
Section titled “Inspect the function app”Retrieve the full configuration of the function app:
az functionapp show --name ls-func-doc89 --resource-group rg-func-demo{ "defaultHostName": "ls-func-doc89.azurewebsites.azure.localhost.localstack.cloud:4566", "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-func-demo/providers/Microsoft.Web/sites/ls-func-doc89", "kind": "functionapp,linux", "name": "ls-func-doc89", "resourceGroup": "rg-func-demo", "state": "Running", "type": "Microsoft.Web/sites", ...}Delete and verify
Section titled “Delete and verify”Delete the function app:
az functionapp delete --name ls-func-doc89 --resource-group rg-func-demoThen list the function apps in the resource group to confirm that none remains. The plan and the storage account stay until you delete the resource group:
az functionapp list --resource-group rg-func-demo[]Features
Section titled “Features”- Full lifecycle: Create, read, update, and delete function apps with the Azure CLI, Bicep, Terraform, or the ARM API. A repeated PUT, such as a second
terraform applyor a Bicep redeployment, updates the app in place and keeps its deployment. - Function host in a container: Each function app runs the Azure Functions host from Azure Functions Core Tools 4.15.1 (4.13.0 on arm64 hosts) in a Docker container of its own, started on deployment.
- Python, Node.js, and .NET: Function apps on these runtimes are built and run.
- Triggers: The Functions host runs the app’s triggers itself, so HTTP, timer, Blob Storage, Queue Storage, Service Bus, and Event Hubs triggers fire against the emulator’s services, as the samples show.
- Identity-based connections: A trigger or binding can connect with the app’s managed identity (
<CONNECTION>__credential,__clientId,__fullyQualifiedNamespace,__blobServiceUri), as the managed identity and Service Bus samples do. - Deployment: Code deploys through Kudu’s zip deploy (
az functionapp deployment source config-zip), OneDeploy (az functionapp deploy), and Azure Functions Core Tools (func azure functionapp publish). - Functions and keys: Functions can be listed and shown, and triggers re-synced. Host keys, function keys, and the master key are created on first use and can be listed, set, and deleted.
- App settings and connection strings: Both reach the function host as environment variables, and changing one restarts the host, as on Azure.
- Stop, start, and restart:
az functionapp stop,start, andrestartchange the app’s state and its container. - Deployment slots: A Consumption app can have one staging slot and an Elastic Premium app two, each with its own container. A swap exchanges the content and every setting that is not sticky.
- Consumption plan auto-provisioning:
az functionapp create --consumption-plan-locationcreates the region’s Linux Consumption plan, as on Azure. - Publishing: Publishing credentials and the publish profile are available, and the profile names the emulator’s hosts.
- Log streaming:
az webapp log tailstreams the function host’s log.
Limitations
Section titled “Limitations”- Docker required for execution: Without Docker, a function app can be created and managed, but its code does not run.
- Builds use an amd64 image: The function host runs natively on arm64, but the Oryx build image that builds each deployment is published for amd64 only (microsoft/Oryx#2133 asks for arm64). On an arm64 host without amd64 emulation, the build fails at once: a Python function app then gets its
requirements.txtfrom apip installin the multi-archpythonimage, a .NET function app starts from the published output in its package, and a Node.js function app starts with only thenode_modulesits package contains. On a Mac with Apple silicon, Docker Desktop runs the build under emulation, and under QEMU the build can crash (.NET does not support QEMU, and Oryx is a .NET app). In Docker Desktop’s general settings, select the Apple Virtualization framework as the Virtual Machine Manager, because Docker VMM has no Rosetta, and then turn on “Use Rosetta for x86_64/amd64 emulation on Apple Silicon”. - Durable Functions not supported: Stateful orchestration via Durable Functions is not emulated.
- Event Grid and Cosmos DB triggers do not fire: Event Grid accepts an
AzureFunctiondestination but drops its events, and the Cosmos DB emulator has no change feed. See the Event Grid and Cosmos DB limitations. - Keys are not enforced: An HTTP trigger with the
functionoradminauthorization level answers without a key, because the host runs as Core Tools’func start, which does not authorize HTTP triggers. - Consumption and Elastic Premium plans report the Basic tier: The Azure CLI and Azure Functions Core Tools therefore publish through Kudu’s zip deploy, which the emulator serves, instead of using run-from-package. The plan’s true tier is stored and sets the slot limits.
- Run-from-package is not supported:
WEBSITE_RUN_FROM_PACKAGEhas no effect. The package is extracted and built. - Java and PowerShell function apps do not run: The app is created, and a deployment to it is refused with a 400 error that names the runtime.
- Windows function apps run on Linux: A function app on a Windows plan is created and stored, and its code runs in the Linux runtime.
- One instance per app: The emulator does not scale an app out.
- OneDeploy on Linux Consumption: The emulator accepts
az functionapp deployfor a Linux Consumption app, which Azure does not offer on that plan. - Swap options: Traffic routing, swap with preview, and auto swap are not implemented.
Configuration
Section titled “Configuration”The App Service configuration applies to function apps. The following variables are specific to them:
| Variable | Default | Type | Description |
|---|---|---|---|
LS_AZURE_FUNCTIONS_CORE_TOOLS_VERSION |
"4.15.1" ("4.13.0" on arm64) |
String | Release of Azure Functions Core Tools that function app containers run. |
LS_AZURE_FUNCTION_HOST_STARTUP_TIMEOUT |
"360" |
Integer (seconds) | Time a deployment waits for the function host to report Running. The first start downloads the Functions extension bundle; later starts reuse a cached copy. |
Samples
Section titled “Samples”The following samples demonstrate how to use Azure Function Apps with LocalStack for Azure:
- Function App and Storage (.NET)
- Function App and Front Door (Python)
- Function App and Managed Identities (Python)
- Function App and Service Bus (.NET)
- API Management and Function App (Python)
- Cold-path automation with Event Hubs Capture, Event Grid, and Functions (Python)
- Payment fraud detection pipeline with Event Hubs, Functions, and Capture (Python)
- URL Shortener with Web App, Functions, Storage, Key Vault, Service Bus, and PostgreSQL (Python)
API Coverage
Section titled “API Coverage”164 of 613 operations implemented
| Operation ▲ | Implemented ▼ |
|---|