为 ARM 模板中的部署脚本配置开发环境Configure development environment for deployment scripts in ARM templates

了解如何通过部署脚本映像创建用于开发和测试 ARM 模板部署脚本的开发环境。Learn how to create a development environment for developing and testing ARM template deployment scripts with a deployment script image. 你可以创建 Azure 容器实例或使用 DockerYou can either create an Azure container instance or use Docker. 在本文中说明了这两个选项。Both options are covered in this article.

先决条件Prerequisites

Azure PowerShell 容器Azure PowerShell container

如果没有 Azure PowerShell 部署脚本,则可创建包含以下内容的 hello.ps1 文件:If you don't have an Azure PowerShell deployment script, you can create a hello.ps1 file by using the following content:

param([string] $name)
$output = 'Hello {0}' -f $name
Write-Output $output
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['text'] = $output

Azure CLI 容器Azure CLI container

对于 Azure CLI 容器映像,可以创建包含以下内容的 hello.sh 文件:For an Azure CLI container image, you can create a hello.sh file by using the following content:

firstname=$1
lastname=$2
output="{\"name\":{\"displayName\":\"$firstname $lastname\",\"firstName\":\"$firstname\",\"lastName\":\"$lastname\"}}"
echo -n "Hello "
echo $output | jq -r '.name.displayName'

备注

运行 Azure CLI 部署脚本时,名为 AZ_SCRIPTS_OUTPUT_PATH 的环境变量会存储脚本输出文件的位置。When you run an Azure CLI deployment script, an environment variable called AZ_SCRIPTS_OUTPUT_PATH stores the location of the script output file. 环境变量在开发环境容器中不可用。The environment variable isn't available in the development environment container. 有关使用 Azure CLI 输出的详细信息,请参阅使用 CLI 脚本中的输出For more information about working with Azure CLI outputs, see Work with outputs from CLI script.

使用 Azure PowerShell 容器实例Use Azure PowerShell container instance

若要在你的计算机上创建脚本,需要创建一个存储帐户,并将存储帐户装载到容器实例。To author your scripts on your computer, you need to create a storage account and mount the storage account to the container instance. 这样,你就可以将脚本上传到存储帐户,并在容器实例上运行该脚本。So that you can upload your script to the storage account and run the script on the container instance.

备注

为测试你的脚本而创建的存储帐户与部署脚本服务用来执行脚本的存储帐户不是同一个。The storage account that you create to test your script is not the same storage account that the deployment script service uses to execute the script. 部署脚本服务会在每次执行时创建唯一名称作为文件共享。Deployment script service creates a unique name as a file share on every execution.

创建 Azure PowerShell 容器实例Create an Azure PowerShell container instance

以下 Azure 资源管理器模板(ARM 模板)创建一个容器实例和文件共享,然后将文件共享装载到容器映像。The following Azure Resource Manager template (ARM template) creates a container instance and a file share, and then mounts the file share to the container image.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "projectName": {
      "type": "string",
      "metadata": {
        "description": "Specify a project name that is used for generating resource names."
      }
    },
    "containerImage": {
      "type": "string",
      "defaultValue": "mcr.microsoft.com/azuredeploymentscripts-powershell:az5.2",
      "metadata": {
        "description": "Specify the container image."
      }
    },
    "mountPath": {
      "type": "string",
      "defaultValue": "/mnt/azscripts/azscriptinput",
      "metadata": {
        "description": "Specify the mount path."
      }
    }
  },
  "variables": {
    "storageAccountName": "[tolower(concat(parameters('projectName'), 'store'))]",
    "fileShareName": "[concat(parameters('projectName'), 'share')]",
    "containerGroupName": "[concat(parameters('projectName'), 'cg')]",
    "containerName": "[concat(parameters('projectName'), 'container')]"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[variables('storageAccountName')]",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Hot"
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts/fileServices/shares",
      "apiVersion": "2019-06-01",
      "name": "[concat(variables('storageAccountName'), '/default/', variables('fileShareName'))]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ]
    },
    {
      "type": "Microsoft.ContainerInstance/containerGroups",
      "apiVersion": "2019-12-01",
      "name": "[variables('containerGroupName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ],
      "properties": {
        "containers": [
          {
            "name": "[variables('containerName')]",
            "properties": {
              "image": "[parameters('containerImage')]",
              "resources": {
                "requests": {
                  "cpu": 1,
                  "memoryInGb": 1.5
                }
              },
              "ports": [
                {
                  "protocol": "TCP",
                  "port": 80
                }
              ],
              "volumeMounts": [
                {
                  "name": "filesharevolume",
                  "mountPath": "[parameters('mountPath')]"
                }
              ],
              "command": [
                "/bin/sh",
                "-c",
                "pwsh -c 'Start-Sleep -Seconds 1800'"
              ]
            }
          }
        ],
        "osType": "Linux",
        "volumes": [
          {
            "name": "filesharevolume",
            "azureFile": {
              "readOnly": false,
              "shareName": "[variables('fileShareName')]",
              "storageAccountName": "[variables('storageAccountName')]",
              "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value]"
            }
          }
        ]
      }
    }
  ]
}

