Using Terraform to create a Dockerized Azure App Service

This article will demonstrate how to create an ACR and App Service in Azure, complete with a custom domain and permissions for the App Service to pull images from the ACR. Note: This article does not go over creating a DNS Zone or DNS records for the custom domain.

Create your Service Principal

The Terraform docs has good documentation on how to do this.

First we need to create a Service Principal (which shows up in the Azure console under App Registrations). Log into your Azure account in the CLI with az login , then create the Service Principal with the following command, using the Subscription ID of the Subscription in your account you want to create the resources in.

az ad sp create-for-rbac --role="Owner" --scopes="/subscriptions/[SUB ID]"

Terraform files

Here are the Terraform files to create an ACR repo and App Service

Set up the required providers for Azure. You could also set up a backend “remote” if you’re running this locally but connecting to Terraform Cloud for example. But for the purposes for this example, it will all be run locally.

This file defines local variables for each environment, to allow them to be referred to easily. For example, our default domain for the App Service looks like ${var.environment}.${var.project}.com , but we override this for the production environment to be ${var.project}.com as we don’t want a subdomain for our production environment.
Note: You need to override the “environment” variable when running for other environments as it defaults to “dev”, shown in the file.

This file defines our Terraform variables. The important ones are the four defined at the bottom that represent our Service Principal.
Note: You don’t need these if you are using Terraform Cloud, as you would define them as Environment variables in the Workspace instead.

Two resource group will be created for this example, the first to house the ACR and the second for all the App Service resources for the backend service.

This file defines our Azure Container Registry resource. This only needs to be created once, not per environment, so a count has been used so that it is only created in the dev environment. (Usually you would create this in the production environment, but this is for example purposes).

This ACR is created in the hub resource group, separate from the backend resource group as in the future, we may want to use this ACR for other services that are also in their own resource groups.

This file defines an Azure App Service Plan and App Service, as well as all the resources to add a custom domain name and permissions to pull images from the ACR.

Applying the Terraform

Run terraform init and then terraform apply to create the resources.

You’ll have to run this a few times and set up some DNS records each time since we haven’t created a DNS Zone and records with in Terraform for this example.

The first time you run apply it will most likely complain that it you missing a TXT DNS record for asuid.[YOUR DOMAIN] (e.g. in the example above it would be This is an easy fix, simply create the DNS record for the subdomain with the value displayed in the error (this should be a 64-length string of characters).

Error: creating/updating Custom Hostname Binding "" (App Service "example-dev-backend-app-service" / Resource Group "example-dev-backend"): web.AppsClient#CreateOrUpdateHostNameBinding: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="BadRequest" Message="A TXT record pointing from to [64 CHARACTER STRING] was not found." 

The second time you run this, you man see an error that your custom domain is not pointing to the default domain of the App Service. You will need to create another DNS record pointing from to .

Error: creating/updating App Service Managed Certificate "" (Resource Group "example-dev-backend"): web.CertificatesClient#CreateOrUpdate: Failure responding 
to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="BadRequest" Message="Properties.CanonicalName is invalid. Not found
CNAME directly pointing to * Current CNAME record of the hostname dev.example.comis empty."

Once done, an image will need to be pushed to the ACR, but that’s another article 😉

Rip it down

Run terraform destroy once you’re ready to delete all the resources.

Hope you found this useful!
Cheers 🤙



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store