Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Assess and migrate workloads from AWS, GCP, or other clouds to Azure services.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/services/container-apps/cloudrun-deployment-guide.md
1# Deployment: Cloud Run to Container Apps23## Prerequisites45Azure CLI 2.53+, gcloud CLI, Docker, ACR, Key Vault, Log Analytics67## Phase 1: Image Migration89### Bash1011```bash12set -euo pipefail13GCP_PROJECT="${GCP_PROJECT:-<project>}"14GCP_REGION="${GCP_REGION:-<region>}"15ACR_NAME="${ACR_NAME:-<acr>}"1617gcloud auth configure-docker "${GCP_REGION}-docker.pkg.dev"18az acr login --name "$ACR_NAME"19for img in "app:v1" "worker:v1"; do20docker pull "${GCP_REGION}-docker.pkg.dev/${GCP_PROJECT}/<repo>/$img"21docker tag "${GCP_REGION}-docker.pkg.dev/${GCP_PROJECT}/<repo>/$img" "${ACR_NAME}.azurecr.io/$img"22docker push "${ACR_NAME}.azurecr.io/$img"23done24```2526### PowerShell2728```powershell29$GCP_PROJECT = if ($env:GCP_PROJECT) { $env:GCP_PROJECT } else { "<project>" }30$GCP_REGION = if ($env:GCP_REGION) { $env:GCP_REGION } else { "<region>" }31$ACR_NAME = if ($env:ACR_NAME) { $env:ACR_NAME } else { "<acr>" }3233gcloud auth configure-docker "${GCP_REGION}-docker.pkg.dev"34az acr login --name $ACR_NAME35@("app:v1", "worker:v1") | ForEach-Object {36docker pull "${GCP_REGION}-docker.pkg.dev/${GCP_PROJECT}/<repo>/$_"37docker tag "${GCP_REGION}-docker.pkg.dev/${GCP_PROJECT}/<repo>/$_" "${ACR_NAME}.azurecr.io/$_"38docker push "${ACR_NAME}.azurecr.io/$_"39}40```4142## Phase 2: Infrastructure4344> Choose ONE path: basic (without VNet) OR VNet-integrated.4546### Basic (no VNet)4748#### Bash4950```bash51set -euo pipefail52az group create --name "$RG" --location "$LOCATION"53az monitor log-analytics workspace create -g "$RG" -n "${RG}-logs" -l "$LOCATION"54LOG_ID=$(az monitor log-analytics workspace show -g "$RG" -n "${RG}-logs" --query customerId -o tsv)55LOG_KEY=$(az monitor log-analytics workspace get-shared-keys -g "$RG" -n "${RG}-logs" --query primarySharedKey -o tsv)56az containerapp env create -n "${RG}-env" -g "$RG" -l "$LOCATION" \57--logs-workspace-id "$LOG_ID" --logs-workspace-key "$LOG_KEY"58```5960#### PowerShell6162```powershell63az group create --name $RG --location $LOCATION64az monitor log-analytics workspace create -g $RG -n "${RG}-logs" -l $LOCATION65$workspace = az monitor log-analytics workspace show -g $RG -n "${RG}-logs" | ConvertFrom-Json66$keys = az monitor log-analytics workspace get-shared-keys -g $RG -n "${RG}-logs" | ConvertFrom-Json67az containerapp env create -n "${RG}-env" -g $RG -l $LOCATION `68--logs-workspace-id $workspace.customerId --logs-workspace-key $keys.primarySharedKey69```7071### VNet-Integrated7273#### Bash7475```bash76set -euo pipefail77az network vnet create -g "$RG" -n "${RG}-vnet" \78--address-prefix 10.0.0.0/16 --subnet-name aca-subnet --subnet-prefix 10.0.0.0/2379SUBNET_ID=$(az network vnet subnet show -g "$RG" --vnet-name "${RG}-vnet" -n aca-subnet --query id -o tsv)80az containerapp env create -n "${RG}-env" -g "$RG" -l "$LOCATION" \81--logs-workspace-id "$LOG_ID" --logs-workspace-key "$LOG_KEY" \82--infrastructure-subnet-resource-id "$SUBNET_ID"83```8485#### PowerShell8687```powershell88az network vnet create -g $RG -n "${RG}-vnet" `89--address-prefix 10.0.0.0/16 --subnet-name aca-subnet --subnet-prefix 10.0.0.0/2390$subnet = az network vnet subnet show -g $RG --vnet-name "${RG}-vnet" -n aca-subnet | ConvertFrom-Json91az containerapp env create -n "${RG}-env" -g $RG -l $LOCATION `92--logs-workspace-id $workspace.customerId --logs-workspace-key $keys.primarySharedKey `93--infrastructure-subnet-resource-id $subnet.id94```9596## Phase 3: Secrets & Identity9798### Bash99100```bash101set -euo pipefail102az keyvault create --name "$KEY_VAULT" -g "$RG" -l "$LOCATION"103IDENTITY_ID=$(az identity create -n "${RG}-id" -g "$RG" -l "$LOCATION" --query id -o tsv)104PRINCIPAL_ID=$(az identity show --ids "$IDENTITY_ID" --query principalId -o tsv)105106# Grant Key Vault access — use RBAC (recommended) or access policies107# Option A: RBAC (default for new vaults)108KV_ID=$(az keyvault show --name "$KEY_VAULT" --query id -o tsv)109az role assignment create --assignee "$PRINCIPAL_ID" \110--role "Key Vault Secrets User" --scope "$KV_ID"111# Option B: Access policies (if vault uses access-policy mode)112# az keyvault set-policy --name "$KEY_VAULT" --object-id "$PRINCIPAL_ID" --secret-permissions get list113114# Migrate secrets without writing them to disk115az keyvault secret set --vault-name "$KEY_VAULT" --name <secret-name> \116--value "$(gcloud secrets versions access latest --secret=<secret-id> --project="$GCP_PROJECT")"117118# ACR pull access119ACR_ID=$(az acr show --name "$ACR_NAME" --query id -o tsv)120az role assignment create --assignee "$PRINCIPAL_ID" --role AcrPull --scope "$ACR_ID"121```122123### PowerShell124125```powershell126az keyvault create --name $KEY_VAULT -g $RG -l $LOCATION127$identity = az identity create -n "${RG}-id" -g $RG -l $LOCATION | ConvertFrom-Json128$principalId = (az identity show --ids $identity.id | ConvertFrom-Json).principalId129130# Grant Key Vault access — RBAC (recommended)131$kvId = (az keyvault show --name $KEY_VAULT | ConvertFrom-Json).id132az role assignment create --assignee $principalId `133--role "Key Vault Secrets User" --scope $kvId134135# Migrate secrets without writing them to disk136$secretValue = gcloud secrets versions access latest --secret=<secret-id> --project=$GCP_PROJECT137az keyvault secret set --vault-name $KEY_VAULT --name <secret-name> --value $secretValue138Remove-Variable secretValue139140# ACR pull access141$acrId = (az acr show --name $ACR_NAME | ConvertFrom-Json).id142az role assignment create --assignee $principalId --role AcrPull --scope $acrId143```144145## Phase 4: Deploy Container App146147### Bash148149```bash150set -euo pipefail151SECRET_URI=$(az keyvault secret show --vault-name "$KEY_VAULT" --name db-pw --query id -o tsv)152az containerapp create \153--name <app-name> -g "$RG" --environment "${RG}-env" \154--image "${ACR_NAME}.azurecr.io/app:v1" --target-port 8080 --ingress external \155--cpu 1.0 --memory 1Gi --min-replicas 0 --max-replicas 10 \156--user-assigned "$IDENTITY_ID" --registry-identity "$IDENTITY_ID" \157--registry-server "${ACR_NAME}.azurecr.io" \158--secrets db-pw=keyvaultref:"${SECRET_URI}",identityref:"${IDENTITY_ID}" \159--env-vars ENV=prod DB_PASSWORD=secretref:db-pw \160--scale-rule-name http --scale-rule-type http --scale-rule-http-concurrency 80161```162163### PowerShell164165```powershell166$secret = az keyvault secret show --vault-name $KEY_VAULT --name db-pw | ConvertFrom-Json167az containerapp create `168--name <app-name> -g $RG --environment "${RG}-env" `169--image "${ACR_NAME}.azurecr.io/app:v1" --target-port 8080 --ingress external `170--cpu 1.0 --memory 1Gi --min-replicas 0 --max-replicas 10 `171--user-assigned $identity.id --registry-identity $identity.id `172--registry-server "${ACR_NAME}.azurecr.io" `173--secrets "db-pw=keyvaultref:$($secret.id),identityref:$($identity.id)" `174--env-vars "ENV=prod" "DB_PASSWORD=secretref:db-pw" `175--scale-rule-name http --scale-rule-type http --scale-rule-http-concurrency 80176```177178### Configuration Mapping179180| Cloud Run | Container Apps |181|-----------|----------------|182| `--min-instances 0` | `--min-replicas 0` |183| `--max-instances 10` | `--max-replicas 10` |184| `--concurrency 80` | `--scale-rule-http-concurrency 80` |185| `--cpu 1` | `--cpu 1.0` |186| `--memory 512Mi` | `--memory 1Gi` |187188## Phase 5: Validation189190### Bash191192```bash193FQDN=$(az containerapp show --name <app-name> -g "$RG" --query properties.configuration.ingress.fqdn -o tsv)194curl -I "https://$FQDN/health"195az containerapp logs show --name <app-name> -g "$RG" --tail 100196```197198### PowerShell199200```powershell201$app = az containerapp show --name <app-name> -g $RG | ConvertFrom-Json202Invoke-WebRequest -Uri "https://$($app.properties.configuration.ingress.fqdn)/health"203az containerapp logs show --name <app-name> -g $RG --tail 100204```205206## Troubleshooting207208| Issue | Solution |209|-------|----------|210| Image pull fails | Verify ACR role: `az role assignment list --assignee $PRINCIPAL_ID --scope $ACR_ID -o table` |211| App won't start | Check logs: `az containerapp logs show --name <app> -g $RG --tail 100` |212| Secret not accessible | Verify RBAC: `az role assignment list --assignee $PRINCIPAL_ID --scope $KV_ID -o table` |213| Scaling not working | Check config: `az containerapp show --name <app> --query properties.template.scale` |214