By following a few conventions, the Azure Developer CLI (azd) makes it quick and easy to get up and running on Azure. Applying those conventions to a project and create an azd template is what our team affectionately calls “azdev-ify”.
azd commands are simple but the work azd does under the hood to connect the Azure services and supporting engineer systems, is complex. We want you to focus on business logic for your app. You can say goodbye to going to multiple places and running one-off scripts to stand up Azure resources. Everything is automatable and repeatable. You get a sample CI/CD pipeline set up. If Azure Monitor is included in the template infrastructure, you can even observe and analyze your application health!
To “azdev-ify" your project, it’s important to first understand how azd works. As PM for the tool, I am often asked what exactly the minimum is to get started. This is the first of a series of blog posts that focus on stepping through the process of making a simple Python app azd compatible.
So, let’s get started!
An azd compatible project follows azd conventions. At the minimum, an azd-compatible repository must have the following:
The infra folder contains the infrastructure as code (IaC) files you need to provision the Azure resources.
Update(11/2/2022): this blog post was originally published on Oct 12, 2022 (based on azd version 0.3.0-beta.2.) It has since been updated to sync with azd version 0.4.0-beta.1.
Let us take a moment to examine the folder content of our Todo azd templates:
Let's start with something simple - TheCatSaidNo. To deploy this app to Azure, you need an Azure App Service with built-in language for Python.
To run it locally:
git clone https://github.com/luabud/TheCatSaidNo
cd thecatsaidno
py -m venv .venv
.venv\scripts\activate
pip3 install -r ./requirements.txt
flask run
Before you get started, please make sure you have azd installed on your development environment. The code used in the blog is based on azd version 0.4.0-beta.1.
To deploy the Azure infrastructure so that your cat can say no:
output AZURE_LOCATION string = location
output AZURE_TENANT_ID string = tenant().tenantId
output REACT_APP_WEB_BASE_URL string = web.outputs.uri
targetScope = 'subscription'
@minLength(1)
@maxLength(64)
@description('Name of the the environment which is used to generate a short unique hash used in all resources.')
param environmentName string
@minLength(1)
@description('Primary location for all resources')
param location string
// Optional parameters to override the default azd resource naming conventions. Update the main.parameters.json file to provide values. e.g.,:
// "resourceGroupName": {
// "value": "myGroupName"
// }
param appServicePlanName string = ''
param resourceGroupName string = ''
param webServiceName string = ''
// serviceName is used as value for the tag (azd-service-name) azd uses to identify
param serviceName string = 'web'
@description('Id of the user or app to assign application roles')
param principalId string = ''
var abbrs = loadJsonContent('./abbreviations.json')
var resourceToken = toLower(uniqueString(subscription().id, environmentName, location))
var tags = { 'azd-env-name': environmentName }
// Organize resources in a resource group
resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: !empty(resourceGroupName) ? resourceGroupName : '${abbrs.resourcesResourceGroups}${environmentName}'
location: location
tags: tags
}
// The application frontend
module web './core/host/appservice.bicep' = {
name: serviceName
scope: rg
params: {
name: !empty(webServiceName) ? webServiceName : '${abbrs.webSitesAppService}web-${resourceToken}'
location: location
tags: union(tags, { 'azd-service-name': serviceName })
appServicePlanId: appServicePlan.outputs.id
runtimeName: 'python'
runtimeVersion: '3.8'
scmDoBuildDuringDeployment: true
}
}
// Create an App Service Plan to group applications under the same payment plan and SKU
module appServicePlan './core/host/appserviceplan.bicep' = {
name: 'appserviceplan'
scope: rg
params: {
name: !empty(appServicePlanName) ? appServicePlanName : '${abbrs.webServerFarms}${resourceToken}'
location: location
tags: tags
sku: {
name: 'B1'
}
}
}
// App outputs
output AZURE_LOCATION string = location
output AZURE_TENANT_ID string = tenant().tenantId
output REACT_APP_WEB_BASE_URL string = web.outputs.uri
Important to note serviceName can be anything but must match the service name you specify later in azure.yaml. I am calling my frontend "web".
param serviceName string = 'web'
After running azd init, the azure.yaml file is also added to the root of your project. Think of azure.yaml as the app’s user manual for azd. azd refers to this file to learn more about the app so that it knows, for instance, what Azure service will be hosting your app, how to build and deploy your app.
Open and edit the file. `name` and `services` are the minimum requirements here:
param serviceName string = 'web'
In Azure Portal, if you look at the Azure App Service provisioned in the previous step, you will notice these tags. This is how azd locates the host in the resource group rg-tsn106.
project: .
name: TheCatSaidNo
services:
web:
project: .
language: py
host: appservice
Finally, deploy the app by running: azd deploy.
Time to call the cat over and show her the app running on Azure!
You can get the code for this blog here. Next, setting up Azure Monitor: Part 2 - Observability for your azd-compatible app.
We love your feedback! If you have any comments or ideas, feel free to add a comment or submit an issue to the Azure Developer CLI Repo.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.