Skip to content

Commit 224d4d2

Browse files
Merge pull request #467 from microsoft/psl-remotpushimage-codmod
feat: Refactor infrastructure parameters and add image build scripts
2 parents cd4b24e + a56cba6 commit 224d4d2

9 files changed

Lines changed: 4464 additions & 310 deletions

docs/CustomizingAzdParameters.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,16 @@ By default this template will use the environment name as the prefix to prevent
1212
| `AZURE_LOCATION` | string | `<User selects during deployment>` | Location of the Azure resources. Controls where the infrastructure will be deployed. |
1313
| `AZURE_ENV_AI_SERVICE_LOCATION` | string | `<User selects during deployment>` | Location of the Azure resources. Controls where the Azure AI Services will be deployed. |
1414
| `AZURE_ENV_MODEL_DEPLOYMENT_TYPE` | string | `GlobalStandard` | Change the Model Deployment Type (allowed values: Standard, GlobalStandard). |
15-
| `AZURE_ENV_GPT_MODEL_NAME` | string | `gpt-4o` | Set the Model Name (allowed values: gpt-4o). |
16-
| `AZURE_ENV_GPT_MODEL_VERSION` | string | `2024-08-06` | Set the Azure model version (allowed values: 2024-08-06) |
15+
| `AZURE_ENV_GPT_MODEL_NAME` | string | `gpt-5.1` | Set the Model Name (allowed values: gpt-5.1). |
16+
| `AZURE_ENV_GPT_MODEL_VERSION` | string | `2025-11-13` | Set the Azure model version (allowed values: 2025-11-13) |
1717
| `AZURE_ENV_GPT_MODEL_CAPACITY` | integer | `150` | Set the Model Capacity (choose a number based on available GPT model capacity in your subscription). |
18-
| `AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID`| string | Guide to get your [Existing Workspace ID](/docs/re-use-log-analytics.md) | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. |
19-
| `AZURE_ENV_IMAGE_TAG` | string | `latest` | Set the Image tag Like (allowed values: latest, dev, hotfix) |
18+
| `AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID`| string | Guide to get your [Existing Workspace ID](re-use-log-analytics.md) | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. |
19+
| `AZURE_ENV_IMAGE_TAG` | string | `latest` | Tag applied to the backend/frontend images that are built remotely and pushed to the deployment's Azure Container Registry. |
2020
| `AZURE_ENV_VM_SIZE` | string | `Standard_D2s_v5` | Specifies the size of the Jumpbox Virtual Machine (e.g., `Standard_D2s_v5`, `Standard_D2s_v4`). Set a custom value if `enablePrivateNetworking` is `true`. |
2121
| `AZURE_ENV_JUMPBOX_ADMIN_USERNAME` | string | `JumpboxAdminUser` | Specifies the administrator username for the Jumpbox Virtual Machine. |
2222
| `AZURE_ENV_JUMPBOX_ADMIN_PASSWORD` | string | `JumpboxAdminP@ssw0rd1234!` | Specifies the administrator password for the Jumpbox Virtual Machine. |
2323
| `AZURE_ENV_COSMOS_SECONDARY_LOCATION` | string | *(not set by default)* | Specifies the secondary region for Cosmos DB. Required if `enableRedundancy` is `true`. |
2424
| `AZURE_EXISTING_AIPROJECT_RESOURCE_ID` | string | *(not set by default)* | Specifies the existing AI Foundry Project Resource ID if it needs to be reused. |
25-
| `AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT`| string | *(not set by default)* | Specifies the Azure Container Registry endpoint to use for container images. |
2625

2726
---
2827

