APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Azure Container Appsで無料の証明書を使う(bicep AVMを使って)

はじめに

以前、Azure Container Appsを使って無料のマネージド証明書を導入する方法をご紹介しました。

techblog.ap-com.co.jp

だいぶ時間も立っているので状況はどうなっているのか気になっていたのですが、今回同様の手順を試す機会がありいくつか確認してみました。 結果、以前の手順に若干の誤りがあったようです。

過去の誤りの訂正

誤りというのは『試行錯誤、そして気づいたこと』の部分の 登録用のBicepファイルを見ていると、実はApplication登録がなくてもデプロイできるんじゃないか。ちなみに、certificateのname '${environment.name}-certificate' ですが、この内容じゃないと登録に失敗します の部分。

前回は1度の実行で問題なく登録できるように説明していますが、今回試してみてやはり

  1. カスタムドメイン情報をつけ、証明書のmanaged certificate情報をつけずにApplicationを登録
  2. 上記が完了したらmanaged certificate情報を付与して再登録

という手順が必要ということがわかりました。

       customDomains: [
          {
            name: '${cname}.${dnsZoneName}'
            bindingType: 'SniEnabled'   // マネージド証明書の利用を宣言
            certificateId: certificate.id   // マネージド証明書のID
          }        

の部分を正常に完了するためにはカスタムドメイン情報を付与したアプリケーションがすでに登録されている必要があるようです。 すでに登録されている状態であれば特に意識する必要はありません。前回うまくいっているように見えたのはAzureのどこかに情報が残っていたためではないかと推測しています。

また、certificateの名前も今回 '${containerName}-certificate' で登録したところ問題なくできました。

あらためてBicepの登録スクリプトを紹介

誤りの訂正だけで終わってしまうと情報がなさすぎるので、あらためてスクリプトを紹介します。

前回との違いは、 Bicep public registry AVMのモジュールを活用しているところです。

今後は、IaCの標準化であるAVM(Azure Verified Module)を活用することが多くなると思いますので、この例が参考になれば幸いです。

techblog.ap-com.co.jp

スクリプト全体

main.bicepの内容は以下のとおりとなります。

@description('Optional. Location for all Resources.')
param location string = resourceGroup().location

@description('Container environment name')
param environmentName string
@description('nginx app name')
param containerName string = 'nginx'
@description('Target port for nginx app')
param targetPort int = 80
@description('Minimum number of container replicas. Defaults to 2 if not set')
param scaleMinReplicas int = 2
@description('Maximum number of container replicas. Defaults to 10 if not set.')
param scaleMaxReplicas int = 5
@allowed([
  'Multiple'
  'Single'
])
@description('Controls how active revisions are handled for the Container app.')
param activeRevisionsMode string = 'Single'

@description('Use custom domain or not')
param customDomainEnabled bool = true
@description('Custom domain suffix if you use')
param customDomainSuffix string = ''
@description('Wheter or not to bind managed certifcate to this host')
param bindCertificate bool = true


resource environment 'Microsoft.App/managedEnvironments@2023-05-01' existing = {
  name: environmentName
}

var useCertifacate = customDomainEnabled && bindCertificate
resource certificate 'Microsoft.App/managedEnvironments/managedCertificates@2023-05-01' = if(useCertifacate) {
  name: '${containerName}-certificate'
  parent: environment
  location: location
  properties: {
    domainControlValidation: 'CNAME'
    subjectName: '${containerName}.${customDomainSuffix}'
  }
}

var customDomains = customDomainEnabled ? [
  {
    name: '${containerName}.${customDomainSuffix}'
    bindingType: bindCertificate ? 'SniEnabled' : 'Disabled'
    certificateId: bindCertificate ? certificate.id : null
  }
] : []

module nginx 'br/public:avm/res/app/container-app:0.2.0' = {
  name: 'container-apps-nginx'
  params: {
    environmentId: environment.id
    name: containerName
    location: location
    containers: [
      // nginx container
      {
        image: 'nginx:1.25.5'
        name: containerName
      }
      
    ]
    customDomains: customDomains
    ingressTargetPort: targetPort
    scaleMinReplicas: scaleMinReplicas
    scaleMaxReplicas: scaleMaxReplicas
    activeRevisionsMode: activeRevisionsMode
  }
}

そしてこのスクリプトを実行する際に使用する bicepparam ファイルは以下の内容となります。

using './main.bicep'

param environmentName = readEnvironmentVariable('ACA_ENVIRONMENT_NAME', 'aca-environment')
param customDomainSuffix = readEnvironmentVariable('CUSTOM_DOMAIN_SUFFIX', '')
param bindCertificate = true

実行するコマンドは以下のとおりです

az deployment group create \
  --name nginx-aca \
  --parameters ./man.bicepparam \
  --resource-group ${RESOURCE_GROUP}

スクリプトの内容解説

AVM

今回Azure Container Appsの登録で使用しているAVMは br/public:avm/res/app/container-app です。内容はMicrosoft Certifiedなので安心して利用できますね。

ドメインの内容
今回のスクリプトはカスタムドメインを使う・使わないも選択可能になっています。customDomainEnabled を trueにするとカスタムドメイン登録を行います。 カスタムドメイン名は customDomainSuffix で指定します。実際のアプリケーション名は ${containerName}.${customDomainSuffix} になります。

DNSレコードの登録
カスタムドメインを利用する場合はDNSに以下のレコードが必要になります。(今回もCNAMEを利用します)

  • asuid.${containerName}.${customDomainSuffix} の TXT として Container Appsのproperty environment.properties.customDomainConfiguration.customDomainVerificationId を登録します
  • ${containerName}.${customDomainSuffix} のCNAME として ${containerName}.${environment.properties.defaultDomain} を登録します

アプリケーションの登録

最初のところで説明した通り、まず証明書の指定をしない状態でコンテナアプリケーションをContainer Apps Environtmentに登録します。 これは bicepparam ファイルのbindCertificate をfalseにして実行することで実現できます。

bindCertificateをfalseにすると resource certificate 'Microsoft.App/managedEnvironments/managedCertificates@2023-05-01' の部分は実行されず、 customDomainsの内容が

var customDomains = [
  {
    name: '${containerName}.${customDomainSuffix}'
    bindingType: 'Disabled'
    certificateId: null
  }
] 

という状態で登録されます。bindiingTypeを'Disabled'にすることでホスト名(name )の部分のみが反映されます。

登録が完了したら今度は bindCertificateをtrueにして再度実行します。今度はresource certificate 'Microsoft.App/managedEnvironments/managedCertificates@2023-05-01' の部分も実行され、cusomDomainsのbidingTypeがSniEnabled として実行されます。これにより無料の証明書が自動的に割り当てられるようになります。

var customDomains = [
  {
    name: '${containerName}.${customDomainSuffix}'
    bindingType: 'SniEnabled'
    certificateId: certificate.id
  }
] 

まとめ

AVMを活用したとはいえ、まだマネージド証明書の有効化の部分までは登録されていませんでした。このためこれまでのナレッジをもとにスクリプトを組み合わせて実現しています。この部分は将来的にはAVMなどで「これが正解」といったものが用意されるではないかと思いますが、それまでの間、この記事が参考になれば幸いです。