共用方式為


在 Bicep 中使用部署指令碼

你可以使用 deploymentScripts 資源在 Bicep 部署中執行腳本並檢視執行結果。 這些腳本幫助你執行以下自訂步驟:

  • 將使用者新增至目錄。
  • 執行資料平面操作;例如,複製 blob 或初始化資料庫。
  • 尋找並驗證許可證金鑰。
  • 建立自我簽署憑證。
  • 在 Microsoft Entra ID 中建立物件。
  • 從自訂系統中尋找 IP 位址區塊。

部署指令碼的優點包括:

  • 它們易於編寫程式碼、使用和偵錯。 您可以在您喜歡的開發環境中編寫部署指令碼。 指令碼可以嵌入到 Bicep 檔案中,也可以嵌入到外部指令碼檔案中。
  • 您可以指定指令碼語言和平台。 目前支援 Linux 環境中的 Azure PowerShell 與 Azure CLI 部署腳本。
  • 您可以允許將命令列引數傳遞至指令碼。
  • 您可以指定指令碼輸出,並將其傳回至部署。

部署指令碼資源僅在 Azure 容器執行個體可用的區域中可用。 欲了解更多資訊,請參閱ACI 的資源可用性與配額限制各區域可供應的產品

警告

部署指令碼服務需要兩個額外的資源來執行和疑難排解指令碼故障:儲存帳戶和容器執行個體。 一般而言,服務會在部署指令碼完成之後清除這些資源。 在移除這些資源之前,您需要承擔這些資源的費用。

欲了解價格資訊,請參閱 Azure 容器實例定價Azure Blob Storage 定價。 若要深入了解,請參閱清除部署指令碼資源

配置最低權限

對於部署指令碼 API 版本 2020-10-01 或更高版本,部署指令碼的執行涉及兩個主體:

  • 部署主體:此主體是用來部署 Bicep 檔案。 它建立底層資源,這些資源是部署腳本資源執行儲存帳號和 Azure 容器實例所需的。 若要配置最小權限原則,請將具有下列屬性的自訂角色指派給部署主體:

    {
      "roleName": "deployment-script-minimum-privilege-for-deployment-principal",
      "description": "Configure least privilege for the deployment principal in deployment script",
      "type": "customRole",
      "IsCustom": true,
      "permissions": [
        {
          "actions": [
            "Microsoft.Storage/storageAccounts/*",
            "Microsoft.ContainerInstance/containerGroups/*",
            "Microsoft.Resources/deployments/*",
            "Microsoft.Resources/deploymentScripts/*"
          ],
        }
      ],
      "assignableScopes": [
        "[subscription().id]"
      ]
    }
    

    如果 Azure Storage 和 Azure Container Instances 資源提供者未註冊,則新增 Microsoft.Storage/register/actionMicrosoft.ContainerInstance/register/action

  • 部署指令碼主體:只有當部署指令碼需要向 Azure 進行驗證並呼叫 Azure CLI 或 PowerShell 時,才需要此原則。 指定部署指令碼主體有兩種方法:

    • 在屬性中指定identity;詳見部署腳本資源語法。 當你指定使用者指派的管理身份時,腳本服務會在呼叫部署腳本前先呼叫 Connect-AzAccount -Identity 。 受管身分必須具有完成指令碼中操作所需的存取權限。 目前,identity 屬性僅支援由使用者指派的管理身分。 若要使用其他身分登錄,請使用清單中的第二種方法。
    • 將服務主體憑證作為安全環境變數傳遞,然後在部署指令碼中呼叫 Connect-AzAccountaz login

    如果使用託管標識,則部署主體需要將內建的託管標識操作員角色指派給託管標識資源。

目前還沒有內建角色專門用來設定部署腳本權限。

建立部署指令碼

以下範例示範了一個包含部署指令碼資源的簡單 Bicep 檔案。 腳本會取一個字串參數並產生另一個字串:

param name string = 'John Dole'
param location string = resourceGroup().location

resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: 'inlineCLI'
  location: location
  kind: 'AzureCLI'
  properties: {
    azCliVersion: '2.52.0'
    arguments: name
    scriptContent: 'echo "The argument is ${name}."; jq -n -c --arg st "Hello ${name}" \'{"text": $st}\' > $AZ_SCRIPTS_OUTPUT_PATH'
    retentionInterval: 'PT1H'
  }
}

output text string = deploymentScript.properties.outputs.text

欲了解更多關於建立部署腳本資源的資訊,請參閱 「在 Bicep 中開發部署腳本」。 為了建立部署腳本資源的腳本,建議建立專用的腳本開發環境,例如 Azure 容器實例或 Docker 映像檔。 指令碼開發並經過全面測試後,您可以從部署指令碼資源整合或呼叫指令碼檔案。 欲了解更多資訊,請參閱 「配置 Bicep 檔案中的部署腳本開發環境」。

將腳本儲存在 inlineScript.bicep 檔案中,然後使用以下腳本部署資源:

$resourceGroupName = Read-Host -Prompt "Enter the name of the resource group to be created"
$location = Read-Host -Prompt "Enter the location (i.e. centralus)"

New-AzResourceGroup -Name $resourceGroupName -Location $location

New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile "inlineScript.bicep"

Write-Host "Press [ENTER] to continue ..."

使用受控識別

以下範例示範如何利用管理身份從部署腳本中與 Azure 互動:

@description('The location of the resources.')
param location string = resourceGroup().location

@description('The storage account to list blobs from.')
param storageAccountData {
  name: string
  container: string
}

@description('The role id of Storage Blob Data Reader.')
var storageBlobDataReaderRoleId = '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1'

@description('The storage account to read blobs from.')
resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' existing = {
  name: storageAccountData.name
}

@description('The Storage Blob Data Reader Role definition from [Built In Roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles).')
resource storageBlobDataReaderRoleDef 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = {
  scope: subscription()
  name: storageBlobDataReaderRoleId
}

@description('The user identity for the deployment script.')
resource scriptIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = {
  name: 'script-identity'
  location: location
}

@description('Assign permission for the deployment scripts user identity access to the read blobs from the storage account.')
resource dataReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  scope: storageAccount
  name: guid(storageBlobDataReaderRoleDef.id, scriptIdentity.id, storageAccount.id)
  properties: {
    principalType: 'ServicePrincipal'
    principalId: scriptIdentity.properties.principalId
    roleDefinitionId: storageBlobDataReaderRoleDef.id
  }
}

@description('The deployment script.')
resource script 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: 'script'
  location: location
  kind: 'AzureCLI'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${scriptIdentity.id}': {}
    }
  }
  properties: {
    azCliVersion: '2.59.0'
    retentionInterval: 'PT1H'
    arguments: '${storageAccount.properties.primaryEndpoints.blob} ${storageAccountData.container}'
    scriptContent: '''
      #!/bin/bash
      set -e
      az storage blob list --auth-mode login --blob-endpoint $1 --container-name $2
    '''
  }
}

監視部署指令碼並對其進行疑難排解

部署一個部署指令碼資源時,需要儲存體帳戶來儲存使用者指令碼、執行結果,以及 stdout 檔案。 您可以指定自己的儲存帳戶。 如需詳細資訊,請參閱使用現有的儲存體帳戶

除了指定自己的儲存帳戶之外,還可以透過設定 cleanupPreference 來代替 OnExpiration。 接著,設定 retentionInterval 持續時間,以允許在移除儲存體帳戶之前有足夠的時間檢閱輸出。 如需詳細資訊,請參閱清除部署指令碼資源

cleanupPreference 屬性新增至上述 Bicep 檔案,並將值設定為 OnExpiration。 預設值是 Always。 此外,將 rentalInterval 設定為 PT1H (一小時) 或更短時間。

param name string = 'John Dole'
param location string = resourceGroup().location

resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: 'inlineCLI'
  location: location
  kind: 'AzureCLI'
  properties: {
    azCliVersion: '2.52.0'
    arguments: name
    scriptContent: 'echo "The argument is ${name}."; jq -n -c --arg st "Hello ${name}" \'{"text": $st}\' > $AZ_SCRIPTS_OUTPUT_PATH'
    cleanupPreference: 'OnExpiration'
    retentionInterval: 'PT1H'
  }
}

output text string = deploymentScript.properties.outputs.text

成功部署 Bicep 檔案後,可以使用 Azure 入口網站、Azure CLI、Azure PowerShell 或 REST API 檢查結果。

Azure 入口網站

部署指令碼資源後,該資源將列在 Azure 入口網站的資源群組下。 概述頁面除了部署指令碼資源外,還列出了兩個支援資源。 保留期限到期後,相關支援資源將被刪除。

請注意,這兩個支援資源的名稱都帶有 azscripts 後綴,因為這些資源是自動建立的。 另一種辨識輔助資源的方法是使用 標籤

部署指令碼資源組的螢幕擷取畫面。

從清單中選擇部署指令碼資源。 部署腳本資源的 概覽 頁面會顯示該資源的重要資訊,包括 配置狀態 以及兩個支援資源: 儲存帳號容器實例記錄區域顯示指令碼的列印文字。

部署指令碼資源資訊的螢幕擷取畫面。

選擇輸出以顯示指令碼的輸出結果。

部署指令碼輸出螢幕擷取畫面。

返回資源群組,選擇儲存帳戶,選擇檔案共享,然後選擇共享名稱後附加 azscripts 的檔案共享。 清單中會出現兩個資料夾:azscriptinputazscriptoutput。 輸出資料夾包含 executionresult.json 檔案和指令碼輸出檔案。 executionresult.json 檔案包含指令碼執行錯誤訊息。 只有指令碼運行成功後才會建立輸出檔。

部署指令碼輸出資料夾內容的螢幕擷取畫面。

輸入資料夾包含系統指令碼檔案和使用者部署指令碼檔案。 您可以將使用者部署指令碼檔案替換為修改後的文件,然後從 Azure 容器執行個體重新執行部署指令碼。

Azure CLI

您可以使用 Azure CLI 管理訂閱或資源群組範圍內的部署指令碼:

命令的輸出應類似此範例:

{
  "arguments": "John Dole",
  "azCliVersion": "2.52.0",
  "cleanupPreference": "OnExpiration",
  "containerSettings": {
    "containerGroupName": null
  },
  "environmentVariables": null,
  "forceUpdateTag": null,
  "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Resources/deploymentScripts/inlineCLI",
  "identity": null,
  "kind": "AzureCLI",
  "location": "centralus",
  "name": "inlineCLI",
  "outputs": {
    "text": "Hello John Dole"
  },
  "primaryScriptUri": null,
  "provisioningState": "Succeeded",
  "resourceGroup": "dsDemo",
  "retentionInterval": "1:00:00",
  "scriptContent": "echo \"The argument is John Dole.\"; jq -n -c --arg st \"Hello John Dole\" '{\"text\": $st}' > $AZ_SCRIPTS_OUTPUT_PATH",
  "status": {
    "containerInstanceId": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.ContainerInstance/containerGroups/jgczqtxom5oreazscripts",
    "endTime": "2023-12-11T20:20:12.149468+00:00",
    "error": null,
    "expirationTime": "2023-12-11T21:20:12.149468+00:00",
    "startTime": "2023-12-11T20:18:26.674492+00:00",
    "storageAccountId": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/jgczqtxom5oreazscripts"
  },
  "storageAccountSettings": null,
  "supportingScriptUris": null,
  "systemData": {
    "createdAt": "2023-12-11T19:45:32.239063+00:00",
    "createdBy": "johndole@contoso.com",
    "createdByType": "User",
    "lastModifiedAt": "2023-12-11T20:18:26.183565+00:00",
    "lastModifiedBy": "johndole@contoso.com",
    "lastModifiedByType": "User"
  },
  "tags": null,
  "timeout": "1 day, 0:00:00",
  "type": "Microsoft.Resources/deploymentScripts"
}

