This article will show you how to deploy a basic website with a database to Azure. It will use Resource Manager templates. Checkout the article on Resource Manager basics if you are unfamiliar.

We start with the familiar empty template and set the scontentVersion property. Add any of the following snippets to the resources property.

{
   "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
   "contentVersion": "1.0.0.0",
   "resources": [],
}

Deploying the Web App

You run web apps (in Azure terminology an “app service”) in “app service plans”. You need to create one if you don’t want to re-use an existing one.

The resource template for an app service plan is the following fragment. Serverfarm is the old name for app service plans. The definition is available here.

{
   "apiVersion": "2015-08-01",
   "location": "[resourceGroup().location]",
   "name": "demo-asp1",
   "type": "Microsoft.Web/serverfarms",
   "sku": {
      "name": "F1",
      "tier": "Free",
   }
}

This will create the smallest (and free) app service plan available. To create a larger app service change the sku property object. For example to create a basic service plan with medium size and 3 instances you specify:

"sku": {
   "name": "B2",
   "capacity": "3"
}

You can find the other values to specify in the portal or in Microsoft Docs.

Next you can define the app service itself (the web site). Add another resource to the array using this fragment:

{
   "apiVersion": "2015-08-01",
   "location": "[resourceGroup().location]",
   "name": "demo-app1",
   "type": "Microsoft.Web/sites",
   "properties": {
      "serverFarmId": "[resourceId('Microsoft.Web/serverFarms','demo-asp1')]"
   },
   "dependsOn": [
      "['Microsoft.Web/serverFarms/demo-asp1']"
   ]
}

The first four properties are analogue to other resources. An important property is the serverFarmId. This identifies the app service plan create above. Because this resource depends on the other resource existing it needs to be in the “dependsOn” array.

Note the following difference. The serverFarmId needs a resource id. Use the function resourceId and passing in the type and name of the resource. But the dependsOn property requires a string.

Deploying the database

Like above you need a SQL server before you can create a SQL database.

{
   "apiVersion": "2014-01-01",
   "location": "[resourceGroup().location]",
   "name": "demo-sql1",
   "type": "Microsoft.Sql/servers",
   "properties": {
      "administratorLogin": "demo",
      "administratorLoginPassword": "Password12!",
   }
}

Be aware that the apiVersion property is older! Providing the administrator login username and password like this is not recommended. See our next article on for a better approach with KeyVault.

Now you can create the database.

{
   "apiVersion": "2015-01-01",
   "location": "[resourceGroup().location]",
   "name": "demo-sql1/demo-sql1-db1",
   "type": "Microsoft.Sql/servers/databases",
   "dependsOn": [
      "['Microsoft.Sql/servers/demo-sql1']"
   ],
   "properties": {
      "edition": "Basic",
      "requestedServiceObjectiveName": "Basic"
   }
}

Note that the name specified must include the server you are deploying too. This is different to how you referenced the app service plan above.

Most editions have multiple child tiers. For example Standard has S0 – S4. Specify the required value in the requestedServiceObjectiveName.

Finally you need to give the website access to the database. Do this by deploying a firewall rule. This is analog to the other resources you have deployed so far.

{
   "apiVersion": "2014-04-01",
   "location": "[resourceGroup().location]",
   "type": "Microsoft.Sql/servers/firewallrules",
   "dependsOn": [
      "demo-sql1"
   ],
   "name": "demo-sql1/AllowAllWindowsAzureIps",
   "properties": {
      "endIpAddress": "0.0.0.0",
      "startIpAddress": "0.0.0.0"
   }
}

This specific IP address range allows all Azure services to access this database. To access the database from your computer you must add another rule. Replace the IP address range with your public IP address.

{
   "apiVersion": "2014-04-01",
   "location": "[resourceGroup().location]",
   "type": "Microsoft.Sql/servers/firewallrules",
   "dependsOn": [
      "demo-sql1"
   ],
   "name": "demo-sql1/MyIP",
   "properties": {
      "endIpAddress": "x.x.x.x",
      "startIpAddress": "x.x.x.x"
   }
}

