1
+ metadata description = 'Creates a container app in an Azure Container App environment.'
1
2
param name string
2
3
param location string = resourceGroup ().location
3
4
param tags object = {}
4
5
6
+ @description ('Allowed origins' )
7
+ param allowedOrigins array = []
8
+
9
+ @description ('Name of the environment for container apps' )
5
10
param containerAppsEnvironmentName string
11
+
12
+ @description ('The name of the container' )
6
13
param containerName string = 'main'
14
+
15
+ @description ('The name of the container registry' )
7
16
param containerRegistryName string
8
17
18
+ @description ('Hostname suffix for container registry. Set when deploying to sovereign clouds' )
19
+ param containerRegistryHostSuffix string = 'azurecr.io'
20
+
9
21
@description ('Minimum number of replicas to run' )
10
22
@minValue (1 )
11
23
param containerMinReplicas int = 1
@@ -20,16 +32,27 @@ param secrets object = {}
20
32
@description ('The environment variables for the container' )
21
33
param env array = []
22
34
35
+ @description ('Specifies if the resource ingress is exposed externally' )
23
36
param external bool = true
24
- param imageName string
25
- param targetPort int = 80
26
37
27
38
@description ('User assigned identity name' )
28
39
param identityName string
29
40
41
+ @description ('The type of identity for the resource' )
42
+ @allowed ([ 'None' , 'SystemAssigned' , 'UserAssigned' ])
43
+ param identityType string = 'None'
44
+
45
+ @description ('The name of the container image' )
46
+ param imageName string
47
+
30
48
@description ('Enabled Ingress for container app' )
31
49
param ingressEnabled bool = true
32
50
51
+ param revisionMode string = 'Single'
52
+
53
+ @description ('The target port for the container' )
54
+ param targetPort int = 80
55
+
33
56
// Dapr Options
34
57
@description ('Enable Dapr' )
35
58
param daprEnabled bool = false
@@ -45,47 +68,53 @@ param containerCpuCoreCount string = '0.5'
45
68
@description ('Memory allocated to a single container instance, e.g. 1Gi' )
46
69
param containerMemory string = '1.0Gi'
47
70
48
- @description ('Workload profile name to use for the container app when using private ingress' )
49
- param workloadProfileName string = 'Warm'
50
-
51
71
var keyvalueSecrets = [for secret in items (secrets ): {
52
72
name : secret .key
53
73
value : secret .value
54
74
}]
55
75
56
- resource userIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
76
+ resource userIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (! empty ( identityName )) {
57
77
name : identityName
58
78
}
59
79
60
- module containerRegistryAccess '../security/registry-access.bicep' = {
80
+ // Private registry support requires both an ACR name and a User Assigned managed identity
81
+ var usePrivateRegistry = !empty (identityName ) && !empty (containerRegistryName )
82
+
83
+ // Automatically set to `UserAssigned` when an `identityName` has been set
84
+ var normalizedIdentityType = !empty (identityName ) ? 'UserAssigned' : identityType
85
+
86
+ module containerRegistryAccess '../security/registry-access.bicep' = if (usePrivateRegistry ) {
61
87
name : '${deployment ().name }-registry-access'
62
88
params : {
63
89
containerRegistryName : containerRegistryName
64
- principalId : userIdentity .properties .principalId
90
+ principalId : usePrivateRegistry ? userIdentity .properties .principalId : ''
65
91
}
66
92
}
67
93
68
- resource app 'Microsoft.App/containerApps@2025-01-01 ' = {
69
- name : name
94
+ resource app 'Microsoft.App/containerApps@2023-05-02-preview ' = {
95
+ name : name
70
96
location : location
71
97
tags : tags
72
98
// It is critical that the identity is granted ACR pull access before the app is created
73
99
// otherwise the container app will throw a provision error
74
100
// This also forces us to use an user assigned managed identity since there would no way to
75
101
// provide the system assigned identity with the ACR pull access before the app is created
76
- dependsOn : [ containerRegistryAccess ]
102
+ dependsOn : usePrivateRegistry ? [ containerRegistryAccess ] : [ ]
77
103
identity : {
78
- type : 'UserAssigned'
79
- userAssignedIdentities : { '${userIdentity .id }' : {} }
104
+ type : normalizedIdentityType
105
+ userAssignedIdentities : ! empty ( identityName ) && normalizedIdentityType == 'UserAssigned' ? { '${userIdentity .id }' : {} } : null
80
106
}
81
107
properties : {
82
108
managedEnvironmentId : containerAppsEnvironment .id
83
109
configuration : {
84
- activeRevisionsMode : 'single'
110
+ activeRevisionsMode : revisionMode
85
111
ingress : ingressEnabled ? {
86
112
external : external
87
113
targetPort : targetPort
88
114
transport : 'auto'
115
+ corsPolicy : {
116
+ allowedOrigins : union ([ 'https://portal.azure.com' , 'https://ms.portal.azure.com' ], allowedOrigins )
117
+ }
89
118
} : null
90
119
dapr : daprEnabled ? {
91
120
enabled : true
@@ -94,12 +123,12 @@ resource app 'Microsoft.App/containerApps@2025-01-01' = {
94
123
appPort : ingressEnabled ? targetPort : 0
95
124
} : { enabled : false }
96
125
secrets : keyvalueSecrets
97
- registries : [
126
+ registries : usePrivateRegistry ? [
98
127
{
99
- server : '${containerRegistry . name }.azurecr.io '
128
+ server : '${containerRegistryName }.${ containerRegistryHostSuffix } '
100
129
identity : userIdentity .id
101
130
}
102
- ]
131
+ ] : []
103
132
}
104
133
template : {
105
134
containers : [
@@ -121,19 +150,14 @@ resource app 'Microsoft.App/containerApps@2025-01-01' = {
121
150
}
122
151
}
123
152
124
- resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-03 -01' existing = {
153
+ resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-05 -01' existing = {
125
154
name : containerAppsEnvironmentName
126
155
}
127
156
128
- // 2022-02-01-preview needed for anonymousPullEnabled
129
- resource containerRegistry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' existing = {
130
- name : containerRegistryName
131
- }
132
-
133
157
output defaultDomain string = containerAppsEnvironment .properties .defaultDomain
158
+ output identityPrincipalId string = userIdentity .properties .principalId
159
+ output identityResourceId string = resourceId ('Microsoft.ManagedIdentity/userAssignedIdentities' , userIdentity .name )
134
160
output imageName string = imageName
135
161
output name string = app .name
136
- output hostName string = app .properties .configuration .ingress .fqdn
137
162
output uri string = ingressEnabled ? 'https://${app .properties .configuration .ingress .fqdn }' : ''
138
- output identityResourceId string = resourceId ('Microsoft.ManagedIdentity/userAssignedIdentities' , userIdentity .name )
139
- output identityPrincipalId string = userIdentity .properties .principalId
163
+ output id string = app .id
0 commit comments