Blog
Azure Container Apps und Bicep - Bereitstellung von abhängigen Ressourcen

- Automatische Skalierungsfunktionen basierend auf externem Datenverkehr, CPU- und Speicherauslösern.
- Interkommunikation zwischen Container-Apps entweder über Ingress oder Dapr.
- Benutzerdefinierte VNET-Integration.
- Verteilen Sie den Datenverkehr auf verschiedene Versionen Ihrer App für einfache Blue/Green-Implementierungen und A/B-Tests.
- Kostenvorteile, wenn Sie die Möglichkeit haben, auf null Instanzen zu skalieren.
Bicep Übersicht und Azure Ressourcen
| Ressource | Beschreibung |
| Container Umgebung | Jede Container-Anwendung benötigt eine Container-Umgebung, die eine oder mehrere Container-Anwendungen enthält. Unter der Haube wird die Umgebung in demselben virtuellen Netzwerk bereitgestellt. |
| Container-Register | Die Container-Registrierung ist der Ort, an dem wir die Container-Images für unsere Anwendung speichern, die dann von der Container-App referenziert werden. |
| Container App | Die Ressource der Container-App selbst. |
| Logbuch-Analytik | Wir verwenden Log Analytics für die Protokollierung verschiedener Daten aus der Container-Umgebung wie Telemetrie- und Leistungsprotokolle. |
| Schlüssel Tresor | Im Schlüsseltresor werden die Geheimnisse gespeichert, die unsere App für den Zugriff auf die Protokollanalyse und die Anmeldeinformationen zum Abrufen von Images aus der Container-Registry benötigt. |

