02 - First Deploy (Flex Consumption)¶
Deploy the app to Azure Functions Flex Consumption (FC1) using long-form CLI commands only.
Prerequisites¶
| Tool | Version | Purpose |
|---|---|---|
| Python | 3.11+ | Local runtime |
| Azure Functions Core Tools | v4 | Local host and publishing |
| Azure CLI | 2.61+ | Azure resource provisioning and management |
| Azure subscription | Active | Target for deployment |
Flex Consumption plan basics
Flex Consumption (FC1) supports VNet integration, identity-based storage, per-function scaling, and remote build workflows.
What You'll Build¶
You will provision a Linux Function App on the Flex Consumption plan, publish your Python v2 app, and validate trigger discovery.
Network Scenario Choices
This tutorial deploys with public networking. FC1 supports VNet integration and private endpoints:
| Scenario | Description | Guide |
|---|---|---|
| Public Only | No VNet (this tutorial) | Current page |
| Private Egress | VNet + Storage PE | Private Egress |
| Private Ingress | + Site Private Endpoint | Private Ingress |
| Fixed Outbound IP | + NAT Gateway | Fixed Outbound |
Looking for a private egress deployment (VNet + Storage PE)? See 02 - First Deploy (Private Egress).
Infrastructure Context
Plan: Flex Consumption (FC1) | Network: VNet integration supported | Storage auth: SystemAssigned MI
Flex Consumption uses blob-based deployment storage with managed identity authentication, unlike Consumption which uses Azure Files with connection strings.
flowchart TD
INET[Internet] -->|HTTPS| FA[Function App\nFlex Consumption FC1\nLinux Python 3.11]
FA -->|"SystemAssigned MI"| ST[Storage Account\nBlob deployment]
FA --> AI[Application Insights]
subgraph STORAGE[Storage Services]
ST --- DEPLOY["Blob Container\napp-package"]
end
style FA fill:#0078d4,color:#fff
style STORAGE fill:#FFF3E0 flowchart TD
A[Set variables + login] --> B[Create RG + storage]
B --> C[Create deployment container]
C --> D[Create function app]
D --> E[Assign Storage Blob Data Contributor]
E --> F[Wait for role propagation]
F --> G[Set placeholder settings]
G --> H["func azure functionapp publish"]
H --> I[Validate endpoints] Steps¶
Step 1 - Set variables and sign in¶
export RG="rg-func-python-flex-demo"
export APP_NAME="func-pyflex-$(date +%m%d%H%M)"
export STORAGE_NAME="stpyflex$(date +%m%d)"
export LOCATION="koreacentral"
az login
az account set --subscription "<subscription-id>"
| Command/Parameter | Purpose |
|---|---|
export RG="rg-func-python-flex-demo" | Sets the resource group name for the deployment. |
export APP_NAME="..." | Defines a globally unique name for the Function App using a timestamp. |
export STORAGE_NAME="..." | Sets a unique name for the storage account. |
export LOCATION="koreacentral" | Chooses the Azure region for the deployment. |
az login | Authenticates your CLI session with Azure. |
az account set --subscription | Targets the specific Azure subscription for resource creation. |
Step 2 - Create resource group and storage account¶
az group create --name "$RG" --location "$LOCATION"
az storage account create \
--name "$STORAGE_NAME" \
--resource-group "$RG" \
--location "$LOCATION" \
--sku Standard_LRS \
--kind StorageV2
| Command/Parameter | Purpose |
|---|---|
az group create | Provisions a new Azure resource group container. |
--name "$RG" | Specifies the resource group name. |
--location "$LOCATION" | Sets the geographical region for the group. |
az storage account create | Provisions a new Azure Storage account. |
--sku Standard_LRS | Selects locally-redundant storage for cost-efficiency. |
--kind StorageV2 | Uses the general-purpose v2 storage account type. |
Step 3 - Create the deployment container¶
az storage container create \
--name app-package \
--account-name "$STORAGE_NAME" \
--auth-mode login
| Command/Parameter | Purpose |
|---|---|
az storage container create | Creates a new blob container within the storage account. |
--name app-package | Names the container that will store deployment zip files. |
--auth-mode login | Uses your Entra ID credentials instead of a connection string. |
Container must exist before function app creation
Flex Consumption requires a pre-existing blob container for deployment packages. If the container does not exist, az functionapp create fails with a ContainerNotFound error.
Step 4 - Create function app¶
az functionapp create \
--name "$APP_NAME" \
--resource-group "$RG" \
--storage-account "$STORAGE_NAME" \
--runtime python \
--runtime-version 3.11 \
--functions-version 4 \
--flexconsumption-location "$LOCATION" \
--deployment-storage-name "$STORAGE_NAME" \
--deployment-storage-container-name app-package \
--deployment-storage-auth-type SystemAssignedIdentity
| Command/Parameter | Purpose |
|---|---|
az functionapp create | Provisions the core Function App resource. |
--runtime python | Selects the Python execution environment. |
--runtime-version 3.11 | Pins the Python version to 3.11. |
--functions-version 4 | Uses version 4 of the Azure Functions runtime host. |
--flexconsumption-location | Specifies the region for the Flex Consumption plan. |
--deployment-storage-name | Links the app to the deployment storage account. |
--deployment-storage-container-name | Targets the specific container for package storage. |
--deployment-storage-auth-type | Uses Managed Identity for secure access to deployment blobs. |
Flex Consumption vs Consumption CLI differences
Flex Consumption uses --flexconsumption-location instead of --consumption-plan-location. It also requires --deployment-storage-name, --deployment-storage-container-name, and --deployment-storage-auth-type parameters.
Step 5 - Assign Storage Blob Data Contributor role¶
The managed identity needs explicit permission to upload deployment packages to blob storage:
PRINCIPAL_ID=$(az functionapp identity show \
--name "$APP_NAME" \
--resource-group "$RG" \
--query principalId \
--output tsv)
STORAGE_ID=$(az storage account show \
--name "$STORAGE_NAME" \
--resource-group "$RG" \
--query id \
--output tsv)
az role assignment create \
--assignee "$PRINCIPAL_ID" \
--role "Storage Blob Data Contributor" \
--scope "$STORAGE_ID"
# Wait for role assignment propagation (30-60 seconds)
echo "Waiting for role assignment propagation..."
sleep 60
| Command/Parameter | Purpose |
|---|---|
az functionapp identity show | Retrieves the principal ID of the function app's managed identity. |
az storage account show | Retrieves the Azure resource ID of the deployment storage account. |
az role assignment create | Grants the function app permission to upload deployment packages to blob storage. |
sleep 60 | Waits for Azure RBAC propagation before attempting the first publish. |
Wait before publishing
If you run func azure functionapp publish immediately after the role assignment, the deployment can fail with a blob storage 403 error while RBAC changes are still propagating. Wait 30-60 seconds first.
Step 6 - Set placeholder trigger settings¶
STORAGE_CONN=$(az storage account show-connection-string \
--name "$STORAGE_NAME" \
--resource-group "$RG" \
--output tsv)
az functionapp config appsettings set \
--name "$APP_NAME" \
--resource-group "$RG" \
--settings \
"QueueStorage=$STORAGE_CONN" \
"TIMER_LAB_SCHEDULE=0 */5 * * * *"
| Command/Parameter | Purpose |
|---|---|
az storage account show-connection-string | Retrieves the full connection string for the storage account. |
az functionapp config appsettings set | Updates the application settings for the Function App. |
--settings | Defines the key-value pairs required by the function triggers. |
Placeholder settings prevent host errors
The Python v2 reference app includes triggers for Queue and Timer. If these connection settings are missing, the Functions host enters an Error state and cannot index any functions.
Step 7 - Publish app¶
| Command/Parameter | Purpose |
|---|---|
cd apps/python | Moves the terminal into the source code directory. |
func azure functionapp publish | Bundles, uploads, and triggers a remote build for the app. |
Upload size
Python function apps are typically smaller than Node.js (~6.5 MB vs ~49 MB) as dependencies are installed remotely.
Step 8 - Validate deployment¶
# List deployed functions
az functionapp function list \
--name "$APP_NAME" \
--resource-group "$RG" \
--output table
# Test the health endpoint
curl --request GET "https://$APP_NAME.azurewebsites.net/api/health"
# Test the hello endpoint
curl --request GET "https://$APP_NAME.azurewebsites.net/api/hello/FlexTest"
| Command/Parameter | Purpose |
|---|---|
az functionapp function list | Queries ARM to retrieve the list of indexed functions. |
--output table | Formats the function list as a readable text table. |
curl --request GET | Sends an HTTP GET request to verify the live endpoints. |
Step 9 - Review Flex Consumption-specific notes¶
- Flex Consumption routes all traffic through the integrated VNet by default once configured.
- Flex Consumption does not support custom container hosting for Function Apps.
- Use long-form CLI flags for maintainable runbooks.
Verification¶
Function list output (showing key fields):
[
{
"name": "helloHttp",
"type": "Microsoft.Web/sites/functions",
"invokeUrlTemplate": "https://<app-name>.azurewebsites.net/api/hello/{name?}",
"language": "python",
"isDisabled": false
}
]
Health endpoint response:
Hello endpoint response:
Next Steps¶
- Add VNet integration: See Private Egress for VNet + Storage PE
- Private egress deployment: See 02 - First Deploy (Private Egress) for VNet + Storage PE tutorial
Next: 03 - Configuration
See Also¶
- Tutorial Overview & Plan Chooser
- Python Language Guide
- Platform: Hosting Plans
- Operations: Deployment
- Recipes Index