Related
"resources": [
{
"type": "Microsoft.Sql/servers",
"location": "[parameters('location')]",
"apiVersion": "2019-06-01-preview",
"name": "[parameters('serverName')]",
"identity": { "type": "SystemAssigned" },
"condition": "[and(parameters('enableVA'), parameters('useVAManagedIdentity'))]",
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorPassword')]"
},
"resources": [
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2021-02-01-preview",
"name": "[concat(parameters('serverName'), '/', parameters('databaseName'))]",
"location": "[parameters('serverLocation')]",
"dependsOn": [ "[concat('Microsoft.Sql/servers/', parameters('serverName'))]" ],
"sku": {
"name": "GP_S_Gen5_1",
"tier": "GeneralPurpose"
},
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"maxSizeBytes": "1073741824"
}
}
]
}
I've tried to use the nested resource for my DB, and I get the error that is described below. Deployment performed in powershell.
Don’t concat the server name in the database name property, just use the db name. The server name is implied by the nested definition.
This is a very common template, one which MS has extensive examples of. Here is a copy from the most basic docs example:
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2020-02-02-preview",
"name": "[parameters('serverName')]",
"location": "[parameters('location')]",
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]"
},
"resources": [
{
"type": "databases",
"apiVersion": "2020-08-01-preview",
"name": "[parameters('sqlDBName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard",
"tier": "Standard"
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', concat(parameters('serverName')))]"
]
}
]
*"type": "microsoft.storagesync/storageSyncServices/syncGroups/serverEndpoints"
{
"type": "microsoft.storagesync/storageSyncServices/registeredServers",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('FilesyncName'), '/rs')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('FilesyncName'))]"
],
"properties": {
"agentVersion": "XXXX",
"serverOSVersion": "XXXX",
"lastHeartBeat": "XXXXX",
"serverRole": "Standalone",
"clusterId": "XX",
"serverId": "XXXXX",
"friendlyName": "XXXXXXXX"
}
},
{
"type": "microsoft.storagesync/storageSyncServices/syncGroups/serverEndpoints",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('FilesyncName'),'/',parameters('syncgroupname'),'/','-se')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices/syncGroups', parameters('FilesyncName'), parameters('syncgroupname'))]",
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('FilesyncName'))]",
"[resourceId('microsoft.storagesync/storageSyncServices/registeredServers', parameters('FilesyncName'), 'rs')]"
],
"properties": {
"serverLocalPath": "F:\\",
"cloudTiering": "On",
"volumeFreeSpacePercent": 20,
"tierFilesOlderThanDays": 7,
"friendlyName": "XXXX",
"serverResourceId": "[resourceId('microsoft.storagesync/storageSyncServices/registeredServers', parameters('FilesyncName'), 'rs')]",
"offlineDataTransfer": "On",
"offlineDataTransferShareName": "fsnew",
"initialDownloadPolicy": "NamespaceOnly",
"localCacheMode": "UpdateLocallyCachedFiles"
}
}*
The above resource type and the ARM TEMPLATE for adding the server end points.
This template doesn't trigger the provisioning the server end-point. Would like to see an example of the same.TIA
The following is a working ARM template that deploys a Storage Sync Service, a Sync Group and a Server Endpoint.
You can get the serverResourceId property when you register the server with your Storage sync server as described here, but in the ResourceId format:
/subscriptions/***/resourceGroups/***/providers/microsoft.storagesync/storageSyncServices/mystoragesyncservice/registeredServers/85fa92da-2b2e-447c-d3rg-f8bf43c4064f
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storagesyncservicename": {
"type": "string",
"defaultValue": "mystoragesyncservice"
}
},
"variables": {},
"resources": [
{
"type": "microsoft.storagesync/storageSyncServices",
"apiVersion": "2020-03-01",
"name": "[parameters('storagesyncservicename')]",
"location": "westus2",
"properties": {
"incomingTrafficPolicy": "AllowAllTraffic"
}
},
{
"type": "microsoft.storagesync/storageSyncServices/syncGroups",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('storagesyncservicename'), '/mystoragesyncgroup')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('storagesyncservicename'))]"
],
"properties": {}
},
{
"type": "microsoft.storagesync/storageSyncServices/syncGroups/serverEndpoints",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('storagesyncservicename'), '/mystoragesyncgroup/5770750b-a1e6-4910-9781-1482fdee757a')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices/syncGroups', parameters('storagesyncservicename'), 'mystoragesyncgroup')]",
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('storagesyncservicename'))]"
],
"properties": {
"serverLocalPath": "D:\\Data",
"cloudTiering": "Off",
"volumeFreeSpacePercent": 20,
"friendlyName": "mytestafs",
"serverResourceId": "/subscriptions/***/resourceGroups/***/providers/microsoft.storagesync/storageSyncServices/mystoragesyncservice/registeredServers/85fa92da-2b2e-447c-d3rg-f8bf43c4064f",
"offlineDataTransfer": "Off",
"initialDownloadPolicy": "NamespaceThenModifiedFiles",
"localCacheMode": "UpdateLocallyCachedFiles"
}
}
]
}
I dont see any reason why not. its just a regular provider in Azure ARM api.
I'm trying to do the following:
Create a keyvault (works)
Create an AZ function (works)
Use the keyvault's vaultURI as an App Setting to the AZ function (works)
Give the AZ function managed identity (works)
Create an Access Policy whereby the AZ function has access to the keyvault (whoopsie!)
Originally I was creating the Access Policy within the Keyvault, but I had to declare the AZ function as depending on the Key Vault (such that I could fetch its URI). Obviously, I was then unable to set Key Vault to depend on the AZ Function (since this would create a cyclic dependency). I then tried creating the AccessPolicy as another step, and marking it as depends on the KeyVault, and the AZ Function (thinking it would be provisioned last).
But for some reason, when looking at the deployment logs, it always seems like he's trying to deploy it first! Any help would be appreciated.
ARM Template truncated for brevity:
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2016-10-01",
"name": "[variables('keyVaultName')]",
"location": "[ResourceGroup().location]",
"properties": {
"sku": {
"family": "A",
"name": "Standard"
},
"tenantId": "[subscription().tenantId]",
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[parameters('userId')]",
"permissions": {
"keys": [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore"
],
"secrets": [
"Get",
"List",
"Set",
"Delete",
"Recover",
"Backup",
"Restore"
],
"certificates": [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore",
"ManageContacts",
"ManageIssuers",
"GetIssuers",
"ListIssuers",
"SetIssuers",
"DeleteIssuers"
]
}
}
],
"enabledForDeployment": false,
"enabledForDiskEncryption": false,
"enabledForTemplateDeployment": false
}
},
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"name": "[concat(variables('keyVaultName'),'/add')]",
"apiVersion": "2018-02-14",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('functionName'))]",
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
],
//tried both the above and the below
"dependsOn": [
"[variables('keyVaultName')]",
"[variables('functionName')]"
],
"properties": {
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]",
"permissions": {
"keys": [
],
"secrets": [
"Get",
"Set",
"Delete"
],
"certificates": [
]
}
}
]
}
},
.
.
.
.
.
.
.
.
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('functionName')]",
"location": "[ResourceGroup().location]",
"dependsOn": [
"[variables('planName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]",
"[variables('keyVaultName')]",
"[variables('databaseName')]"
],
"kind": "functionapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"serverFarmId": "[variables('planName')]",
"enabled": true,
"reserved": false
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "connectionstrings",
"type": "config",
"dependsOn": [
"[variables('functionName')]",
"[variables('databaseName')]"
],
"properties": {
}
},
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[variables('functionName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]",
"[variables('keyVaultName')]"
],
"properties": "[union(variables('completeAppSettings'),json(concat('{ AzureWebJobsStorage:\"', concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), '2019-04-01').keys[0].value), '\", WEBSITE_CONTENTAZUREFILECONNECTIONSTRING:\"',\tconcat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), '2019-04-01').keys[0].value), '\", WEBSITE_CONTENTSHARE:\"', variables('functionName'), '\", APPINSIGHTS_INSTRUMENTATIONKEY:\"', reference(concat('microsoft.insights/components/', variables('appInsightsName'))).InstrumentationKey, '\", KeyVaultUri:\"', reference(concat('Microsoft.KeyVault/vaults/', variables('keyVaultName'))).vaultUri, '\"}')))]"
},
{
"type": "slots",
"apiVersion": "2016-08-01",
"name": "[variables('functionStagingName')]",
"location": "[ResourceGroup().location]",
"dependsOn": [
"[variables('functionName')]",
"[variables('keyVaultName')]"
],
"kind": "functionapp",
"properties": {
"enabled": false,
"serverFarmId": "[variables('planName')]"
}
}
]
}
]
P.s. I know the way I'm creating my app settings is a work of art (sarcasm). Please don't judge me, just know that it works.
P.p.s Complete ARM Template: https://pastebin.com/mma4PyRu
your template is absolutely fine, so if this doesnt work it looks like a bug. having said that, you can always work around this by moving your accessPolicy assignment into a nested template:
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "linkedTemplate",
"dependsOn": [
"[variables('keyVaultName')]",
"[variables('functionName')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json",
"contentVersion":"1.0.0.0"
},
"parameters": {
"managedIdentityId":{"value": "[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]"}
}
}
You'd need to upload the template somewhere (which should consist of just your accessPolicy assignment
Reading: https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-linked-templates#external-template
Try removing the apiVersion from the reference() function, that should delay the call until after the resource is provisioned. e.g.
[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default')).principalId]"
I have an Azure Resource Group Deployment project in Visual Studio 2019 that validates and deploys fine from Visual Studio, however when I try to deploy it through Azure Release Pipeline with an Azure Resource Group Deployment Task it intermittently fails with the error:
The request content was invalid and could not be deserialized:
'Required property 'type' not found in JSON. Path
'properties.template.resources[6]', line 1, position 3759.'. Task
failed while creating or updating the template deployment.
I haven't been able to find any helpful information in my research of the problem.
Here is the template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"sql_name": {
"defaultValue": "project-sql",
"type": "String"
},
"name": {
"defaultValue": "a-data-factory",
"type": "String"
},
"location": {
"defaultValue": "Central US",
"type": "String"
},
"apiVersion": {
"defaultValue": "2018-06-01",
"type": "String"
},
"gitAccountName": {
"type": "String"
},
"gitRepositoryName": {
"type": "String"
},
"gitBranchName": {
"defaultValue": "foo-branch",
"type": "String"
},
"gitRootFolder": {
"defaultValue": "/",
"type": "String"
},
"gitProjectName": {
"type": "String"
},
"ssisdbname": {
"type": "String",
"defaultValue": "SSISDB"
},
"factoryName": {
"type": "string",
"metadata": "Data Factory Name",
"defaultValue": "a-data-factory"
}
},
"variables": {
"factoryId": "[concat('Microsoft.DataFactory/factories/', parameters('factoryName'))]"
},
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2015-05-01-preview",
"name": "[parameters('sql_name')]",
"location": "northcentralus",
"kind": "v12.0",
"properties": {
"administratorLogin": "theadmin",
"administratorLoginPassword": "",
"version": "12.0"
}
},
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2017-03-01-preview",
"name": "[concat(parameters('sql_name'), '/dummyDB')]",
"location": "northcentralus",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('sql_name'))]"
],
"sku": {
"name": "S0",
"tier": "Standard"
},
"kind": "v12.0,user",
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"maxSizeBytes": 268435456000,
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"zoneRedundant": false
}
},
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2017-03-01-preview",
"name": "[concat(parameters('sql_name'), '/dummerDB')]",
"location": "northcentralus",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('sql_name'))]"
],
"sku": {
"name": "S0",
"tier": "Standard"
},
"kind": "v12.0,user",
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"maxSizeBytes": 268435456000,
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"zoneRedundant": false
}
},
{
"type": "Microsoft.Sql/servers/encryptionProtector",
"apiVersion": "2015-05-01-preview",
"name": "[concat(parameters('sql_name'), '/current')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('sql_name'))]"
],
"kind": "servicemanaged",
"properties": {
"serverKeyName": "ServiceManaged",
"serverKeyType": "ServiceManaged"
}
},
{
"type": "Microsoft.Sql/servers/firewallRules",
"apiVersion": "2015-05-01-preview",
"name": "[concat(parameters('sql_name'), '/AllowAllWindowsAzureIps')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('sql_name'))]"
],
"properties": {
"startIpAddress": "0.0.0.0",
"endIpAddress": "0.0.0.0"
}
},
{
"type": "Microsoft.DataFactory/factories",
"apiVersion": "[parameters('apiVersion')]",
"name": "[parameters('factoryName')]",
"location": "[parameters('location')]",
"identity": {
"type": "SystemAssigned"
},
"resources": [
{
"name": "[concat(parameters('factoryName'), '/theIntegrationRuntime1')]",
"type": "Microsoft.DataFactory/factories/integrationRuntimes",
"apiVersion": "2018-06-01",
"properties": {
"type": "Managed",
"typeProperties": {
"computeProperties": {
"location": "Central US",
"nodeSize": "Standard_D2_v3",
"numberOfNodes": 1,
"maxParallelExecutionsPerNode": 2
},
"ssisProperties": {
"catalogInfo": {
"catalogServerEndpoint": "project-sql.database.windows.net",
"catalogAdminUserName": "theadmin",
"catalogAdminPassword": {
"type": "SecureString",
"value": ""
},
"catalogPricingTier": "S0"
},
"edition": "Standard",
"licenseType": "LicenseIncluded"
}
}
},
"dependsOn": [ "[resourceId('Microsoft.DataFactory/factories', parameters('factoryname'))]" ]
}
],
"properties": {
"repoConfiguration": {
"type": "FactoryVSTSConfiguration",
"accountName": "[parameters('gitAccountName')]",
"repositoryName": "[parameters('gitRepositoryName')]",
"collaborationBranch": "[parameters('gitBranchName')]",
"rootFolder": "[parameters('gitRootFolder')]",
"projectName": "[parameters('gitProjectName')]"
}
},
"dependsOn": [ "[resourceId('Microsoft.Sql/servers', parameters('sql_name'))]" ]
}
]
}
The Release Pipeline was pointed to an old build artifact with a malformed template.
I have been trying to automate deployment of my resources to resource group on Azure. Right now I am using ARM templates and so far I was able to create App Insights and App Service Plan using a template. This is how it looks like:
{
"apiVersion": "2015-05-01",
"name": "[variables('servicePlan')]",
"kind": "linux",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "BTC Push Notification Settings HostingPlan"
},
"sku": {
"name": "[variables('skuNamePlan')]",
"capacity": "[variables('skuSizePlan')]"
},
"properties": {
"name": "[variables('servicePlan')]"
}
},
{
"apiVersion": "2015-05-01",
"name": "[variables('appInsights')]",
"type": "Microsoft.Insights/components",
"location": "southcentralus",
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('appInsights'))]": "Resource",
"displayName": "BTC Push Notification Settings App Insights"
},
"properties": {
"applicationId": "[variables('appInsights')]"
}
}
I am having hard time creating Web App for Containers and pointing it to my docker image using ARM template. I have done it manually and it worked, likewise I did it through azure-cli like this az webapp create --resource-group ExampleGroupAlpina --plan myAppServicePlan --name DockerContainer --deployment-container-image-name this-is-my-image/sample-docker and this worked as well. I would appreciate if anyone could suggest creating this Web App for Containers using ARM Template.
For me none of these other answers worked. With the assistance of Azure support and these other answers I came up with the following template, that succesfully creates an app service plan with an Linux App Service for Containers running a custom Docker image from Azure Container Repository:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"environment":{
"type": "string"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location (region) for all resources."
}
},
"appServiceSku": {
"type": "string",
"defaultValue": "B1",
"metadata": {
"description": "The SKU of App Service Plan "
}
},
"dockerImageName": {
"type": "string",
"defaultValue": "_MY_REGISTRY_USERNAME_.azurecr.io/_MY_NAMESPACE_/_MY_DOCKER_IMAGE_NAME_:_TAG_"
},
"dockerRegistryUrl": {
"type": "string",
"defaultValue": "https://_MY_REGISTRY_USERNAME_.azurecr.io"
},
"dockerRegistryUsername": {
"type": "string",
"defaultValue": "_MY_REGISTRY_USERNAME_"
},
"dockerRegistryPassword": {
"type": "string",
"defaultValue": "_MY_REGISTRY_PSW_"
},
"_artifactsLocation": {
"type": "string"
},
"_artifactsLocationSasToken": {
"type": "securestring"
}
},
"variables": {
"name": "projectname-",
"webAppPortalName": "[concat(variables('name'), parameters('environment'), '-webapp')]",
"appServicePlanName": "[concat(variables('name'), parameters('environment'),'-hosting')]",
"resources": [
{
"apiVersion": "2017-08-01",
"type": "Microsoft.Web/serverfarms",
"kind": "linux",
"name": "[variables('appServicePlanName')]",
"location": "[parameters('location')]",
"comments": "This app service plan is used for the web app and slots.",
"properties": {
"reserved": true
},
"dependsOn": [],
"sku": {
"name": "[parameters('appServiceSku')]"
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('webAppPortalName')]",
"kind": "app,linux,container",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
],
"properties": {
"name": "[variables('webAppPortalName')]",
"siteConfig": {
"linuxFxVersion": "[concat('DOCKER|', parameters('dockerImageName'))]",
"alwaysOn": true,
"appSettings": [
{
"name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
"value": "false"
},
{
"name": "DOCKER_REGISTRY_SERVER_URL",
"value": "[parameters('dockerRegistryUrl')]"
},
{
"name": "DOCKER_REGISTRY_SERVER_USERNAME",
"value": "[parameters('dockerRegistryUsername')]"
},
{
"name": "DOCKER_REGISTRY_SERVER_PASSWORD",
"value": "[parameters('dockerRegistryPassword')]"
}
]
},
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
}
}
]
}
_artifactsLocation and _artifactsLocationSasToken do not need values, but somehow they need to be included. The main difference to other answers is the inclusion of the reserved attribute in the properties for the App Service Plan.
Hopefully this saves some of the headache this created for me!
The following ARM template worked for me.
It allows to specify the authentication details of a private Azure Container Registry.
Also make sure the docker image name follows this pattern: _MY_REGISTRY_USERNAME_-on.azurecr.io/_MY_NAMESPACE_/_MY_DOCKER_IMAGE_NAME_:latest
I run the az command like this:
az group deployment create \
--name "deployAzureApp" \
--resource-group <MY_RESOURCE_GROUP_NAME> \
--template-file <MY_ARM_JSON_TEMPLATE>.json --verbose --debug
Here's the Azure Resource Manager (ARM) JSON template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"type": "String",
"defaultValue": "_MY_APP_NAME_"
},
"dockerImageName": {
"type": "String",
"defaultValue": "_MY_REGISTRY_USERNAME_-on.azurecr.io/_MY_NAMESPACE_/_MY_DOCKER_IMAGE_NAME_:latest"
},
"dockerRegistryUrl": {
"type": "String",
"defaultValue": "https://_MY_REGISTRY_USERNAME_-on.azurecr.io"
},
"dockerRegistryUsername": {
"type": "String",
"defaultValue": "_MY_REGISTRY_USERNAME_"
},
"dockerRegistryPassword": {
"type": "String",
"defaultValue": "_MY_REGISTRY_PSW_"
},
"servicePlanName": {
"type": "String",
"defaultValue": "_MY_SERVICE_PLAN_NAME_"
},
"appLocation": {
"type": "String",
"defaultValue": "_MY_REGION_"
}
},
"resources": [
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[parameters('appName')]",
"kind": "app,linux,container",
"location": "[parameters('appLocation')]",
"properties": {
"name": "[parameters('appName')]",
"siteConfig": {
"linuxFxVersion": "[concat('DOCKER|', parameters('dockerImageName'))]",
"alwaysOn": true,
"appSettings": [
{
"name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
"value": "false"
},
{
"name": "DOCKER_REGISTRY_SERVER_URL",
"value": "[parameters('dockerRegistryUrl')]"
},
{
"name": "DOCKER_REGISTRY_SERVER_USERNAME",
"value": "[parameters('dockerRegistryUsername')]"
},
{
"name": "DOCKER_REGISTRY_SERVER_PASSWORD",
"value": "[parameters('dockerRegistryPassword')]"
}
]
},
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('servicePlanName'))]"
}
}
]
}
About Azure Web App for Container, actually, there is just one point different with Azure Web App in the template. The point is the kind type.
Azure Web App:
"kind": "app"
Azure Web App for Container:
"kind": "app,linux,container",
So, you can create the Azure Web App for Container using template just setting up the kind with app,linux,container.
Update
I do the test and find out that the website kind is not the most important. The key is the property of the website:
"siteConfig": {
"linuxFxVersion": "DOCKER|nginx"
},
And the template will like below and it does a good job.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"webAppName": {
"type": "string",
"metadata": {
"description": "Base name of the resource such as web app name and app service plan "
},
"minLength": 2
},
"sku": {
"type": "string",
"defaultValue": "S1",
"metadata": {
"description": "The SKU of App Service Plan "
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"webAppPortalName": "[concat(parameters('webAppName'), '-webapp')]",
"appServicePlanName": "[concat('AppServicePlan-', parameters('webAppName'))]"
},
"resources": [
{
"apiVersion": "2017-08-01",
"type": "Microsoft.Web/serverfarms",
"kind": "linux",
"name": "[variables('appServicePlanName')]",
"location": "[parameters('location')]",
"comments": "This app service plan is used for the web app and slots.",
"properties": {},
"dependsOn": [],
"sku": {
"name": "[parameters('sku')]"
}
},
{
"apiVersion": "2016-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables('webAppPortalName')]",
"location": "[parameters('location')]",
"comments": "This is the web app, also the default 'nameless' slot.",
"properties": {
"name": "[parameters('webAppName')]",
"siteConfig": {
"appCommandLine": "",
"linuxFxVersion": "DOCKER|nginx"
},
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
]
}
]
}
For what I observed, the linuxFxVersion problem depends on the App Service Plan where the Web App is hosted. What helped me was to set the reserved property on the properties object of App Service Plan resource to true.
What Microsoft doumentation says about the reserved setting:
If Linux app service plan true, false otherwise.
It says nothing about its default value, but from what I observed its false.
This is how my App Service Plan resource ARM template looks like.
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2019-08-01",
"name": "[variables('appServicePlanName')]",
"location": "[parameters('location')]",
"sku": {
"name": "[parameters('appServicePlanSkuName')]",
"tier": "[parameters('appServicePlanSkuTier')]",
"size": "[parameters('appServicePlanSkuSize')]",
"family": "[parameters('appServicePlanSkuFamily')]",
"capacity": "[parameters('appServicePlanSkuCapacity')]"
},
"kind": "linux",
"properties": {
"name": "[variables('appServicePlanName')]",
"reserved": true
}
}
The above template doesn't work now and will show the following logs-
[error]BadRequest: {
"Code": "BadRequest",
"Message": "The parameter LinuxFxVersion has an invalid value.",
"Target": null,
"Details": [
{
"Message": "The parameter LinuxFxVersion has an invalid value."
},
{
"Code": "BadRequest"
},
{
"ErrorEntity": {
"ExtendedCode": "01007",
"MessageTemplate": "The parameter {0} has an invalid value.",
"Parameters": [
"LinuxFxVersion"
],
"Code": "BadRequest",
"Message": "The parameter LinuxFxVersion has an invalid value."
}
}
],
"Innererror": null
}
To fix this, We can make it 2 steps deployment process as mentioned in the following blog
Updated Solution