スキル一覧に戻る
pascalvanderheiden

azd-deployment

by pascalvanderheiden

A list of re-useable agent skills I created for my own purpose.

0🍴 0📅 2026年1月20日
GitHubで見るManusで実行

SKILL.md


Azure Developer CLI (azd) Deployment

Comprehensive guidance for deploying applications to Azure using the Azure Developer CLI.

Quick Reference

# Initialize project
azd init

# Authenticate
azd auth login

# Provision and deploy
azd up

# Individual steps
azd provision    # Create Azure resources
azd deploy       # Deploy application code

# Environment management
azd env new <name>
azd env select <name>
azd env set <key> <value>
azd env get-values

Project Structure

Every azd project requires this structure:

project-root/
├── azure.yaml              # Service definitions (required)
├── infra/                  # Infrastructure as Code (required)
│   ├── main.bicep          # Main entry point
│   ├── main.parameters.json
│   └── modules/            # Reusable Bicep modules
├── src/                    # Application source code
│   ├── web/                # Frontend (Static Web App)
│   └── api/                # Backend (Container Apps)
├── .azure/                 # Environment configs (auto-generated)
└── scripts/                # Deployment scripts (optional)

azure.yaml Configuration

Basic Structure

name: my-app
metadata:
  template: my-app@1.0.0

services:
  web:
    project: ./src/web
    language: js
    host: staticwebapp
    
  api:
    project: ./src/api
    language: python
    host: containerapp
    docker:
      path: ./Dockerfile
      context: ../

hooks:
  postprovision:
    posix:
      shell: sh
      run: ./scripts/post-provision.sh

Host Types

HostDescriptionUse Case
staticwebappAzure Static Web AppsFrontend SPAs, static sites
containerappAzure Container AppsAPIs, microservices, background jobs
appserviceAzure App ServiceTraditional web apps
functionAzure FunctionsEvent-driven, serverless
aksAzure Kubernetes ServiceComplex container orchestration

Infrastructure as Code (Bicep)

Main Entry Point

Create infra/main.bicep as the deployment entry point:

targetScope = 'subscription'

@minLength(1)
@maxLength(64)
@description('Environment name used for resource naming')
param environmentName string

@minLength(1)
@description('Primary location for all resources')
param location string

@description('Principal ID of the deploying user')
param principalId string = ''

var abbrs = loadJsonContent('./abbreviations.json')
var resourceToken = toLower(uniqueString(subscription().id, environmentName, location))
var tags = { 'azd-env-name': environmentName }

resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = {
  name: 'rg-${environmentName}'
  location: location
  tags: tags
}

module resources './resources.bicep' = {
  name: 'resources'
  scope: rg
  params: {
    location: location
    environmentName: environmentName
    resourceToken: resourceToken
    tags: tags
    principalId: principalId
  }
}

output AZURE_RESOURCE_GROUP string = rg.name
output AZURE_LOCATION string = location
output API_URI string = resources.outputs.apiUri
output WEB_URI string = resources.outputs.webUri

System-Assigned Managed Identity Pattern

Always use System-Assigned Managed Identity with RBAC:

// Container App with System-Assigned Identity
resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  name: 'ca-${resourceToken}'
  location: location
  tags: union(tags, { 'azd-service-name': 'api' })
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    managedEnvironmentId: containerAppEnv.id
    configuration: {
      ingress: {
        external: true
        targetPort: 8000
        transport: 'http'
      }
    }
    template: {
      containers: [
        {
          name: 'api'
          image: 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
          resources: {
            cpu: json('0.5')
            memory: '1Gi'
          }
          env: [
            { name: 'AZURE_CLIENT_ID', value: '' }  // Uses system identity
          ]
        }
      ]
    }
  }
}

RBAC Role Assignments

Assign roles to managed identities (never use connection strings):

// Role definitions
var roles = {
  storageBlobDataContributor: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
  cognitiveServicesOpenAIUser: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'
  searchIndexDataContributor: '8ebe5a00-799e-43f5-93ac-243d3dce84a7'
  keyVaultSecretsUser: '4633458b-17de-408a-b874-0445c86b69e6'
}

// Storage Blob Data Contributor for Container App
resource storageBlobRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(storageAccount.id, containerApp.id, roles.storageBlobDataContributor)
  scope: storageAccount
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roles.storageBlobDataContributor)
    principalId: containerApp.identity.principalId
    principalType: 'ServicePrincipal'
  }
}

// Azure OpenAI User for Container App
resource openAIRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(openAIAccount.id, containerApp.id, roles.cognitiveServicesOpenAIUser)
  scope: openAIAccount
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roles.cognitiveServicesOpenAIUser)
    principalId: containerApp.identity.principalId
    principalType: 'ServicePrincipal'
  }
}

// AI Search Index Data Contributor
resource searchRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(searchService.id, containerApp.id, roles.searchIndexDataContributor)
  scope: searchService
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roles.searchIndexDataContributor)
    principalId: containerApp.identity.principalId
    principalType: 'ServicePrincipal'
  }
}

Firewall Configuration

Configure network security for PostgreSQL and Storage:

// PostgreSQL Flexible Server with firewall rules
resource postgresServer 'Microsoft.DBforPostgreSQL/flexibleServers@2023-12-01-preview' = {
  name: 'psql-${resourceToken}'
  location: location
  tags: tags
  sku: {
    name: 'Standard_B1ms'
    tier: 'Burstable'
  }
  properties: {
    version: '16'
    administratorLogin: 'pgadmin'
    administratorLoginPassword: postgresPassword
    storage: { storageSizeGB: 32 }
    backup: { backupRetentionDays: 7, geoRedundantBackup: 'Disabled' }
    highAvailability: { mode: 'Disabled' }
  }
}