装载路径的默认值是 /mnt/azscripts/azscriptinputThe default value for the mount path is /mnt/azscripts/azscriptinput. 这是容器实例中将它装载到文件共享的路径。This is the path in the container instance where it's mounted to the file share.

模板中指定的默认容器映像为 mcr.microsoft.com/azuredeploymentscripts-powershell:az5.2。The default container image specified in the template is mcr.microsoft.com/azuredeploymentscripts-powershell:az5.2. 查看所有支持的 Azure PowerShell 版本的列表。See a list of all supported Azure PowerShell versions.

模板在 1,800 秒后暂停容器实例。The template suspends the container instance after 1,800 seconds. 在容器实例进入终端状态并且会话结束之前,你有 30 分钟的时间。You have 30 minutes before the container instance goes into a terminated state and the session ends.

若要部署模板:To deploy the template:

$projectName = Read-Host -Prompt "Enter a project name that is used to generate resource names"
$location = Read-Host -Prompt "Enter the location (i.e. chinaeast)"
$templateFile = Read-Host -Prompt "Enter the template file path and file name"
$resourceGroupName = "${projectName}rg"

New-AzResourceGroup -Location $location -name $resourceGroupName
New-AzResourceGroupDeployment -resourceGroupName $resourceGroupName -TemplateFile $templatefile -projectName $projectName

上传部署脚本Upload the deployment script

将部署脚本上传到存储帐户。Upload your deployment script to the storage account. 以下是 PowerShell 脚本示例:Here's an example of a PowerShell script:

$projectName = Read-Host -Prompt "Enter the same project name that you used earlier"
$fileName = Read-Host -Prompt "Enter the deployment script file name with the path"

$resourceGroupName = "${projectName}rg"
$storageAccountName = "${projectName}store"
$fileShareName = "${projectName}share"

$context = (Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName).Context
Set-AzStorageFileContent -Context $context -ShareName $fileShareName -Source $fileName -Force

你也可使用 Azure 门户或 Azure CLI 来上传文件。You also can upload the file by using the Azure portal or the Azure CLI.

测试部署脚本Test the deployment script

  1. 在 Azure 门户中,打开部署了容器实例和存储帐户的资源组。In the Azure portal, open the resource group where you deployed the container instance and the storage account.

  2. 打开容器组。Open the container group. 默认资源组名称是追加了 cg 的项目名称。The default container group name is the project name appended with cg. 容器实例处于“正在运行”状态。The container instance is in the Running state.

  3. 在资源菜单中,选择“容器”。In the resource menu, select Containers. 容器实例名称是追加了 container 的项目名称。The container instance name is the project name appended with container.

    屏幕截图显示了 Azure 门户中的部署脚本连接容器实例。

  4. 依次选择“连接”、“连接” 。Select Connect, and then select Connect. 如果无法连接到容器实例,请重启容器组,然后重试。If you can't connect to the container instance, restart the container group and try again.

  5. 在控制台窗格中运行以下命令:In the console pane, run the following commands:

    cd /mnt/azscripts/azscriptinput
    ls
    pwsh ./hello.ps1 "John Dole"
    

    输出为 Hello John DoleThe output is Hello John Dole.

    屏幕截图显示了控制台中的部署脚本连接容器实例测试输出。

使用 Azure CLI 容器实例Use an Azure CLI container instance

若要在你的计算机上创建脚本,请创建一个存储帐户,并将存储帐户装载到容器实例。To author your scripts on your computer, create a storage account and mount the storage account to the container instance. 然后,你就可以将脚本上传到存储帐户,并在容器实例上运行该脚本。Then, you can upload your script to the storage account and run the script on the container instance.

备注

为测试你的脚本而创建的存储帐户与部署脚本服务用来执行脚本的存储帐户不是同一个。The storage account that you create to test your script isn't the same storage account that the deployment script service uses to execute the script. 部署脚本服务会在每次执行时创建唯一名称作为文件共享。The deployment script service creates a unique name as a file share on every execution.

