Deployment of Azure Container Apps with Volume Mounts using Terraform

Recently with working with a customer, we wanted to set up Azure Container Apps with Volume Mounts using CI/CD with Terraform. Until now, the only option has been to configure it using Azure CLI.

However! last week Microsoft introduced some new part of the API that allows us to manage this using Azure Resource Manager natively, as seen here –> Microsoft.App/managedEnvironments/storages 2022-01-01-preview – Bicep, ARM template & Terraform AzAPI reference | Microsoft Learn

Azure Container Apps can either be configured to use

  • Local file system
  • Temporary file storage
  • Azure Files

Azure Files has some advantages given if you need persistent and read-write storage.

  • Files written under the mount location are persisted to the file share.
  • Files in the share are available via the mount location.
  • Multiple containers can mount the same file share, including ones that are in another replica, revision, or container app.
  • All containers that mount the share can access files written by any other container or method.
  • More than one Azure Files volume can be mounted in a single container.

To achieve this using Terraform you need to use the AzAPI provider since Azure Container Apps is not a native TF resource as part of the Azure provider yet.

So, to use Azure Files to the deployment we need to split it up into three sections.

1: Setup Azure Files and a share using Terraform

resource "azurerm_storage_account" "stacc" {
  name                     = "staccaca"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Premium"
  account_replication_type = "LRS"
  account_kind             = "FileStorage"
}

resource "azurerm_storage_share" "share" {
  name                 = "acashare"
  quota                = "200"
  storage_account_name = azurerm_storage_account.storage.name
  depends_on           = [azurerm_storage_account.storage]
}

2: Setup Azure Container App Environment with Custom Storage Properties

This requires a new resource reference as part of the deployment. I’ve excluded the deployment of the App Environment, but you will still need it to deploy the configuration. It should also be noted that I’ve needed to disable the schema validation since it is not a defined property as part of the schema but the REST endpoint supports it.

resource "azapi_resource" "acastorage" {
  schema_validation_enabled = false
  type = "Microsoft.App/managedEnvironments/storages@2022-01-01-preview"
  name = "acastorage"
  parent_id = azapi_resource.containerapp_environment.id
  body = jsonencode({
    properties = {
      azureFile = {
        accountKey = azurerm_storage_account.storage.primary_access_key
        accountName = azurerm_storage_account.storage.name
        shareName = azurerm_storage_share.share.name
        AccessMode = "ReadWrite"
      }
    }
  })
}

3: Lastly reference the mount point in the application. 

It is important to note during when you are adding the Azure Files share that you need to reference the storage account name, if not the deployment will fail. I’ve marked it with bold the actually storage references.

resource "azapi_resource" "containerapp" {
  type      = "Microsoft.App/containerapps@2022-03-01"
  name      = "app01acae"
  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 : 80
        },
      }
      template = {
        containers = [
          {
            image = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"
            name  = "simple-hello-world-container"
            resources = {
              cpu    = 0.25
              memory = "0.5Gi"
            }
            volumeMounts = [
              {
                mountPath  = "/my-files",
                volumeName = "azurefilesvolume"
              }
            ]
          }
        ]
        scale = {
          minReplicas = 0,
          maxReplicas = 2
        },
        volumes = [
          {
            name        = "azurefilesvolume",
            storageType = "AzureFile"
            storageName = "acastoragereferencename"
          }
        ]
      }
    }

Once the deployment is done you can logon to the Container Apps using az containerapp exec command and see that the volume mounting was successful. Then running df -h as seen below

NOTE: If you do not generate any files within the container the file share will be empty.

Happy storage mounting!

Leave a Reply

Scroll to Top