Web Apps Containers: How to mount Azure Storage using ARM template
arm web-apps docker

Using ARM template to mount Azure File Storage to a Docker container running on Azure Web Apps.
February 15, 2021

Azure App Service on Linux and Web Apps for containers have the option to mount Azure Storage container to a specific path as a network share. This feature is currently (02/2021) in preview and Microsoft Docs contain only instructions for Azure CLI, but not for Resource Manager templates.

This article is about that - using ARM template to mount Azure File Storage to a Docker container running on Azure Web Apps.

tl;dr

Use this in Web App config:

"properties": {
    "linuxFxVersion": "[concat('DOCKER|', variables('dockerImageFullName'))]",
    "azureStorageAccounts": {
        "myshareid": {
            "type": "AzureFiles",
            "accountName": "[parameters('storageAccountName')]",
            "shareName": "[parameters('fileShareName')]",
            "mountPath": "/mnt/myshare",
            "accessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-04-01').keys[0].value]"
        }
    }
}

How to

Keep in mind that this feature is in preview and is not supported for production scenarios. That said, it technically works fine.

Current limitations:

  • Only Azure Files containers for Read/Write and Azure Blob containers for Read.
  • Maximum of five mount points per app.
  • No access from App Service FTP endpoint.

Let's start by preparing the Storage Account and File share. This part expects that the following parameters were defined:

"resources": [
[...]
    {
        "type": "Microsoft.Storage/storageAccounts",
        "name": "[parameters('storageAccountName')]",
        "apiVersion": "2019-06-01",
        "location": "[resourceGroup().location]",
        "sku": {
            "name": "Standard_LRS"
        },
        "kind": "StorageV2"
    },
    {
        "type": "Microsoft.Storage/storageAccounts/fileServices/shares",
        "apiVersion": "2019-06-01",
        "name": "[concat(parameters('storageAccountName'), '/default/', parameters('fileShareName'))]",
        "dependsOn": [
            "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
        ]
    },
[...]

Then obviously and App Service Plan. The important part here is reserved = true, because that's what defines linux/container plans. Expected parameters:

{
    "apiVersion": "2020-06-01",
    "name": "[variables('appServicePlanName')]",
    "type": "Microsoft.Web/serverfarms",
    "location": "[resourceGroup().location]",
    "sku": {
        "name": "[parameters('webAppSku')]"
    },
    "properties": {
        "reserved": true
    }
},

Next, we need the Web App. This definition is incomplete, but starts like this:

{
    "type": "Microsoft.Web/sites",
    "apiVersion": "2018-11-01",
    "name": "[parameters('webAppName')]",
    "location": "[resourceGroup().location]",
    "kind": "app,linux,container",
    "properties": {
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
    },
[...]

(Full reference. Samples.)

Finally, the goal is to make the file share available to the container at /mnt/myshare. In order to do that, we have to specify azureStorageAccounts in Web App's properties. Access is granted by using accessKey from the Storage Account created earler.

Here is this part defined as a separate resource of type Microsoft.Web/sites/config. Expected parameters:

{
    "type": "Microsoft.Web/sites/config",
    "apiVersion": "2018-11-01",
    "name": "[concat(parameters('webAppName'), '/web')]",
    "location": "[resourceGroup().location]",
    "dependsOn": [
        "[resourceId('Microsoft.Web/sites', parameters('webAppName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), 'default', parameters('fileShareName'))]"
    ],
    "properties": {
        "linuxFxVersion": "[concat('DOCKER|', variables('dockerImageFullName'))]",
        "azureStorageAccounts": {
            "myshareid": {
                "type": "AzureFiles",
                "accountName": "[parameters('storageAccountName')]",
                "shareName": "[parameters('fileShareName')]",
                "mountPath": "/mnt/myshare",
                "accessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-04-01').keys[0].value]"
            }
        }
    }
},

Done. To verify that the mount was configured successfuly, check Azure Portal or use Azure CLI:

az webapp config storage-account list -g <resource-group> -n <app-name>

Found something inaccurate or plain wrong? Was this content helpful to you? Let me know!

šŸ“§ codez@deedx.cz