docs/DeploymentGuide.md

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -280,42 +280,59 @@ azd config set provision.preflight off
280280
azd up
281281
```
282282
283+
## Step 5: Build and Push Container Images
284+
### 5.1 Run Image Build Script
285+
286+
1. You can run the ACR build and push script from the project root. Use the appropriate command for your shell:
287+
288+
- For Bash (Linux/macOS/WSL):
289+
290+
```bash
291+
bash scripts/build_and_push_images.sh
292+
```
293+
294+
- For PowerShell (Windows):
295+
296+
```
297+
.\scripts\build_and_push_images.ps1
298+
```
299+
283300
**During deployment, you'll be prompted for:**
284301
1. **Environment name** (e.g., "cmsaapp") - Must be 3-16 characters long, alphanumeric only
285302
2. **Azure subscription** selection
286303
3. **Azure region** - Select a region with available GPT model quota
287304
4. **Resource group** selection (create new or use existing)
288305

289-
**Expected Duration:** 6-9 minutes for default configuration
306+
**Expected Duration:** 9-14 minutes for default configuration (includes remotely building and pushing the container images)
290307

291308
**⚠️ Deployment Issues:** If you encounter errors or timeouts, try a different region as there may be capacity constraints. For detailed error solutions, see our [Troubleshooting Guide](./TroubleShootingSteps.md).
292309

293-
### 4.3 Get Application URL
310+
### 5.2 Get Application URL
294311

295312
After successful deployment:
296313
1. Open [Azure Portal](https://portal.azure.com/)
297314
2. Navigate to your resource group
298315
3. Find the Container App with "frontend" in the name
299316
4. Copy the **Application URI**
300317

301-
⚠️ **Important:** Complete [Post-Deployment Steps](#step-5-post-deployment-configuration) before accessing the application.
318+
⚠️ **Important:** Complete Step 5.1 and Step 6.1 before accessing the application.
302319

303-
## Step 5: Post-Deployment Configuration
320+
## Step 6: Post-Deployment Configuration
304321

305-
### 5.1 Configure Authentication (Required)
322+
### 6.1 Configure Authentication (Required)
306323

307324
**This step is mandatory for application access:**
308325

309326
1. Follow [App Authentication Configuration](./AddAuthentication.md)
310327
2. Wait up to 10 minutes for authentication changes to take effect
311328

312-
### 5.2 Verify Deployment
329+
### 6.2 Verify Deployment
313330

314-
1. Access your application using the URL from Step 4.3
331+
1. Access your application using the URL from Step 5.2
315332
2. Confirm the application loads successfully
316333
3. Verify you can sign in with your authenticated account
317334

318-
### 5.3 Test the Application
335+
### 6.3 Test the Application
319336

320337
Follow the detailed workflow to test the migration functionality:
321338

@@ -329,7 +346,7 @@ Follow the detailed workflow to test the migration functionality:
329346

330347
📖 **Detailed Instructions:** See the complete [Sample Workflow](./SampleWorkflow.md) guide for step-by-step testing procedures.
331348

332-
## Step 6: Clean Up (Optional)
349+
## Step 7: Clean Up (Optional)
333350

334351
### Remove All Resources
335352
```shell

infra/main.bicep

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ param location string = resourceGroup().location
3434
azd : {
3535
type: 'location'
3636
usageName : [
37-
'OpenAI.GlobalStandard.gpt-4o, 150'
37+
'OpenAI.GlobalStandard.gpt-5.1, 150'
3838
]
3939
}
4040
})
@@ -98,19 +98,16 @@ param enableTelemetry bool = true
9898
param deploymentType string = 'GlobalStandard'
9999

100100
@minLength(1)
101-
@description('Optional. Name of the GPT model to deploy. Defaults to gpt-4o.')
102-
param gptModelName string = 'gpt-4o'
101+
@description('Optional. Name of the GPT model to deploy. Defaults to gpt-5.1.')
102+
param gptModelName string = 'gpt-5.1'
103103

104104
@minLength(1)
105-
@description('Optional. Set the Image tag. Defaults to latest_2025-11-10_599.')
106-
param imageTag string = 'latest_2025-11-10_599'
107-
108-
@description('Optional. Azure Container Registry endpoint. Defaults to cmsacontainerreg.azurecr.io')
109-
param containerRegistryEndpoint string = 'cmsacontainerreg.azurecr.io'
105+
@description('Optional. Image tag applied to the backend/frontend images that are built remotely and pushed to the deployment\'s Azure Container Registry by the post-provision script. Defaults to latest.')
106+
param imageTag string = 'latest'
110107

111108
@minLength(1)
112-
@description('Optional. Version of the GPT model to deploy. Defaults to 2024-08-06.')
113-
param gptModelVersion string = '2024-08-06'
109+
@description('Optional. Version of the GPT model to deploy. Defaults to 2025-11-13.')
110+
param gptModelVersion string = '2025-11-13'
114111

115112
@description('Optional. Use this parameter to use an existing AI project resource ID. Defaults to empty string.')
116113
param existingFoundryProjectResourceId string = ''
@@ -897,6 +894,35 @@ module cosmosDb 'modules/cosmosDb.bicep' = {
897894
}
898895
}
899896

897+
// ========== Azure Container Registry ========== //
898+
// A dedicated Azure Container Registry is provisioned with every deployment.
899+
// The container apps are initially created with a public "hello world" placeholder
900+
// image; the post-provision script (scripts/build_and_push_images.*) builds the
901+
// backend/frontend images remotely with 'az acr build', pushes them to this registry,
902+
// and then updates the container apps to run the freshly built images.
903+
var placeholderContainerImage = 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
904+
905+
module containerRegistry 'br/public:avm/res/container-registry/registry:0.12.1' = {
906+
name: take('avm.res.container-registry.registry.${solutionSuffix}', 64)
907+
params: {
908+
#disable-next-line BCP334 // solutionSuffix always yields a name of sufficient length at deployment time
909+
name: take('cr${solutionSuffix}', 50)
910+
location: location
911+
acrSku: enableRedundancy ? 'Premium' : 'Standard'
912+
acrAdminUserEnabled: false
913+
zoneRedundancy: enableRedundancy ? 'Enabled' : 'Disabled'
914+
roleAssignments: [
915+
{
916+
principalId: appIdentity.outputs.principalId
917+
principalType: 'ServicePrincipal'
918+
roleDefinitionIdOrName: 'AcrPull'
919+
}
920+
]
921+
tags: allTags
922+
enableTelemetry: enableTelemetry
923+
}
924+
}
925+
900926
var containerAppsEnvironmentName = 'cae-${solutionSuffix}'
901927

902928
module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.13.1' = {
@@ -953,10 +979,17 @@ module containerAppBackend 'br/public:avm/res/app/container-app:0.22.0' = {
953979
appIdentity.outputs.resourceId
954980
]
955981
}
982+
registries: [
983+
{
984+
server: containerRegistry.outputs.loginServer
985+
identity: appIdentity.outputs.resourceId
986+
}
987+
]
956988
containers: [
957989
{
958990
name: 'cmsabackend'
959-
image: '${containerRegistryEndpoint}/cmsabackend:${imageTag}'
991+
// Placeholder image; replaced with the ACR image by scripts/build_and_push_images.*
992+
image: placeholderContainerImage
960993
env: concat(
961994
[
962995
{
@@ -1133,6 +1166,12 @@ module containerAppFrontend 'br/public:avm/res/app/container-app:0.22.0' = {
11331166
appIdentity.outputs.resourceId
11341167
]
11351168
}
1169+
registries: [
1170+
{
1171+
server: containerRegistry.outputs.loginServer
1172+
identity: appIdentity.outputs.resourceId
1173+
}
1174+
]
11361175
containers: [
11371176
{
11381177
env: [
@@ -1145,7 +1184,8 @@ module containerAppFrontend 'br/public:avm/res/app/container-app:0.22.0' = {
11451184
value: 'prod'
11461185
}
11471186
]
1148-
image: '${containerRegistryEndpoint}/cmsafrontend:${imageTag}'
1187+
// Placeholder image; replaced with the ACR image by scripts/build_and_push_images.*
1188+
image: placeholderContainerImage
11491189
name: 'cmsafrontend'
11501190
resources: {
11511191
cpu: 1
@@ -1202,3 +1242,18 @@ output PICKER_AGENT_MODEL_DEPLOY string = modelDeployment.name
12021242
output FIXER_AGENT_MODEL_DEPLOY string = modelDeployment.name
12031243
output SEMANTIC_VERIFIER_AGENT_MODEL_DEPLOY string = modelDeployment.name
12041244
output SYNTAX_CHECKER_AGENT_MODEL_DEPLOY string = modelDeployment.name
1245+
1246+
// ========== Container Registry / image build outputs ========== //
1247+
// Consumed by the post-provision script (scripts/build_and_push_images.*) to build
1248+
// and push the application images and update the container apps.
1249+
@description('Login server of the Azure Container Registry provisioned for this deployment.')
1250+
output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer
1251+
@description('Name of the Azure Container Registry provisioned for this deployment.')
1252+
output AZURE_CONTAINER_REGISTRY_NAME string = containerRegistry.outputs.name
1253+
@description('Image tag used when building and pushing the backend/frontend images.')
1254+
output AZURE_ENV_IMAGE_TAG string = imageTag
1255+
@description('Name of the backend container app to update with the freshly built image.')
1256+
output BACKEND_CONTAINER_APP_NAME string = containerAppBackend.outputs.name
1257+
@description('Name of the frontend container app to update with the freshly built image.')
1258+
output FRONTEND_CONTAINER_APP_NAME string = containerAppFrontend.outputs.name
1259+

0 commit comments

Comments
 (0)