- Đăng vào
Deploy webapp trên Azure bằng ARM Template (Bicep)
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}'