Commute App on Azure App Service

In a previous blog post I described how I built Commute. In that blog post, the app was running on a single Azure VM. If you haven't yet, check out that post for some context on the app.

In this blog post, I deploy Commute on Azure App Service on Linux (currently in public preview[1]). App Service is a platform-as-a-service (PaaS) offering of Microsoft Azure[2] so there's no need to worry about individual VMs.

All commands use the Azure CLI 2.0. If you haven't tried it out yet, it's an invaluable tool to interact with Azure.

1 - Create Resource Group

First step is to create a resource group, I like to have each of my apps in a separate resource group. (What's a resource group?)

$ az group create -n commute-app -l westus
{
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/commute-app",
  "location": "westus",
  "managedBy": null,
  "name": "commute-app",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null
}

2 - Create an App Service Plan

Next, we create an App Service plan. A single app service plan allows us to host several apps inside of it. The --is-linux flag is important as that's what will allow us to deploy our Docker-based app. (What's an app service plan?)

Tip: I use the S1 Sku as I want custom domain support but there are many other skus available.

$ az appservice plan create -g commute-app -n commute-plan --sku S1 --is-linux
{
  "appServicePlanName": "commute-plan",
  "geoRegion": "West US",
  "kind": "app",
  "location": "West US",
  "maximumNumberOfWorkers": 10,
  "name": "commute-plan",
  "provisioningState": "Succeeded",
  "reserved": true,
  "resourceGroup": "commute-app",
  "sku": {
    "name": "S1",
    "size": "S1",
    "tier": "Standard"
  },
  "status": "Ready",
  ...
}

3 - Create an App Service App

Now, we create an app inside the app service plan. Use the resource group and plan names you created before.

Tip: Did you forget the name of the resource group or plan you just created, use tab completion provided by Azure CLI.

$ az appservice web create -g commute-app --plan commute-plan -n commute-app-api
{
  "defaultHostName": "commute-app-api.azurewebsites.net",
  "enabled": true,
  "kind": "app",
  "location": "West US",
  "name": "commute-app-api",
  "state": "Running",
  "usageState": "Normal",
  ...
}

4 - Configure backend app with container

The app has been created now but we need to configure it to run what we want. Commute App is based on containers and App Service supports Docker images! This command will configure the app to use the container.

$ az appservice web config container update -g commute-app -n commute-app-api -c derekbekoe/commute-api:0.3
{
  "DOCKER_CUSTOM_IMAGE_NAME": "derekbekoe/commute-api:0.3"
}

5 - Configure backend

The app uses the Google Maps API. The following command sets the API key to use. Azure App Service will restart the containers and pass in the API key that it needs.

The exact line of code in the app that uses this key is here on GitHub.

$ az appservice web config appsettings update -g commute-app -n commute-app-api --settings GOOGLE_MAPS_API_KEY=<GOOGLE_MAPS_API_KEY>
{
  "DOCKER_CUSTOM_IMAGE_NAME": "derekbekoe/commute-api:0.3",
  "GOOGLE_MAPS_API_KEY": "<GOOGLE_MAPS_API_KEY>",
  "WEBSITE_NODE_DEFAULT_VERSION": "6.9.1"
}

The backend has been deployed and will be available at https://api_app_name.azurewebsites.net.

6 - Deploy the frontend app

Just like before, we create an app service app but this time for our frontend.

$ az appservice web create -g commute-app --plan commute-plan -n commute-app
{
  "defaultHostName": "commute-app.azurewebsites.net",
  "enabled": true,
  "kind": "app",
  "location": "West US",
  "name": "commute-app",
  "state": "Running",
  "usageState": "Normal",
  ...
}

7 - Configure frontend app with container

Once again, we configure the app we've created with the container to our frontend service.

$ az appservice web config container update -g commute-app -n commute-app -c derekbekoe/commute-frontend:0.3
{
  "DOCKER_CUSTOM_IMAGE_NAME": "derekbekoe/commute-frontend:0.3"
}

8 - Configure frontend app

The frontend requires the endpoint for the api service. Set this environment variable with the following command.

Replace api_app_name with your API app name.

$ az appservice web config appsettings update -g commute-app -n commute-app --settings COMMUTE_API="https://api_app_name.azurewebsites.net"
{
  "COMMUTE_API": "https://api_app_name.azurewebsites.net",
  "DOCKER_CUSTOM_IMAGE_NAME": "derekbekoe/commute-frontend:0.3",
  "WEBSITE_NODE_DEFAULT_VERSION": "6.9.1"
}

🎉 You're done! 🎉

The full app is now available at https://app_name.azurewebsites.net.

Configure your custom domain (somewhat advanced)

For extra credit, you probably don't want your production app to use a subdomain of azurewebsites.net but your own domain name.

This section outlines how to hook up your custom domain name to your Azure App Service app.

The first thing you'll probably try is the az appservice web config hostname add command. However, this will likely fail initially.

$ az appservice web config hostname add -g commute-app --webapp-name commute-app --name commute.today
Operation failed with status: 'Bad Request'. Details: 400 Client Error: Bad Request for url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/commute-app/providers/Microsoft.Web/sites/commute-app/hostNameBindings/commute.today?api-version=2016-08-01

Why did it fail? Because you first need to prove that you own that domain name.

Go into the Azure Portal to get the external IP address of the web app.

Azure Portal App Service Custom Domain pane

Now, in the DNS settings of your provider (here I use CloudFlare), set an A record to point to that IP address. Also, set a TXT record with the value of the DNS name of your web app (app_name.azurewebsites.net).

CloudFlare DNS settings

Setting the A record will allow your DNS provider to route traffic correctly. The TXT record tells Azure App Service that you own that domain and it should accept traffic from your custom domain app_name.azurewebsites.net.

Now, you can add the hostname to your web app config. You'll now see that hostNameType=Verified.

$ az appservice web config hostname add -g commute-app --webapp-name commute-app --name commute.today
{
  "hostNameType": "Verified",
  "location": "West US",
  "name": "commute-app/commute.today",
  "siteName": "commute-app",
}

🎊🎉 All done! 🎉🎊

Now, Commute is running on Azure App Service, we get TLS termination with load balancing and we no longer have to worry about any individual VMs!

Commute App Running


  1. Introduction to App Service on Linux - https://docs.microsoft.com/en-us/azure/app-service-web/app-service-linux-intro ↩ī¸Ž

  2. What is Azure App Service? - https://docs.microsoft.com/en-us/azure/app-service/app-service-value-prop-what-is ↩ī¸Ž