Hiện tại mình đang học để thi chứng chỉ AZ-204, trong quá trình học vừa thực hành theo các bài Lab dùng Azure Portal mình cũng tự viết thêm các ARM Template là 1 dạng IaC được sử dụng trên Azure.
Ví dụ này được thực hiện theo Lab 01: Build a web application on Azure platform as a service offering

Tóm tắt
Trong bài lab này nôm na sẽ hướng dẫn chúng ta triển khai một webapp cho phép người dùng xem và upload hình ảnh lên Azure Storage Blob. Ngôn ngữ lập trình sử dụng trong bài Lab này là .NET core.
- Blob Container để lưu hình ảnh (Azure Storage Account)
- API xem và upload hình ảnh (Azure App Service)
- Frontend cho người dùng tương tác (Azure App Service)
Thông thường để dễ dàng quản lý các resource, người ta thường quy định cách đặt tên theo 1 quy tắc nhất quán nào đó. Ví dụ mình xây dựng tên của các resource dựa trên 3 thông số chính
, projectCode
env
và appName
. Các service, resource của mỗi app được gom vào 1 Resource Group riêng tên là ${projectCode}-${env}-rg-${appName}
Mình sử dụng Location là East US
và các lệnh được thực thi trên Azure PowerShell
$projectCode = "az204" $env = "dev" $appName = "lab-01" New-AzDeployment -Location "East US" -env $env -projectCode $projectCode -appName $appName -TemplateFile main.Bicep -Verbose
main.Bicep
targetScope = 'subscription' param appName string param env string param projectCode string param region string = 'eastus' @allowed([ 'Premium_LRS' 'Premium_ZRS' 'Standard_GRS' 'Standard_GZRS' 'Standard_LRS' 'Standard_RAGRS' 'Standard_RAGZRS' 'Standard_ZRS' ]) param storageAccountType string = 'Standard_LRS' //Create the resource group. resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { name: '${projectCode}-${env}-rg-${appName}' location: region } // Create the storage account. module storageAccount './storage-account.bicep' = { name: 'deploy-${projectCode}-${env}-sta-${appName}' params: { appName: appName env: env projectCode: projectCode location: rg.location storageAccountType: storageAccountType } scope: resourceGroup(rg.name) } // Create App Service Plan. module appServicePlan './appservice-plan.bicep' = { name: 'deploy-${projectCode}-${env}-asp-${appName}' params: { appName: appName env: env projectCode: projectCode location: rg.location } scope: resourceGroup(rg.name) } // Create API. module backend './backend-appservice.bicep' = { name: 'deploy-${projectCode}-${env}-app-${appName}-api' params: { appName: appName env: env projectCode: projectCode location: rg.location serverFarmId: appServicePlan.outputs.serverFarmId storageAccountId: storageAccount.outputs.storageAccountId storageAcountApiVersion: storageAccount.outputs.storageAccountApiVersion } scope: resourceGroup(rg.name) } // Create Frontend. module frontend './frontend-appservice.bicep' = { name: 'deploy-${projectCode}-${env}-app-${appName}-web' params: { appName: appName env: env projectCode: projectCode location: rg.location serverFarmId: appServicePlan.outputs.serverFarmId apiUrl: backend.outputs.apiUrl } scope: resourceGroup(rg.name) } output apiUrl string = backend.outputs.apiUrl output frontendUrl string = frontend.outputs.webUrl
storage-account.bicep
targetScope = 'resourceGroup' param appName string param env string param projectCode string param location string = resourceGroup().location param storageAccountType string var storageAccountName = replace('${projectCode}${env}sta${appName}', '-', '') var containerName = 'images' resource sa 'Microsoft.Storage/storageAccounts@2021-06-01' = { name: storageAccountName location: location sku: { name: storageAccountType } kind: 'StorageV2' properties: { accessTier: 'Hot' } } resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2021-06-01' = { name: '${sa.name}/default/${containerName}' properties: { publicAccess: 'Blob' } } output storageAccountId string = sa.id output storageAccountApiVersion string = sa.apiVersion
appservice-plan.bicep
targetScope = 'resourceGroup' param appName string param env string param projectCode string param location string = resourceGroup().location var appServicePlan = '${projectCode}-${env}-asp-${appName}' resource asp 'Microsoft.Web/serverfarms@2022-03-01' = { name: appServicePlan location: location sku: { name: 'F1' tier: 'Free' } } output serverFarmId string = asp.id
backend-appservice.bicep
targetScope = 'resourceGroup' param appName string param env string param projectCode string param location string = resourceGroup().location param serverFarmId string param storageAccountId string param storageAcountApiVersion string var appServiceName = '${projectCode}-${env}-app-${appName}-api' var storageAccountName = replace('${projectCode}${env}sta${appName}', '-', '') resource backendApp 'Microsoft.Web/sites@2022-03-01' = { name: appServiceName location: location identity: { type: 'SystemAssigned' } properties: { serverFarmId: serverFarmId siteConfig: { windowsFxVersion: 'DOTNETCORE|3.1' appSettings: [ { name: 'StorageConnectionString' value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageAccountId, storageAcountApiVersion).keys[0].value}' } ] } httpsOnly: true } } resource zipSourceApi 'Microsoft.Web/sites/extensions@2022-03-01' = { parent: backendApp name: 'MSDeploy' properties: { packageUri: 'https://github.com/MicrosoftLearning/AZ-204-DevelopingSolutionsforMicrosoftAzure/raw/master/Allfiles/Labs/01/Starter/API/api.zip' } } output apiUrl string = 'https://${backendApp.properties.defaultHostName}'
frontend-appservice.bicep
targetScope = 'resourceGroup' param appName string param env string param projectCode string param location string = resourceGroup().location param serverFarmId string param apiUrl string var appServiceName = '${projectCode}-${env}-app-${appName}-web' resource frontendApp 'Microsoft.Web/sites@2022-03-01' = { name: appServiceName location: location identity: { type: 'SystemAssigned' } properties: { serverFarmId: serverFarmId siteConfig: { windowsFxVersion: 'DOTNETCORE|3.1' appSettings: [ { name: 'ApiUrl' value: apiUrl } ] } httpsOnly: true } } resource zipSourceWeb 'Microsoft.Web/sites/extensions@2022-03-01' = { parent: frontendApp name: 'MSDeploy' properties: { packageUri: 'https://github.com/MicrosoftLearning/AZ-204-DevelopingSolutionsforMicrosoftAzure/raw/master/Allfiles/Labs/01/Starter/Web/web.zip' } } output webUrl string = 'https://${frontendApp.properties.defaultHostName}'