Adding app settings and connection strings

You deploy app settings as a seperate resource definition. Note that the name has to include the app service name (not the app service plan name). Also each resource has a mention of the app service in the dependsOn property. You specify the appSettings via the the properties object as a list of key value pairs.

{
   "apiVersion": "2016-03-01",
   "location": "[resourceGroup().location]",
   "type": "Microsoft.Web/sites/config",
   "name": "demo-app1/appsettings",
   "dependsOn": [
      "demo-app1"
   ],
   "properties": {
      "key1": "value1",
      "key2": "value2"
   }
}

You can specify connection strings very similarly.

{
   "apiVersion": "2016-03-01",
   "location": "[resourceGroup().location]",
   "type": "Microsoft.Web/sites/config",
   "name": "demo-app1/connectionstrings",
   "dependsOn": [
      "demo-app1"
   ],
   "properties": {
      "DefaultConnection": {
         "value": "",
         "type": "SQLAzure"
      }
   }
}

The is a standard SQL server connection string:
Data Source=tcp:demo-sql1.database.windows.net,1433;Initial Catalog=demo-sql1-db1;User Id=demo@demo-sql1.database.windows.net;Password=Password12!;

Automatic Deployment from GitHub

There are many ways to deploy to your App Service including FTP, Git and even Dropbox. One of the most interesting ones is direct deployment from a GitHub repository. Each time you commit and push to a branch your App Service updates.

The required resource definition for this is as follows:

{
   "apiVersion": "2015-08-01",
   "location": "[resourceGroup().location]",
   "type": "Microsoft.Web/sites/sourcecontrols",
   "name": "demo-app1/web",
   "dependsOn": [
      "demo-app1",
      "[resourceId('Microsoft.Web/sites/config','demo-app1','appsettings')]",
      "[resourceId('Microsoft.Web/sites/config','demo-app1','connectionstrings')]"
   ],
   "properties": {
      "RepoUrl": "https://github.com/aaronkai/html5-bootstrap",
      "branch": "master",
      "IsManualIntegration": true
   }
}

Note that the name once again needs to include the app service name. Deploying this resource will immediately afterwards pull from the repository. Your build process may depend on app settings and connection strings. So you have to add three dependencies. One for the app services itself. And on each for the app settings and connection strings.

Note that you need to specify the resourceId for these resources. At the time of writing specifying the resource name does not suffice. Even if you add the namespace: Microsoft.Web/sites/config/demo-app1/appsettings .

The properties required are the repository URL and the branch. The third property IsManualIntegration  is set to true. This means you have to trigger deployments in the portal or via an API when you push to GitHub.

Of course this is not the ideal behaviour. To enable automatic deployment set the property to false. This requires that you have setup a connection to GitHub in the portal beforehand. See also Microsoft Docs and search for IsManualIntegration .

Child resources

As you browse the other template files you may come accross child resources defined underneath a parent:

{
   "apiVersion": "2015-08-01",
   "location": "[resourceGroup().location]",
   "name": "demo-app1",
   "type": "Microsoft.Web/sites",
   "properties": {
      "serverFarmId": "[resourceId('Microsoft.Web/serverFarms','demo-asp1')]"
   },
   "dependsOn": [
      "demo-asp1"
   ],
   "resources": [{
      "apiVersion": "2016-03-01",
      "location": "[resourceGroup().location]",
      "type": "config",
      "name": "appsettings",
      "dependsOn": [
         "demo-app1"
      ],
      "properties": {
         "key1": "value1",
         "key2": "value2"
      }
   }]
}

Using this approach you can shorten the names and type values. The parents name and type are automatically appended. You can define these dependencies five levels deep. Unfortunately you must still define the dependencies explicitly.

See Microsoft Docs for more information on defining dependencies in Azure Resource Templates.

Advertisement