In this blog post I am going to show you can deploy multiple Container Apps in Azure using Terraform and AzAPI.
You may be wondering what is AzAPI?
Some times with new resource updates, the terraform AzureRM provider is not up to date or missing a piece of functionality within a particular resource. With this new provider, you can begin deploying using Terraform from day 1 without the need to wait until AzureRM has been updated – awesome!
Further details in this terraform post
Terraform breakdown
I will be deploying:
- Resource Group
- Log Analytics workspace that will be connected to the Container App environment
- Container App environment
- Two container apps

The Resource Group are straight-forward Terraform resources
resource "azurerm_resource_group" "rg" {
name = "${var.aca_name}-rg"
location = var.location
}
resource "azurerm_log_analytics_workspace" "loganalytics" {
name = "${var.aca_name}-la"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
sku = "PerGB2018"
retention_in_days = 30
}
Creating the Container App environment, is the first use of AzAPI, you may be wondering how do I get the syntax required? Extracting from the template feature within Azure is a good recommendation. I will show an example of this
resource "azapi_resource" "containerapp_environment" {
type = "Microsoft.App/managedEnvironments@2022-03-01"
name = "${var.aca_name}acae"
parent_id = azurerm_resource_group.rg.id
location = azurerm_resource_group.rg.location
body = jsonencode({
properties = {
appLogsConfiguration = {
destination = "log-analytics"
logAnalyticsConfiguration = {
customerId = azurerm_log_analytics_workspace.loganalytics.workspace_id
sharedKey = azurerm_log_analytics_workspace.loganalytics.primary_shared_key
}
}
}
})
}
The above was created from the extracted .json template, example of the .json template:
{
"type": "Microsoft.App/managedEnvironments",
"apiVersion": "2022-03-01",
"name": "[parameters('managedEnvironments_tamopsacapublic_name')]",
"location": "uksouth",
"properties": {
"appLogsConfiguration": {
"destination": "log-analytics",
"logAnalyticsConfiguration": {
"customerId": "de002841-1e88-4c38-a4ec-b6ac13334723"
}
},
"zoneRedundant": false
}
},
To finish the Terraform deployment, is the Container Apps – I created this with a for_each, so it can loop over the amount of Container Apps that I want to deploy
resource "azapi_resource" "containerapp" {
for_each = local.apps
type = "Microsoft.App/containerapps@2022-03-01"
name = "${each.key}acae"
parent_id = azurerm_resource_group.rg.id
location = azurerm_resource_group.rg.location
body = jsonencode({
properties = {
managedEnvironmentId = azapi_resource.containerapp_environment.id
configuration = {
ingress = {
external : true,
targetPort : each.value.targetPort
},
}
template = {
containers = [
{
image = each.value.image,
name = each.value.imagename
resources = {
cpu = each.value.cpu
memory = each.value.memory
}
}
]
scale = {
minReplicas = each.value.minReplicas,
maxReplicas = each.value.maxReplicas
}
}
}
})
depends_on = [
azapi_resource.containerapp_environment
]
}
locals.tf
locals {
apps = {
app01 = {
targetPort = 80
image = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"
imagename = "simple-hello-world-container"
minReplicas = 0
maxReplicas = 2
cpu = 0.25
memory = "0.5Gi"
},
app02 = {
targetPort = 80
image = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"
imagename = "simple-hello-world-container"
minReplicas = 0
maxReplicas = 2
cpu = 0.25
memory = "0.5Gi"
}
}
}
Full terraform here in this repository , it is configured to run locally with a tf.vars file with example commands:
terraform init
terraform apply -var-file="prod.tfvars"
Once deployed successfully, as mentioned – Log Analytics have been preconfigured with the Container Environment – logs appear right away!

AzAPI is awesome; wouldn’t be possible to deploy Container Apps currently without this 🙂
Thanks for reading & hopefully it assists you in your journey until there is a suitable provider released for all things Container Apps.
4 comments