Azure PowerShell

您可以使用 Azure PowerShell 管理訂閱或資源群組範圍內的部署指令碼:

Get-AzDeploymentScript 輸出結果類似以下範例:

Name                : inlinePS
Id                  : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Resources/deploymentScripts/inlinePS
ResourceGroupName   : dsDemo
Location            : centralus
SubscriptionId      : aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e
ProvisioningState   : Succeeded
Identity            :
ScriptKind          : AzurePowerShell
AzPowerShellVersion : 14.0
StartTime           : 12/11/2023 9:45:50 PM
EndTime             : 12/11/2023 9:46:59 PM
ExpirationDate      : 12/11/2023 10:46:59 PM
CleanupPreference   : OnExpiration
StorageAccountId    : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/ee5o4rmoo6ilmazscripts
ContainerInstanceId : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.ContainerInstance/containerGroups/ee5o4rmoo6ilmazscripts
Outputs             :
                      Key                 Value
                      ==================  ==================
                      text                Hello John Dole.

RetentionInterval   : PT1H
Timeout             : P1D

REST API

您可以使用 REST API 取得資源組層級和訂閱層級的部署指令碼資源資訊:

/subscriptions/<SubscriptionID>/resourcegroups/<ResourceGroupName>/providers/microsoft.resources/deploymentScripts/<DeploymentScriptResourceName>?api-version=2020-10-01
/subscriptions/<SubscriptionID>/providers/microsoft.resources/deploymentScripts?api-version=2020-10-01

下列範例會使用 ARMClient。 ARMClient 不是 Microsoft 支援的工具。

armclient login
armclient get /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/myrg/providers/microsoft.resources/deploymentScripts/myDeployementScript?api-version=2020-10-01

輸出結果類似以下範例:

{
  "kind": "AzureCLI",
  "identity": null,
  "location": "centralus",
  "systemData": {
    "createdAt": "2023-12-11T19:45:32.239063+00:00",
    "createdBy": "johndole@contoso.com",
    "createdByType": "User",
    "lastModifiedAt": "2023-12-11T20:18:26.183565+00:00",
    "lastModifiedBy": "johndole@contoso.com",
    "lastModifiedByType": "User"
  },
  "properties": {
    "provisioningState": "Succeeded",
    "azCliVersion": "2.52.0",
    "scriptContent": "echo \"The argument is John Dole.\"; jq -n -c --arg st \"Hello John Dole\" '{\"text\": $st}' > $AZ_SCRIPTS_OUTPUT_PATH",
    "arguments": "John Dole",
    "retentionInterval": "1:00:00",
    "timeout": "1 day, 0:00:00",
    "containerSettings": {
      "containerGroupName": null
    },
    "status": {
      "containerInstanceId": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.ContainerInstance/containerGroups/jgczqtxom5oreazscripts",
      "endTime": "2023-12-11T20:20:12.149468+00:00",
      "error": null,
      "expirationTime": "2023-12-11T21:20:12.149468+00:00",
      "startTime": "2023-12-11T20:18:26.674492+00:00",
      "storageAccountId": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/jgczqtxom5oreazscripts"
    },
    "outputs": {
      "text": "Hello John Dole"
    },
    "cleanupPreference": "OnSuccess"
  },
  "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Resources/deploymentScripts/inlineCLI",
  "type": "Microsoft.Resources/deploymentScripts",
  "name": "inlineCLI",
}

下列 REST API 會傳回記錄:

/subscriptions/<SubscriptionID>/resourcegroups/<ResourceGroupName>/providers/microsoft.resources/deploymentScripts/<DeploymentScriptResourceName>/logs?api-version=2020-10-01

它僅在部署指令碼資源被刪除之前有效。


部署指令碼錯誤程式碼

下表列出了部署指令碼的錯誤代碼:

