The services section is where the real party happens! ๐ This is where you define all the different
pieces of your application - web frontends, APIs, background workers, databases, caches, you name it.
๐ง Smart Auto-Detection
azd app is pretty smart! It auto-detects your language, framework, and how to run your service
based on files in your project directory. You often only need to specify project
and ports!
Service Types
Services come in different flavors depending on what they do:
๐ http
Web servers, APIs, anything with HTTP endpoints. Default when ports are defined.
๐ tcp
Raw TCP connections like databases, Redis, message queues.
โ๏ธ process
Background workers, queue processors. Default when no ports.
๐ณ container
Docker containers. Auto-detected when image is set.
services:
# HTTP service - serves web content
web:
project: ./frontend
ports: ["3000"]
type: http# Default when ports are defined
# TCP service - raw socket connections (databases)
database:
image: postgres:16
ports: ["5432"]
type: tcp
# Process service - runs in background (workers, queues)
worker:
project: ./worker
type: process# Default when no ports defined
# Container service - Docker image
redis:
image: redis:7
type: container# Auto-detected when 'image' is set
Service Modes
Modes determine how azd app manages the service lifecycle:
๐ daemon (default)
Long-running process that stays up. Most services use this.
๐ watch
Continuous file watcher (tsc --watch, nodemon). Monitors output for health.
Configure custom URLs for accessing your services through the local and azure configuration objects. These URLs are used when the actual access point differs from the auto-discovered service URL.
Property
Type
Context
Writable
Description & Examples
local.url
string
Local dev
Readonly
Auto-discovered local URL (NEVER overridden). Always shows the actual localhost endpoint.
Custom domain name for Azure deployment (domain only, no protocol). Converted to HTTPS URL for display. The original Azure URL is preserved in azure.url.
Can be auto-discovered from Azure resource settings (e.g., App Service custom domain) or set locally in azure.yaml.
Examples: www.contoso.com, api.fabrikam.com
โ ๏ธ Do not include http:// or https://
Common Use Cases
Custom domains: Users access via www.company.com instead of Azure-generated URLs
Development tunnels: Expose local services via ngrok or similar tools
Reverse proxies: Traffic flows through a gateway or load balancer
CDN endpoints: Content delivered via Azure Front Door or Cloudflare
API gateways: APIs accessed through Azure API Management
services:
# Local development with ngrok tunnel
api:
project: ./backend
ports: ["8080"]
local:
customUrl: https://myapi.ngrok.io
# Local URL shown as: https://myapi.ngrok.io
# Auto-discovered: http://localhost:8080
# Production with custom domain and CDN
web:
host: containerapp
project: ./frontend
azure:
customUrl: https://www.mycompany.com
customDomain: www.mycompany.com
# Access URL: https://www.mycompany.com
# Azure deployed to: https://web-abc123.azurecontainerapps.io
# API behind Azure API Management
backend:
host: containerapp
project: ./api
azure:
customUrl: https://api.mycompany.com
customDomain: api.mycompany.com
# Access URL: https://api.mycompany.com
# Azure deployed to: https://backend-xyz789.azurecontainerapps.io
# Both local tunnel and production custom domain
fullstack:
host: appservice
project: ./app
local:
customUrl: https://app.ngrok.io
azure:
customUrl: https://app.company.com
customDomain: app.company.com
# Local: https://app.ngrok.io
# Azure: https://app.company.com
๐ฏHow It Works: URL Property Design
The system maintains two separate readonly URL properties that preserve the original auto-discovered endpoints. Custom URLs are stored separately and used for display purposes.
Local Development URLs:
local.url - Readonly, always preserves the original auto-discovered URL (e.g., http://localhost:3000)
azure.customDomain - Optional domain name that converts to HTTPS URL (e.g., www.contoso.com โ https://www.contoso.com)
Original Azure URL is never overwritten - both the provisioned endpoint and custom domain are preserved
๐Readonly Properties
The local.url and azure.url properties are readonly and automatically set at runtime.
You cannot directly set these in your azure.yaml. Instead, configure
local.customUrl, azure.customUrl, or
azure.customDomain to provide custom access URLs.
๐กExample: URL Separation
services:
api:
project: ./backend
ports: ["8080"]
local:
customUrl: https://api.ngrok.io
azure:
customDomain: api.mycompany.com
# What happens at runtime:
# Local development (azd app run):
# - local.url = "http://localhost:8080" (auto-discovered, NEVER changes)
# Key Point: Original URLs are ALWAYS preserved alongside custom URLs
โจDisplay Behavior
CLI (azd app info): Shows both "Access URL" (custom) and original URL when they differ
Dashboard: Primary link uses the custom URL; hover/tooltip shows the original provisioned URL
Service Discovery: Environment variables reference the appropriate URL based on context
Logs: Both URLs included in startup messages for clarity and debugging
โ ๏ธImportant Notes
These properties are informational only - they don't configure DNS, SSL certificates, or routing
You must separately configure your infrastructure (custom domains, reverse proxies, CDN, etc.)
customUrl requires full URL with protocol (http:// or https://)
customDomain accepts domain name only (e.g., www.example.com) - can be auto-discovered from Azure or set locally
Used primarily for documentation, UX, and helping developers know both the actual provisioned endpoint and the custom access point
Environment Variable Formats
services:
api:
# Array format (supports secrets)
environment:
- name: NODE_ENV
value: development
- name: DB_PASSWORD
secret: DB_SECRET# Reference to secret
# Object format (simpler, no secrets)
environment:
NODE_ENV: development
API_URL: http://localhost:8080
DEBUG: "true"
โค๏ธHealth Checks
Health checks are how azd app knows when your services are actually ready to accept connections.
No more "Connection refused" errors because you tried to hit your API before it finished starting up! ๐ฏ
๐กPro Tip
Health checks are automatically configured for most services! HTTP services get HTTP health checks,
containers with TCP ports get TCP checks, and process services get process checks. You only need to
customize them if the defaults don't work for you.
Health Check Types
services:
# HTTP health check (default for HTTP services)
api:
ports: ["8080"]
healthcheck:
type: http
path: /health# Default is /health
interval: 30s
timeout: 10s
retries: 3
# TCP health check - checks if port is listening
database:
image: postgres:16
ports: ["5432"]
healthcheck:
type: tcp
interval: 10s
retries: 5
# Process health check - verifies process is running
worker:
project: ./worker
healthcheck:
type: process
interval: 15s
# Output health check - watches stdout for pattern
typescript-watcher:
project: ./frontend
command: tsc --watch
mode: watch
healthcheck:
type: output
pattern: "Found 0 errors\. Watching for file changes"
Run Docker containers alongside your code services! Perfect for databases, caches, Azure emulators,
and any other infrastructure you need during development.
services:
custom-app:
image: myapp:latest# Use existing image
ports: ["8080"]
built-app:
docker:
path: ./Dockerfile# Path to Dockerfile
context: .# Build context
platform: linux/amd64
buildArgs:
- NODE_VERSION=20
- BUILD_ENV=production
registry: myregistry.azurecr.io
image: myapp
tag: v1.0.0
ports: ["8080"]
๐ฆ Container Service Properties
image - Docker image name (makes it a container service)
Build in cloud (Azure Container Registry Tasks) for faster CI/CD
Check out the Container Services Guide for
detailed examples and pre-built container configurations!
โ๏ธresources
Define Azure resources your application uses in production. While this mainly affects deployment,
it's useful for documentation and understanding your app's cloud dependencies.
resources:
# Azure Storage Account
storage:
type: Microsoft.Storage/storageAccounts
# Azure Key Vault
keyvault:
type: Microsoft.KeyVault/vaults
# SQL Server with dependency
sqlserver:
type: Microsoft.Sql/servers
uses:
- keyvault# Depends on key vault
# Existing resource (not provisioned by azd)
existing-db:
type: Microsoft.Sql/servers
existing: true
Resource Properties
type (required) - Azure resource type
uses - Other resources this depends on
existing - Set true for existing resources not provisioned by azd
All Resource Types
Type
Azure Service
Common Uses
azure.servicebus.namespace
Azure Service Bus
Message queues, pub/sub messaging
azure.storage.account
Azure Storage
Blob storage, file shares, queues, tables
azure.cosmos.account
Cosmos DB
NoSQL database, globally distributed
azure.sql.server
Azure SQL Database
Relational database (SQL Server)
azure.keyvault.vault
Azure Key Vault
Secrets, keys, certificates management
azure.eventhub.namespace
Event Hubs
Big data streaming, event ingestion
azure.redis.cache
Azure Cache for Redis
In-memory cache, session storage
azure.search.service
Azure AI Search
Full-text search, vector search
azure.appinsights.account
Application Insights
Monitoring, telemetry, diagnostics
azure.ai.model
Azure AI Model
AI/ML models (OpenAI, etc.)
azure.ai.project
Azure AI Project
AI project workspace
azure.containerapp.environment
Container Apps Environment
Container app infrastructure
azure.aks.cluster
Azure Kubernetes Service
Kubernetes cluster orchestration
azure.container.registry
Azure Container Registry
Private Docker image registry
Common Resource Properties
Property
Type
Required
Description
type
enum
โ Yes
Azure resource type (see table above)
uses
array
No
Names of resources this depends on
existing
boolean
No
true if resource already exists (not provisioned by azd)
props
object
No
Resource-specific properties (varies by type)
โ reqs (Prerequisites)
Define prerequisite tools your project needs. azd app will check for these tools and their versions
before running your application. No more "works on my machine" problems! ๐
reqs:
# Simple version check
- name: node
minVersion: "20.0.0"
# With installation URL override
- name: python
minVersion: "3.11"
installUrl: "https://www.python.org/downloads/"
# Check if tool is running (Docker daemon)
- name: docker
minVersion: "20.0.0"
checkRunning: true
installUrl: "https://docs.docker.com/desktop/"
# Custom version check command
- name: my-tool
minVersion: "2.5.0"
command: my-tool
args: ["version"]
versionPrefix: "v"# Strip 'v' prefix
versionField: 1# Which field has version
installUrl: "https://example.com/install"
# Custom running check
- name: kubernetes
command: kubectl
checkRunning: true
runningCheckCommand: kubectl
runningCheckArgs: ["cluster-info"]
runningCheckExpected: "Kubernetes control plane"
runningCheckExitCode: 0
๐ Built-in Tools
azd app has smart defaults for common tools: node, python, docker, go, java, dotnet, rust, etc.
Just specify the name and minVersion!
๐ ๏ธ Custom Tools
For custom tools, specify how to check the version with command,
args, and parsing options.
All Requirement Properties
Property
Type
Required
Description
name
string
โ Yes
Tool name (node, python, docker, go, etc.)
minVersion
string
No
Minimum required version (semver format)
command
string
No
Command to run for version check (defaults: node --version, python --version, etc.)
args
array
No
Arguments for version command: ["--version"]
versionPrefix
string
No
Prefix to strip from version string (e.g., "v" for "v1.2.3")
versionField
string
No
Field name if version is in JSON output
checkRunning
boolean
No
Also verify tool is running (e.g., Docker daemon)
runningCheckCommand
string
No
Command to check if running
runningCheckArgs
array
No
Arguments for running check command
runningCheckExpected
string
No
Expected substring in output if running
runningCheckExitCode
number
No
Expected exit code if running (default: 0)
installUrl
string
No
URL shown to user for installation instructions
Built-in Tool Names
These tools have automatic version detection and smart defaults:
Control log filtering, classification, and Azure Log Analytics integration. Keep your logs clean and organized!
Basic Logging
logs:
# Filter out noisy logs
filters:
exclude:
- "npm warn"
- "Debugger listening on"
- "ExperimentalWarning"
# Override log levels
classifications:
- text: "DEPRECATED"
level: warning
- text: "fatal"
level: error
- text: "panic"
level: error
Azure Log Analytics Integration
Stream logs from your deployed Azure services (Container Apps, App Service, Functions) directly into your local dashboard with Log Analytics integration. View local and cloud logs in one unified interface.
๐ Complete Azure Logs Guide
See the Azure Cloud Log Streaming reference for detailed setup, dashboard features, troubleshooting, and examples.
# Project-level: Configure polling behavior
logs:
analytics:
pollingInterval: 30s# How often to refresh Azure logs (default: 30s)
defaultTimespan: PT15M# Time range for queries (ISO 8601 duration, default: PT15M)
# Service-level: Specify Log Analytics tables
services:
web:
host: appservice
path: ./src/web
logs:
analytics:
table: AppServiceConsoleLogs# App Service standard table
๐ฏ Next.js frontend with environment variables and tests
๐ FastAPI backend with health checks and Log Analytics
โ๏ธ Python background worker for queue processing
๐ TypeScript compiler in watch mode with output monitoring
๐ PostgreSQL database container with health checks
โก Redis cache for sessions and caching
โ๏ธ Azurite for Azure Storage emulation
โ Prerequisites checking for Node, Docker, and Python
๐ช Lifecycle hooks for setup and notifications
๐ Global logging with filters and Azure Analytics
๐งช Comprehensive testing with coverage tracking
โกQuick Reference
Cheat sheet for the impatient (we don't judge!):
# Property Quick Reference
## Root Properties (All)
### Required
- name - Application name (required)
### Development (azd app)
- services - Service definitions
- reqs - Prerequisites
- hooks - Lifecycle hooks (prerun, postrun)
- logs - Logging configuration
- test - Testing configuration
### Deployment (azd)
- resources - Azure resources
- infra - Infrastructure config (Bicep/Terraform)
- pipeline - CI/CD configuration
- resourceGroup - Override resource group
- requiredVersions - Version constraints
- state - Remote state management
- platform - Dev Center integration
- workflows - Custom command workflows
- cloud - Sovereign cloud selection
- metadata - Custom metadata
## Service Properties
### Core (azd app)
- language - Programming language
- project - Project directory
- entrypoint - Entry file
- command - Run command override
- type - http|tcp|process|container
- mode - daemon|watch|build|task
### Network & Containers
- ports - Port mappings
- image - Docker image
- docker - Build configuration
- environment - Env variables
### Dependencies & Health
- uses - Service/resource dependencies
- healthcheck - Health monitoring
### Configuration (azd app)
- logs - Service logging config
- test - Service test config
### Deployment (azd)
- host - Azure service type (required for deployment)
- resourceGroup - Service resource group
- resourceName - Override resource name
- apiVersion - API version
- module - Infrastructure module
- dist - Deployment artifacts path
- k8s - Kubernetes configuration
- config - Host-specific config
- hooks - Service lifecycle hooks
## Resource Properties
- type - Resource type (required)
- uses - Dependencies
- existing - Is existing resource
- [type-specific] - Container arrays, SKU config, etc.
๐Pro Tips & Tricks
๐ฏ Let Auto-Detection Do Its Thing
Start minimal! azd app will figure out your language, framework, and run commands. Add overrides only when needed.
๐ Use Dependencies Wisely
The uses property ensures services start in the right order.
Your API won't start until the database is healthy!
๐ฅ Health Checks Are Your Friend
Proper health checks prevent race conditions. For watch mode services, use output patterns instead of HTTP checks!
๐ Filter Those Logs
Nobody needs to see "npm warn deprecated" 500 times. Use log filters to keep your output clean and focused!
๐ณ Containers for Infrastructure
Run databases, caches, and Azure emulators as containers. No need to install PostgreSQL on every dev machine!
๐งช Test Early, Test Often
Configure tests in azure.yaml so everyone runs them the same way.
Enforce coverage thresholds to maintain quality!
๐ท๏ธmetadata (Custom Metadata)
Store custom metadata about your application. Commonly used to track template information.
metadata:
template: todo-nodejs-mongo@0.0.1-beta
author: Azure Samples
description: Full-stack application with Node.js and MongoDB
customField: any-value-you-want
The metadata section accepts any custom properties you want to store (additionalProperties: true). Most commonly used to track
which template a project was created from.