创建 Azure CLI 容器实例Create an Azure CLI container instance

以下 ARM 模板创建一个容器实例和文件共享,然后将文件共享装载到容器映像:The following ARM template creates a container instance and a file share, and then mounts the file share to the container image:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "projectName": {
      "type": "string",
      "metadata": {
        "description": "Specify a project name that is used for generating resource names."
      }
    },
    "containerImage": {
      "type": "string",
      "defaultValue": "mcr.microsoft.com/azure-cli:2.9.1",
      "metadata": {
        "description": "Specify the container image."
      }
    },
    "mountPath": {
      "type": "string",
      "defaultValue": "/mnt/azscripts/azscriptinput",
      "metadata": {
        "description": "Specify the mount path."
      }
    }
  },
  "variables": {
    "storageAccountEndPoint": "https://core.chinacloudapi.cn/",
    "storageAccountName": "[tolower(concat(parameters('projectName'), 'store'))]",
    "fileShareName": "[concat(parameters('projectName'), 'share')]",
    "containerGroupName": "[concat(parameters('projectName'), 'cg')]",
    "containerName": "[concat(parameters('projectName'), 'container')]"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[variables('storageAccountName')]",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Hot"
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts/fileServices/shares",
      "apiVersion": "2019-06-01",
      "name": "[concat(variables('storageAccountName'), '/default/', variables('fileShareName'))]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ]
    },
    {
      "type": "Microsoft.ContainerInstance/containerGroups",
      "apiVersion": "2019-12-01",
      "name": "[variables('containerGroupName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ],
      "properties": {
        "containers": [
          {
            "name": "[variables('containerName')]",
            "properties": {
              "image": "[parameters('containerImage')]",
              "resources": {
                "requests": {
                  "cpu": 1,
                  "memoryInGb": 1.5
                }
              },
              "ports": [
                {
                  "protocol": "TCP",
                  "port": 80
                }
              ],
              "volumeMounts": [
                {
                  "name": "filesharevolume",
                  "mountPath": "[parameters('mountPath')]"
                }
              ],
              "command": [
                "/bin/bash",
                "-c",
                "echo hello; sleep 1800"
              ]
            }
          }
        ],
        "osType": "Linux",
        "volumes": [
          {
            "name": "filesharevolume",
            "azureFile": {
              "readOnly": false,
              "shareName": "[variables('fileShareName')]",
              "storageAccountName": "[variables('storageAccountName')]",
              "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value]"
            }
          }
        ]
      }
    }
  ]
}

装载路径的默认值是 /mnt/azscripts/azscriptinputThe default value for the mount path is /mnt/azscripts/azscriptinput. 这是容器实例中将它装载到文件共享的路径。This is the path in the container instance where it's mounted to the file share.

模板中指定的默认容器映像为 mcr.microsoft.com/azure-cli:2.9.1。The default container image specified in the template is mcr.microsoft.com/azure-cli:2.9.1. 查看支持的 Azure CLI 版本的列表。See a list of supported Azure CLI versions.

重要

部署脚本使用 Microsoft 容器注册表 (MCR) 中可用的 CLI 映像。The deployment script uses the available CLI images from Microsoft Container Registry (MCR). 认证部署脚本的 CLI 映像大约需要一个月的时间。It takes about one month to certify a CLI image for a deployment script. 不要使用 30 天内发布的 CLI 版本。Don't use the CLI versions that were released within 30 days. 若要查找映像的发行日期,请参阅 Azure CLI 发行说明To find the release dates for the images, see Azure CLI release notes. 如果使用了不受支持的版本,错误消息中会列出受支持的版本。If you use an unsupported version, the error message lists the supported versions.

模板在 1,800 秒后暂停容器实例。The template suspends the container instance after 1,800 seconds. 在容器实例进入终端状态并且会话结束之前,你有 30 分钟的时间。You have 30 minutes before the container instance goes into a terminal state and the session ends.

若要部署模板:To deploy the template:

$projectName = Read-Host -Prompt "Enter a project name that is used to generate resource names"
$location = Read-Host -Prompt "Enter the location (i.e. chinaeast2)"
$templateFile = Read-Host -Prompt "Enter the template file path and file name"
$resourceGroupName = "${projectName}rg"

