Raymond Raymond

Use Bicep to deploy Azure Container Apps with a free managed certificate

event 2023-06-10 visibility 382 comment 0 insights
more_vert
insights Stats
Use Bicep to  deploy Azure Container Apps with a free managed certificate

Code description

Context

A few weeks ago when I was migrating Kontext from Azure App Services to Azure Container Apps, there was no free managed certificate. To address that issue, I used Let's Encrypt to create a certificate for Kontext. This process will take me a few minutes every few months . 

Now good news is that free managed certificate is also in preview in Azure Container Apps. The following code snippet shows you how to do that in Bicep.


Note:

* when I deploy using Bicep, my container app was already existing. This means the domain verification is already added to my Azure DNS zones.  If you are building a new app using managed certificate, I would suggest you do it in two steps:

  1. Bicep code to create container app enivronment, container and DNS records (incl. A record that points to IP of your container app and/or asuid  verification TXT record).

  2. And then update Bicep code to add managed certificate and custom domains. In custom domains, you can reference the managed certificate ID directly. And then deploy Bicep code again with delta changes.

* The container image is from GitHub (not Azure Container Registry) in the following example.

Issues

When I run the deployments, Azure throws out one interim error like the following (however the deployment itself was not failing):

The client 'XXX' with object id 'XXX' does not have authorization to perform action 'Microsoft.App/locations/managedCertificateOperationStatuses/read' over scope '/subscriptions/XXX/providers/Microsoft.App/locations/Australia East/managedCertificateOperationStatuses/XXX' or the scope is invalid. If access was recently granted, please refresh your credentials. (Code: AuthorizationFailed)

After I wait for about 10 minutes the deployment becomes successful as the following screenshot does:

2023061092538-image.png

References

Code snippet

@description('Change it to your region')
param location string = 'australiaeast'

@description('Name of the Container App Environment')
param containerAppEnvName string = 'container-app-env'

@description('Name of the Container App')
param webContainerName string = 'web-app'

@description('GitHub container registry user')
@secure()
param gitHubUserName string

@description('GitHub container registry user access token')
@secure()
param gitHubUserAccessToken string

param logAnalyticsCutomerId string
param logAnalyticsSharedKey string

resource myContainerAppEnvironment 'Microsoft.App/managedEnvironments@2022-11-01-preview' = {
  name: containerAppEnvName
  location: location
  properties: {
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalyticsCutomerId
        sharedKey: logAnalyticsSharedKey
      }
    }
  }
}

resource myManagedCert 'Microsoft.App/managedEnvironments/managedCertificates@2022-11-01-preview' = {
  name: 'managed-cert'
  location: location
  parent: myContainerAppEnvironment
  properties: {
    domainControlValidation: 'HTTP'
    subjectName: 'example-domain.com'
  }
}

resource myWebContainerApp 'Microsoft.App/containerApps@2022-11-01-preview' = {
  name: webContainerName
  location: location
  properties: {
    environmentId: myContainerAppEnvironment.id
    configuration: {
      ingress: {
        external: true
        targetPort: 8000
        allowInsecure: false
        traffic: [
          {
            latestRevision: true
            weight: 100
          }
        ]
        customDomains:[
          {
            bindingType: 'SniEnabled'
            certificateId: myManagedCert.id
            name: 'example-domain.com'
          }
        ]
      }

      registries: [
        {
          server: 'ghcr.io'
          username: gitHubUserName
          passwordSecretRef: 'container-registry-password'
        }
      ]
      secrets: [
        {
          name: 'container-registry-password'
          value: gitHubUserAccessToken
        }
      ]
    }
    template: {
      containers: [
        {
          name: webContainerName
          image: 'ghcr.io/exmaple-org/example-repo:latest'
          resources: {
            cpu: any('0.5')
            memory: '1Gi'
          }
          env: [
            {
              name: 'ASPNETCORE_ENVIRONMENT'
              value: 'AZURE'
            }
          ]
        }
      ]
      scale: {
        minReplicas: 0
        maxReplicas: 1
      }
    }
  }
}

output customDomainVerificationId string = myWebContainerApp.properties.customDomainVerificationId
output appIpAddress string = myContainerAppEnvironment.properties.staticIp
More from Kontext
comment Comments
No comments yet.

Please log in or register to comment.

account_circle Log in person_add Register

Log in with external accounts