Bizeps Dateien
- Main.bicep (contains the Key Vault resource)
- containerApp.bicep
- containerEnvironment.bicep
- containerRegistry.bicep
- logAnalytics.bicep
Geheimnisse der Handhabung im Bizeps
- Use Managed Identities if you don’t want to worry about handling or dealing with secrets/credentials in your bicep files. It allows for authentication and authorization across other resources in Azure.
- Avoid secrets in your bicep files and pass in the value of the secrets from a CI/CD pipeline. An example of this would be storing credentials for the container registry in a GitHub actions secret.
- Use the @secure() decorator for all sensitive parameters. This will ensure the underlying Azure Resource Manager won’t log any passwords or sensitive variables. An example of this can be seen in the container registry bicep file below on line 6.
- Do not output secrets in your bicep files. I've often seen outputs which will include a username or password so it can be used by another module. The values could be compromised by anyone who has access to the deployment. To avoid this, you can add your secrets to Key Vault or use managed identities. An example of this would be:
output userName string = containerRegistry.listCredentials().username
Ressourcen- und Moduldateien
I've included abbreviated versions of the bicep files below. For the complete solution you can reference the files in the following GitHub repo: GitHub - jarrodgodfrey/containerapp-bicep//logAnalytics.bicep
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
name: keyVaultName
}
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2020-10-01' = {
name: logAnalyticsWorkspaceName
location: location
tags: tags
properties: {
retentionInDays: 30
features: {
searchVersion: 1
}
sku: {
name: 'PerGB2018'
}
}
}
//set up a shared secret in key vault which containts the log analytics primary shared key
resource sharedKeySecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
name: sharedKeyName
parent: keyVault
properties: {
value: logAnalytics.listKeys().primarySharedKey
}
}
Here you can see the log analytics resource defined on line 7. What’s more interesting is I’ve defined another resource referencing the existing Key Vault in main.bicep on line 3. I’m using it to set the parent when we add the log analytics shared key to the vault on line 25.
//containerAppEnvironment.bicep
param containerEnvironmentName string
param location string
param logAnalyticsCustomerId string
@secure()
param logAnalyticsSharedKey string
param tags object
resource env 'Microsoft.App/managedEnvironments@2022-03-01' = {
name: containerEnvironmentName
location: location
tags: tags
properties: {
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logAnalyticsCustomerId
sharedKey: logAnalyticsSharedKey
}
}
}
}
output containerAppEnvId string = env.id
Notice on line 7 we have a parameter for the log analytics shared key which is used to configure the container environment on line 19.
//containerRegistry.bicep
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
name: keyVaultName
}
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' = {
name: crName
location: location
tags: tags
sku: {
name: 'Basic'
}
properties: {
adminUserEnabled: true
}
identity: {
type: 'SystemAssigned'
}
}
//adding container registry username to keyvault
resource acrUsername 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
name: usernameSecret
parent: keyVault
properties: {
value: containerRegistry.listCredentials().username
}
}
//adding container registry password to key vault
resource acrPasswordSecret1 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
name: primaryPasswordSecret
parent: keyVault
properties: {
value: containerRegistry.listCredentials().passwords[0].value
}
}
Similar to what was done in logAnalytics.bicep, the username and password are being added to key vault starting on line 23. This is important because the container app itself will utilize those secrets from Key Vault to pull the images from the registry.
//containerApp.bicep
resource containerApp 'Microsoft.App/containerApps@2022-03-01' = {
name: containerAppName
location: location
tags: tags
properties: {
managedEnvironmentId: containerAppEnvId
configuration: {
activeRevisionsMode: 'Single'
ingress: {
external: true
transport: 'http'
targetPort: 3500
allowInsecure: false
traffic: [
{
latestRevision: true
weight: 100
}
]
}
secrets: [
{
name: 'container-registry-password'
value: acrPasswordSecret
}
]
registries: [
{
server: acrServerName
username: acrUsername
passwordSecretRef: 'container-registry-password'
}
]
}
template: {
containers: [
{
name: containerAppName
image: '${acrServerName}/epic-app:latest'
env: envVariables
resources: {
cpu: 1
memory: '2.0Gi'
}
}
]
scale: {
minReplicas: 1
maxReplicas: 10
}
}
}
identity: {
type: 'SystemAssigned'
}
}
Notice we’re passing in the container registry credentials and using them on line 32 so the container app will have access to pull the images. Another important line is 41 where the image is specified. We’re providing the container app the server name of the registry and the name of the image.
//main.bicep
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
name: keyVaultName
location: location
tags: tags
properties: {
sku: {
family: 'A'
name: 'standard'
}
tenantId: tenant().tenantId
enabledForDeployment: true
enabledForTemplateDeployment: true
enableSoftDelete: false
accessPolicies: [
]
}
}
//module invocations:
module logAnalytics 'logAnalytics.bicep' = {
name: 'log-analytics'
params: {
tags: tags
keyVaultName: keyVault.name
location: location
logAnalyticsWorkspaceName: logAnalyticsWorkspaceName
}
}
module containerEnv 'containerAppEnvironment.bicep' = {
name: 'container-app-env'
params: {
containerEnvironmentName: containerEnvironmentName
location: location
logAnalyticsCustomerId: logAnalytics.outputs.customerId
logAnalyticsSharedKey: keyVault.getSecret('law-shared-key')
tags: tags
}
}
module containerRegistry 'containerRegistry.bicep' = {
name: 'acr'
params: {
tags: tags
crName: containerRegistryName
keyVaultName: keyVault.name
location: location
}
}
module containerApp 'containerapp.bicep' = if (isContainerImagePresent){
name: 'container-app'
params: {
tags: tags
location: location
containerAppName: containerAppName
envVariables: containerAppEnvVariables
containerAppEnvId: containerEnv.outputs.containerAppEnvId
acrServerName: containerRegistry.outputs.serverName
acrUsername: keyVault.getSecret('acr-username-shared-key')
acrPasswordSecret: keyVault.getSecret('acr-password-shared-key')
}
}
You can see here where the Key Vault resource is defined and how all the modules are being invoked and deployed.
az deployment group create --resource-group rg-epic-app --template-file main.bicep --parameters isContainerImagePresent=t
Fazit
I’m extremely excited about the future of Azure Container Apps. As I’ve said I think this technology will really take off once it’s fully adopted by the community. This post has targeted the approach to deploy all the resources you need to get started with a container app. I’ve also explained how to configure the Bicep files so each resource can read and store secrets in a secure way where applicable. I’ll plan to write another post which will be more of a deeper dive into the capabilities of Azure Container Apps… stay tuned! Learn more about how Xpirit can help you transform your business !Verfasst von

Esteban Garcia
Managing Director at Xebia Microsoft Services US and a recognized expert in DevOps, GitHub Advanced Security, and GitHub Copilot. As a Microsoft Regional Director (RD) and Most Valuable Professional (MVP), he leads his team in adopting cutting-edge Microsoft technologies to enhance client services across various industries. Esteemed for his contributions to the tech community, Esteban is a prominent speaker and advocate for innovative software development and security solutions.
Contact