New-AzResourceGroup -Location $location -name $resourceGroupName
New-AzResourceGroupDeployment -resourceGroupName $resourceGroupName -TemplateFile $templatefile -projectName $projectName

上传部署脚本Upload the deployment script

将部署脚本上传到存储帐户。Upload your deployment script to the storage account. 下面是一个 PowerShell 示例:The following is a PowerShell example:

$projectName = Read-Host -Prompt "Enter the same project name that you used earlier"
$fileName = Read-Host -Prompt "Enter the deployment script file name with the path"

$resourceGroupName = "${projectName}rg"
$storageAccountName = "${projectName}store"
$fileShareName = "${projectName}share"

$context = (Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName).Context
Set-AzStorageFileContent -Context $context -ShareName $fileShareName -Source $fileName -Force

你也可使用 Azure 门户或 Azure CLI 来上传文件。You also can upload the file by using the Azure portal or the Azure CLI.

测试部署脚本Test the deployment script

  1. 在 Azure 门户中,打开部署了容器实例和存储帐户的资源组。In the Azure portal, open the resource group where you deployed the container instance and the storage account.

  2. 打开容器组。Open the container group. 默认资源组名称是追加了 cg 的项目名称。The default container group name is the project name appended with cg. 容器实例处于“正在运行”状态。The container instance is shown in the Running state.

  3. 在资源菜单中,选择“容器”。In the resource menu, select Containers. 容器实例名称是追加了 container 的项目名称。The container instance name is the project name appended with container.

    部署脚本连接容器实例

  4. 依次选择“连接”、“连接” 。Select Connect, and then select Connect. 如果无法连接到容器实例,请重启容器组,然后重试。If you can't connect to the container instance, restart the container group and try again.

  5. 在控制台窗格中运行以下命令:In the console pane, run the following commands:

    cd /mnt/azscripts/azscriptinput
    ls
    ./hello.sh John Dole
    

    输出为 Hello John DoleThe output is Hello John Dole.

    部署脚本容器实例测试

使用 DockerUse Docker

可以使用预配置的 docker 容器映像作为部署脚本开发环境。You can use a pre-configured Docker container image as your deployment script development environment. 若要安装 Docker,请参阅获取 DockerTo install Docker, see Get Docker. 你还需要配置文件共享以将包含部署脚本的目录装载到 Docker 容器中。You also need to configure file sharing to mount the directory, which contains the deployment scripts into Docker container.

  1. 将部署脚本容器映像拉取到本地计算机:Pull the deployment script container image to the local computer:

    docker pull mcr.microsoft.com/azuredeploymentscripts-powershell:az4.3
    

    此示例使用 PowerShell 4.3.0 版本。The example uses version PowerShell 4.3.0.

    从 MCR 中拉取 CLI 映像:To pull a CLI image from an MCR:

    docker pull mcr.microsoft.com/azure-cli:2.0.80
    

    此示例使用 CLI 2.0.80 版本。This example uses version CLI 2.0.80. 部署脚本使用此处的默认 CLI 容器映像。Deployment script uses the default CLI containers images found here.

  2. 在本地运行 Docker 映像。Run the Docker image locally.

    docker run -v <host drive letter>:/<host directory name>:/data -it mcr.microsoft.com/azuredeploymentscripts-powershell:az4.3
    

    将“<主机驱动器号>”和“<主机目录名>”替换为共享驱动器上的现有文件夹 。Replace <host driver letter> and <host directory name> with an existing folder on the shared drive. 它将文件夹映射到容器中的/data 文件夹。It maps the folder to the /data folder in the container. 例如,要映射 D:\docker:For example, to map D:\docker:

    docker run -v d:/docker:/data -it mcr.microsoft.com/azuredeploymentscripts-powershell:az4.3
    

    -it 意味着使容器映像保持活动状态。-it means keeping the container image alive.

    CLI 示例:A CLI example:

    docker run -v d:/docker:/data -it mcr.microsoft.com/azure-cli:2.0.80
    
  3. 以下屏幕截图显示了如何运行 PowerShell 脚本,假设你在共享驱动器中具有 helloworld.ps1 文件。The following screenshot shows how to run a PowerShell script, given that you have a helloworld.ps1 file in the shared drive.

    资源管理器模板部署脚本 docker cmd

成功测试脚本后,可以将其用作模板中的部署脚本。After the script is tested successfully, you can use it as a deployment script in your templates.

后续步骤Next steps

本教程已介绍部署脚本的用法。In this article, you learned how to use deployment scripts. 完成部署脚本教程:To walk through a deployment script tutorial: