Deploying An Azure Function App Using ARM Template

This article demonstrates the required resources to deploy the Azure function app using the Azure Resource Manager template.

An ARM template is a JSON file. Basically, this is the language of Azure behind the scenes. So when we're in the Azure portal and we click the review and create a button of any resources it's converting those text boxes and dropdowns into an ARM template and then scheduling that ARM template for deployment.

Basic Structure of ARM template

ARM templates consist of four basic elements of the JSON file.

{
   "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
   "contentVersion": "",
   "parameters": {  },
   "variables": {  },
   "resources": [  ],
   "outputs": {  }
}

All ARM templates starts with the dollar sign schema property. It has this fixed value and that is the mandatory part of an ARM template.

The content version property is for us as a content developer to keep track of. So let's say you're going to develop this ARM template and you're just going to keep it around and modify it as you go forward to improve it or add features.

The third parameter is called parameters. And this is what's going to be required as inputs into this ARM template. Every one of these parameters then has to have a corresponding value within the parameters JSON.

Variables are the fourth property of this JSON file and variables are basically computed values. So a resource group is a function of what resource groups is being deployed to. It's going to concatenate various values.

The fifth property is the resources. It’s an array where the square bracket represents one resource being deployed in Azure. Now, you might think creating a function app is a single resource, but as we've seen with the portal creation, it actually does create two to four objects like function app, storage, application insights, app service plan. It does have some dependencies.

The sixth property is the outputs. You can capture the resource Id of the component that was created and we can pass that to another template. This will be helpful for template chaining purposes.

Building ARM Template for an Azure Function App

When we deploy an azure function app, it typically consists of below dependent resources.

Resource Name Is required? Type reference
Function App Yes Microsoft.Web/sites
Storage Account Yes Microsoft.Storage/storageAccounts
Application Insights No Microsoft.Insights/components
App Service Plan No Microsoft.Web/serverfarms

The assumption here is that we already have a resource group and we will create resources in the same location where the resource group is currently present. We will follow below convention while creating resources from ARM. Image reference from Microsoft documentation.

Deploying An Azure Function App Using ARM Template

Let’s build our template step by step for each resource.

Parameters & Variables

We are taking environment name as Input and in the variable, we will concatenate environment name with resources we are creating.

"parameters": {
		"envName": {
            "defaultValue": "qa",
            "type": "String"
        }
    },
    "variables": {
		"appInsightsName" :"[concat('appi-myapp-',parameters('envName'),resourceGroup().location)]",
		"functionStorageAccountName" :"[concat('stmytodofn',parameters('envName'),resourceGroup().location)]",
		"appServicePlanName" :"[concat('plan-myapp-',parameters('envName'),resourceGroup().location)]",
		"sitesFunctionAppName" :"[concat('func-myToDoJob-',parameters('envName'),resourceGroup().location)]"
		
	},

Storage Account

		{
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2021-04-01",
            "name": "[variables('functionStorageAccountName')]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "kind": "Storage",
            "properties": {
                "supportsHttpsTrafficOnly": true
            }
        },

Application Insights

	    {
            "type": "microsoft.insights/components",
            "apiVersion": "2020-02-02",
            "name": "[variables('appInsightsName')]",
            "location": "[resourceGroup().location]",
            "kind": "web",
            "properties": {
                "Application_Type": "web",
				"ApplicationId": "[variables('appInsightsName')]"
            }
        },

App Service Plan

		{
            "type": "Microsoft.Web/serverfarms",
            "apiVersion": "2018-02-01",
            "name": "[variables('appServicePlanName')]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "S1",
                "tier": "Standard",
                "size": "S1",
                "family": "S",
                "capacity": 1
            },
            "kind": "app",
            "properties": {
                "perSiteScaling": false,
                "maximumElasticWorkerCount": 1,
                "isSpot": false,
                "reserved": false,
                "isXenon": false,
                "hyperV": false,
                "targetWorkerCount": 0,
                "targetWorkerSizeId": 0
            }
        },	

Function App

		{
            "type": "Microsoft.Web/sites",
            "apiVersion": "2018-11-01",
            "name": "[variables('sitesFunctionAppName')]",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
				"[resourceId('microsoft.insights/components/', variables('appInsightsName'))]",
				"[resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName'))]"
            ],
            "kind": "functionapp",
			"identity": {
				"type": "SystemAssigned"
			},
            "properties": {
                "enabled": true,
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
                "httpsOnly": true,
                "siteConfig": {
					"appSettings":[
						{
							"name":"APPINSIGHTS_INSTRUMENTATIONKEY",
							"value":"[reference(concat('microsoft.insights/components/', variables('appInsightsName'))).InstrumentationKey]"
						},
						{
							"name": "AzureWebJobsStorage",
							"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('functionStorageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName')),'2017-06-01').keys[0].value)]"
						},
						{
							"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
							"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('functionStorageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName')),'2017-06-01').keys[0].value)]"
						},
						{
							"name": "WEBSITE_CONTENTSHARE",
							"value": "[toLower(variables('sitesFunctionAppName'))]"
						},
						{
							"name": "FUNCTIONS_EXTENSION_VERSION",
							"value": "~3"
						},
						{
							"name": "FUNCTIONS_WORKER_RUNTIME",
							"value": "dotnet"
						},
						{
							"name": "WEBSITE_RUN_FROM_PACKAGE",
							"value": "1"
						},
						{
							"name": "WEBSITE_TIME_ZONE",
							"value": "UTC"
						}
					]
                }
            }
        }

Deploy ARM Template from the Azure Portal

In the Azure portal, click on create a resource, then search for Template deployment (deploy using custom templates), click on create.

On the Custom deployment page, click on the link Build your own template in the editor. From there, you can copy-paste or upload your ARM template. You need to save it to see the real deployment form.

Deploying An Azure Function App Using ARM Template

Then select resources group if you are created it earlier and provide environment name then click on create. Now your deployment will be started and completed.

Deploying An Azure Function App Using ARM Template

Now if you go to the resources group. You will see all the required resources are created.

Deploying An Azure Function App Using ARM Template

Excellent! We are done with your implementation and we deployed the Azure function app along with storage account, application insights, and app services plan.

Hope you find this article useful. Happy Learning!