// Allow Azure services to access PostgreSQL
resource postgresFirewallAzure 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2023-12-01-preview' = {
  parent: postgresServer
  name: 'AllowAzureServices'
  properties: {
    startIpAddress: '0.0.0.0'
    endIpAddress: '0.0.0.0'
  }
}

// Storage Account with network rules
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: 'st${resourceToken}'
  location: location
  tags: tags
  kind: 'StorageV2'
  sku: { name: 'Standard_LRS' }
  properties: {
    allowBlobPublicAccess: false
    minimumTlsVersion: 'TLS1_2'
    networkAcls: {
      defaultAction: 'Deny'
      bypass: 'AzureServices'
      virtualNetworkRules: []
      ipRules: []
    }
  }
}

Static Web App with Backend Linking

Link Container Apps as backend API in Static Web Apps:

// Static Web App
resource staticWebApp 'Microsoft.Web/staticSites@2023-12-01' = {
  name: 'stapp-${resourceToken}'
  location: staticWebAppLocation
  tags: union(tags, { 'azd-service-name': 'web' })
  sku: { name: 'Standard', tier: 'Standard' }
  properties: {
    stagingEnvironmentPolicy: 'Enabled'
    allowConfigFileUpdates: true
    enterpriseGradeCdnStatus: 'Disabled'
  }
}

// Link Container App as backend
resource staticWebAppBackend 'Microsoft.Web/staticSites/linkedBackends@2023-12-01' = {
  parent: staticWebApp
  name: 'api-backend'
  properties: {
    backendResourceId: containerApp.id
    region: location
  }
}

Microsoft Foundry Integration

Configure Azure AI Services for LLM access:

// Azure AI Services (Cognitive Services) for Foundry
resource aiServices 'Microsoft.CognitiveServices/accounts@2024-10-01' = {
  name: 'ai-${resourceToken}'
  location: location
  tags: tags
  kind: 'AIServices'
  sku: { name: 'S0' }
  properties: {
    customSubDomainName: 'ai-${resourceToken}'
    publicNetworkAccess: 'Enabled'
  }
}

// Deploy GPT-4o model
resource gpt4oDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = {
  parent: aiServices
  name: 'gpt-4o'
  sku: {
    name: 'GlobalStandard'
    capacity: 10
  }
  properties: {
    model: {
      format: 'OpenAI'
      name: 'gpt-4o'
      version: '2024-11-20'
    }
  }
}

// Deploy text-embedding-3-large
resource embeddingDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = {
  parent: aiServices
  name: 'text-embedding-3-large'
  sku: {
    name: 'Standard'
    capacity: 50
  }
  properties: {
    model: {
      format: 'OpenAI'
      name: 'text-embedding-3-large'
      version: '1'
    }
  }
  dependsOn: [gpt4oDeployment]
}

Azure AI Search Configuration

resource searchService 'Microsoft.Search/searchServices@2024-06-01-preview' = {
  name: 'srch-${resourceToken}'
  location: location
  tags: tags
  sku: { name: 'basic' }
  properties: {
    replicaCount: 1
    partitionCount: 1
    hostingMode: 'default'
    publicNetworkAccess: 'enabled'
    authOptions: {
      aadOrApiKey: {
        aadAuthFailureMode: 'http401WithBearerChallenge'
      }
    }
  }
}

Environment Variables & Outputs

Pass resource information to applications via outputs:

// Outputs automatically become environment variables
output AZURE_AI_SERVICES_ENDPOINT string = aiServices.properties.endpoint
output AZURE_SEARCH_ENDPOINT string = 'https://${searchService.name}.search.windows.net'
output AZURE_STORAGE_ACCOUNT string = storageAccount.name
output POSTGRES_HOST string = postgresServer.properties.fullyQualifiedDomainName
output POSTGRES_DATABASE string = 'appdb'
output API_URI string = 'https://${containerApp.properties.configuration.ingress.fqdn}'
output WEB_URI string = 'https://${staticWebApp.properties.defaultHostname}'

Hooks for Post-Provisioning

Create scripts for tasks after provisioning:

# azure.yaml
hooks:
  postprovision:
    posix:
      shell: sh
      run: ./scripts/post-provision.sh
    windows:
      shell: pwsh
      run: ./scripts/post-provision.ps1

Example post-provision script:

#!/bin/bash
set -e

echo "Running post-provision tasks..."

# Create PostgreSQL database
az postgres flexible-server db create \
  --resource-group "$AZURE_RESOURCE_GROUP" \
  --server-name "$POSTGRES_SERVER_NAME" \
  --database-name "appdb"

# Create storage containers
az storage container create \
  --account-name "$AZURE_STORAGE_ACCOUNT" \
  --name "documents" \
  --auth-mode login

echo "Post-provision complete!"

Deployment Workflow

Standard Workflow

# 1. Initialize (first time only)
azd init

# 2. Authenticate
azd auth login

# 3. Create environment
azd env new dev

# 4. Set any required parameters
azd env set POSTGRES_PASSWORD "$(openssl rand -base64 32)"

# 5. Provision and deploy
azd up

# 6. View outputs
azd env get-values

CI/CD Pipeline (GitHub Actions)

See references/github-actions.md for CI/CD configuration.

Troubleshooting

IssueSolution
Resource not foundRun azd provision to create resources
Permission deniedCheck RBAC role assignments
Connection refusedVerify firewall rules allow Azure services
Identity not configuredEnsure managed identity is enabled
Deployment failedCheck container logs: az containerapp logs show

Resources

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です