Subchapter 21.16
references/recipes/azd/azure-yaml.mdMarkdown7 KBView on GitHub
⛔ CRITICAL: Check for .NET Aspire projects FIRST
DO NOT manually create azure.yaml for .NET Aspire projects. If you detect:
- Files ending with
*.AppHost.csproj(e.g., )
MyApp.AppHost.csprojAspire.Hosting or Aspire.AppHost.Sdk in .csproj filesSTOP and use azd init --from-code instead. See aspire.md for details.
Create azure.yaml in project root for AZD.
name: <project-name>
metadata:
template: azd-init
services:
<service-name>:
project: <path-to-source>
language: <python|js|ts|java|dotnet|go>
host: <containerapp|appservice|function|staticwebapp|aks>name: <project-name>
metadata:
template: azd-init
# Specify Terraform as IaC provider
infra:
provider: terraform
path: ./infra
services:
<service-name>:
project: <path-to-source>
language: <python|js|ts|java|dotnet|go>
host: <containerapp|appservice|function|staticwebapp|aks>💡 Tip: Omit
infrasection to use Bicep (default). Addinfra.provider: terraformto use Terraform. See terraform.md for details.
| Host | Azure Service | Use For |
|---|---|---|
containerapp | Container Apps | APIs, microservices, workers |
appservice | App Service | Traditional web apps |
function | Azure Functions | Serverless functions |
staticwebapp | Static Web Apps | SPAs, static sites |
aks | AKS | Kubernetes workloads |
name: myapp
services:
api:
project: ./src/api
language: python
host: containerapp
docker:
path: ./src/api/Dockerfilename: myapp
infra:
provider: terraform
path: ./infra
services:
api:
project: ./src/api
language: python
host: containerapp
docker:
path: ./src/api/DockerfileWhen a non-Aspire project has a Dockerfile that expects files relative to a specific directory:
name: myapp
services:
ginapp:
project: .
host: containerapp
image: ginapp
docker:
path: ginapp/Dockerfile
context: ginapp💡 Tip: The
contextfield specifies the Docker build context directory. This is crucial for:
- Dockerfiles with
COPYcommands expecting files relative to a subdirectory- Multi-service repos where each service has its own context
⚠️ Aspire projects: Do NOT manually add per-service entries with
docker.contextfor AspireAddDockerfile()resources. Aspire handles container builds at runtime through the AppHost. The generatedazure.yamlshould contain only a singleappservice pointing to the AppHost. See aspire.md for details.
⚠️ Language Field: When using the
dockersection, thelanguagefield should be omitted or set to the language that azd will use for framework-specific behaviors. For containerized apps with custom Dockerfiles, the language is not used by azd since the build is handled by Docker. Only includelanguageif you need azd to perform additional framework-specific actions beyond Docker build.
services:
functions:
project: ./src/functions
language: js
host: functionFor React, Vue, Angular, Next.js, etc. that require npm run build:
services:
web:
project: ./src/web # folder containing package.json
language: js # triggers: npm install && npm run build
host: staticwebapp
dist: dist # build output folder (e.g., dist, build, out)For pure HTML sites without a framework build step:
Static files in subfolder (recommended):
services:
web:
project: ./src/web # folder containing index.html
host: staticwebapp
dist: . # works when project != rootStatic files in root - requires build script:
⚠️ SWA CLI Limitation: When
project: ., you cannot usedist: .. Files must be copied to a separate output folder.
Add a minimal package.json with a build script:
{
"scripts": {
"build": "node -e \"require('fs').mkdirSync('public',{recursive:true});require('fs').readdirSync('.').filter(f=>/\\.(html|css|js|png|jpe?g|gif|svg|ico|json|xml|txt|webmanifest|map)$/i.test(f)).forEach(f=>require('fs').copyFileSync(f,'public/'+f))\""
}
}Then configure azure.yaml with language: js to trigger the build:
services:
web:
project: .
language: js # triggers npm install && npm run build
host: staticwebapp
dist: public| Layout | Configuration |
|---|---|
| Static in root | project: ., language: js, dist: public + package.json build script |
| Framework in root | project: ., language: js, dist: <output> |
| Static in subfolder | project: ./path, dist: . |
| Framework in subfolder | project: ./path, language: js, dist: <output> |
Key rules:
distis relative toprojectpath- SWA CLI limitation: When
project: ., cannot usedist: .- must use a distinct folder- For static files in root, add
package.jsonwith build script to copy files to dist folder- Use
language: jsto trigger npm build even for pure static sites in rootlanguage: htmlandlanguage: staticare NOT valid - will fail
Bicep must include the azd-service-name tag:
resource staticWebApp 'Microsoft.Web/staticSites@2022-09-01' = {
name: name
location: location
tags: union(tags, { 'azd-service-name': 'web' })}}
### App Service
```yaml
services:
api:
project: ./src/api
language: dotnet
host: appservicehooks:
preprovision:
shell: sh
run: ./scripts/setup.sh
postprovision:
shell: sh
run: ./scripts/seed-data.sh| Field | Options |
|---|---|
language | python, js, ts, java, dotnet, go (omit for staticwebapp without build) |
host | containerapp, appservice, function, staticwebapp, aks |
docker.path | Path to Dockerfile (relative to project root) |
docker.context | Docker build context directory (optional, defaults to directory containing Dockerfile) |
💡 Docker Context: When
docker.contextis omitted, azd uses the directory containing the Dockerfile as the build context. Specifycontextexplicitly when the Dockerfile expects files from a different directory.
./azure.yaml