錯誤碼 描述
DeploymentScriptInvalidOperation Bicep 檔案中的部署指令碼資源定義包含無效的屬性名稱。
DeploymentScriptResourceConflict 如果部署指令碼資源處於非終止狀態且執行時間未超過一小時,則無法刪除該部署指令碼資源。 或者,你不能同時用相同的資源識別碼(相同的訂閱、資源群組名稱和資源名稱)重複執行同一個部署腳本,但腳本內容不同。
DeploymentScriptOperationFailed 部署指令碼操作內部失敗。 聯絡 Microsoft 客服
DeploymentScriptStorageAccountAccessKeyNotSpecified 現有儲存帳戶未指定存取金鑰。
DeploymentScriptContainerGroupContainsInvalidContainers 部署指令碼服務建立的容器群組被外部修改,並新增了無效容器。
DeploymentScriptContainerGroupInNonterminalState 兩個或多個部署指令碼資源在同一資源組中使用相同的 Azure 容器執行個體名稱,其中一個尚未完成執行。
DeploymentScriptExistingStorageNotInSameSubscriptionAsDeploymentScript 部署中提供的現有儲存與指令碼部署所在的訂閱中並不存在。
DeploymentScriptStorageAccountInvalidKind BlobBlobStorageBlobStorage 類型的現有儲存體帳戶不支援檔案共用,因此無法使用。
DeploymentScriptStorageAccountInvalidKindAndSku 現有儲存帳戶不支援文件共用。 如需支援的儲存體帳戶類型清單,請參閱使用現有的儲存體帳戶
DeploymentScriptStorageAccountNotFound 儲存帳戶不存在,或已被外部進程或工具刪除。
DeploymentScriptStorageAccountWithServiceEndpointEnabled 指定的儲存體帳戶具有服務端點。 不支援具有服務端點的儲存體帳戶。
DeploymentScriptStorageAccountInvalidAccessKey 為現有儲存體帳戶指定的存取金鑰不正確。
DeploymentScriptStorageAccountInvalidAccessKeyFormat 儲存帳戶密鑰格式無效。 管理儲存體帳戶存取金鑰
DeploymentScriptExceededMaxAllowedTime 部署指令碼執行時間超過了部署指令碼資源定義中指定的逾時值。
DeploymentScriptInvalidOutputs 部署指令碼輸出不是有效的 JSON 物件。
DeploymentScriptContainerInstancesServiceLoginFailure 使用者指派的託管身分在嘗試登入 10 次 (每次間隔一分鐘) 後仍然無法登入。
DeploymentScriptContainerGroupNotFound 外部工具或程序刪除了部署指令碼服務所建立的容器群組。
DeploymentScriptDownloadFailure 下載支援的指令碼失敗。 查看使用支援指令碼
DeploymentScriptError 使用者指令碼出現錯誤。
DeploymentScriptBootstrapScriptExecutionFailed 啟動程序指令碼出現錯誤。 引導指令碼是協調部署指令碼執行的系統指令碼。
DeploymentScriptExecutionFailed 執行部署指令碼時發生未知錯誤。
DeploymentScriptContainerInstancesServiceUnavailable Azure 容器實例服務在建立容器實例時會拋出「service unavailable」錯誤。
DeploymentScriptContainerGroupInNonterminalState 在建立容器執行個體期間,另一個部署指令碼在相同範圍內使用了相同的容器執行個體名稱(相同的訂閱、資源組名稱和資源名稱)。
DeploymentScriptContainerGroupNameInvalid 指定的容器執行個體名稱不符合 Azure 容器執行個體的要求。 在 Azure 容器執行個體中針對常見問題進行疑難排解

存取私人虛擬網路

您可以透過一些額外的配置在私有網路中執行部署指令碼。 欲了解更多資訊,請參閱從 Bicep 部署腳本存取私人虛擬網路 或透過 私有端點私密執行 Bicep 部署腳本

後續步驟

本文介紹如何使用部署指令碼。 欲探討本文主題,請參閱: