この記事では、for
構文を使用してコレクション内の項目を反復処理する方法について説明します。 この機能は、0.3.1 以降でサポートされています。 ループを使用すると、リソース、モジュール、変数、プロパティ、または出力の複数のコピーを定義できます。 ループを使用して、Bicep ファイル内で繰り返し構文を回避し、デプロイ時に作成するコピーの数を動的に設定します。 さまざまな構文を使用して for
する方法のクイック スタートについては、「クイック スタート: Bicep で複数のリソース インスタンスを作成する」を参照してください。
ループを使用して複数のリソースまたはモジュールを作成するには、各インスタンスに name
プロパティの一意の値が必要です。 配列やコレクションのインデックス値や一意な値を使って、名前を作成できます。
トレーニング リソース
ループに関する詳細なガイダンスについては、Microsoft Learn の 条件とループを使用して柔軟な Bicep ファイルをビルド するモジュールを参照してください。
Loop 構文
ループは次の方法で宣言できます。
整数インデックスを使用します。 このオプションは、"この多数のインスタンスを作成します。" というシナリオがある場合に機能します。range 関数は、開始インデックスから始まり、指定された要素の数を含む整数の配列を作成します。 ループ内では、整数インデックスを使用して値を変更できます。 詳細については、「整数インデックス」を参照してください。
[for <index> in range(<startIndex>, <numberOfElements>): { ... }]
配列内の項目の使用: このオプションは、シナリオが "配列内の各要素のインスタンスを作成する" 場合に機能します。ループ内では、現在の配列要素の値を使用して値を変更できます。 詳細については、「配列要素」を参照してください。
[for <item> in <collection>: { ... }]
ディクショナリ オブジェクト内の項目の使用: このオプションは、シナリオが "オブジェクト内の各項目のインスタンスを作成する" 場合に機能します。items 関数は、オブジェクトを配列に変換します。 ループ内では、オブジェクトのプロパティを使用して値を作成できます。 詳細については、「辞書オブジェクト」を参照してください。
[for <item> in items(<object>): { ... }]
整数インデックスと配列内の項目を使用する: このオプションは、シナリオが "配列内の各要素のインスタンスを作成したいが、別の値を作成するには現在のインデックスも必要です" 場合に機能します。詳細については、「ループ配列とインデックス」を参照してください。
[for (<item>, <index>) in <collection>: { ... }]
条件付きデプロイの追加: このオプションは、シナリオが "複数のインスタンスを作成するが、条件が満たされている場合にのみ各インスタンスをデプロイする" 場合に機能します。詳細については、「条件を使用したループ」を参照してください。
[for <item> in <collection>: if(<condition>) { ... }]
ループの制限
Bicep でのループの使用には、次の制限があります。
- Bicep ループは、デプロイの開始時に決定できる値でのみ機能します。
- ループの反復処理に、負の数を指定したり、800 回を超える数を指定したりすることはできません。
- リソースは入れ子になった子リソースとループできないため、子リソースを最上位のリソースに変更します。 詳細については、「 子リソースのイテレーション」を参照してください。
- 複数のプロパティ レベルでループするには、 ラムダ
map
関数を使用します。
整数インデックス
インデックスを使用する簡単な例として、文字列の配列を含む 変数 を作成します。
param itemCount int = 5
var stringArray = [for i in range(0, itemCount): 'item${(i + 1)}']
output arrayResult array = stringArray
出力には、次の値を含む配列が返されます。
[
"item1",
"item2",
"item3",
"item4",
"item5"
]
次の例では、storageCount
パラメーターで指定されているストレージ アカウントの数を作成します。 ストレージ アカウントごとに 3 つのプロパティが返されます。
param ___location string = resourceGroup().___location
param storageCount int = 2
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, storageCount): {
name: '${i}storage${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
output storageInfo array = [for i in range(0, storageCount): {
id: storageAcct[i].id
blobEndpoint: storageAcct[i].properties.primaryEndpoints.blob
status: storageAcct[i].properties.statusOfPrimary
}]
ストレージ アカウント リソース名の作成にインデックス i
が使用されていることに注意してください。
次の例では、モジュールを複数回デプロイします。
param ___location string = resourceGroup().___location
param storageCount int = 2
var baseName = 'store${uniqueString(resourceGroup().id)}'
module stgModule './storageAccount.bicep' = [for i in range(0, storageCount): {
name: '${i}deploy${baseName}'
params: {
storageName: '${i}${baseName}'
___location: ___location
}
}]
output storageAccountEndpoints array = [for i in range(0, storageCount): {
endpoint: stgModule[i].outputs.storageEndpoint
}]
配列要素
次の例では、storageNames
パラメーターで指定された名前ごとに 1 つのストレージ アカウントを作成します。 各リソース インスタンスの name プロパティは一意である必要があります。
param ___location string = resourceGroup().___location
param storageNames array = [
'contoso'
'fabrikam'
'coho'
]
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for name in storageNames: {
name: '${name}${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
次の例では、配列に対して反復処理を行い、プロパティを定義します。 仮想ネットワーク内に 2 つのサブネットを作成します。 サブネット名は一意である必要があります。
param rgLocation string = resourceGroup().___location
var subnets = [
{
name: 'api'
subnetPrefix: '10.144.0.0/24'
}
{
name: 'worker'
subnetPrefix: '10.144.1.0/24'
}
]
resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
name: 'vnet'
___location: rgLocation
properties: {
addressSpace: {
addressPrefixes: [
'10.144.0.0/20'
]
}
subnets: [for subnet in subnets: {
name: subnet.name
properties: {
addressPrefix: subnet.subnetPrefix
}
}]
}
}
配列とインデックス
次の例では、ストレージ アカウントを定義するときに配列要素とインデックス値の両方を使用します。
param storageAccountNamePrefix string
var storageConfigurations = [
{
suffix: 'local'
sku: 'Standard_LRS'
}
{
suffix: 'geo'
sku: 'Standard_GRS'
}
]
resource storageAccountResources 'Microsoft.Storage/storageAccounts@2023-05-01' = [for (config, i) in storageConfigurations: {
name: '${storageAccountNamePrefix}${config.suffix}${i}'
___location: resourceGroup().___location
sku: {
name: config.sku
}
kind: 'StorageV2'
}]
次の例では、配列の要素とインデックスの両方を使用して、新しいリソースに関する情報を出力します。
param ___location string = resourceGroup().___location
param orgNames array = [
'Contoso'
'Fabrikam'
'Coho'
]
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = [for name in orgNames: {
name: 'nsg-${name}'
___location: ___location
}]
output deployedNSGs array = [for (name, i) in orgNames: {
orgName: name
nsgName: nsg[i].name
resourceId: nsg[i].id
}]
辞書オブジェクト
ディクショナリ オブジェクト内の要素を反復処理するには、オブジェクトを配列に変換する items
関数を使用します。
value
プロパティを使用して、オブジェクトのプロパティを取得します。 nsg リソース名は一意である必要があることに注意してください。
param nsgValues object = {
nsg1: {
name: 'nsg-westus1'
___location: 'westus'
}
nsg2: {
name: 'nsg-east1'
___location: 'eastus'
}
}
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = [for nsg in items(nsgValues): {
name: nsg.value.name
___location: nsg.value.___location
}]
条件判定を伴うループ
リソースとモジュールの場合は、ループ構文を含む if
式を追加して、条件に応じてコレクションを展開できます。
次の例では、ループを条件ステートメントと組み合わせて示します。 この例では、モジュールのすべてのインスタンスに 1 つの条件が適用されます。
param ___location string = resourceGroup().___location
param storageCount int = 2
param createNewStorage bool = true
var baseName = 'store${uniqueString(resourceGroup().id)}'
module stgModule './storageAccount.bicep' = [for i in range(0, storageCount): if(createNewStorage) {
name: '${i}deploy${baseName}'
params: {
storageName: '${i}${baseName}'
___location: ___location
}
}]
次の例は、配列内の現在の要素に固有の条件を適用する方法を示しています。
resource parentResources 'Microsoft.Example/examples@2024-06-06' = [for parent in parents: if(parent.enabled) {
name: parent.name
properties: {
children: [for child in parent.children: {
name: child.name
setting: child.settingValue
}]
}
}]
バッチ処理でのデプロイ
Azure リソースは、既定で並列にデプロイされます。 ループを使用して、あるリソースの種類のインスタンスを複数作成すると、それらのインスタンスはすべて同時にデプロイされます。 それらが作成される順序は保証されません。 Bicep ファイル内のリソースの合計制限である 800 個を除き、並列にデプロイされるリソースの数に制限はありません。
あるリソースの種類のすべてのインスタンスを同時に更新したくない場合があるかもしれません。 たとえば、運用環境を更新する場合は、特定の数だけ更新を一度に更新するように、更新をずらす必要がある場合があります。 インスタンスのサブセットをバッチ処理して同時にデプロイするように指定できます。 他のインスタンスは、そのバッチが完了するまで待機します。
リソースのインスタンスを順次デプロイするには、 batchSize
デコレーターを追加します。 値には、同時にデプロイするインスタンスの数を設定します。 依存関係はループ内の以前のインスタンスの間に作成されるため、前のバッチが完了するまで 1 つのバッチは開始されません。
param ___location string = resourceGroup().___location
@batchSize(2)
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, 4): {
name: '${i}storage${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
順次デプロイを行う場合は、バッチ サイズを 1 に設定します。
batchSize
デコレーターは、sys 名前空間にあります。 このデコレーターを同じ名前の別の項目と区別する必要がある場合は、デコレータの前に「sys: @sys.batchSize(2)
」を付けます。
子リソースの反復処理
子リソースの複数のインスタンスを作成するには、次の Bicep ファイルの両方でこのタスクがサポートされています。
入れ子になった子リソース
param ___location string = resourceGroup().___location
resource stg 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: 'examplestorage'
___location: ___location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
resource service 'fileServices' = {
name: 'default'
resource share 'shares' = [for i in range(0, 3): {
name: 'exampleshare${i}'
}]
}
}
最上位レベルの子リソース
resource stg 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: 'examplestorage'
___location: resourceGroup().___location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
}
resource service 'Microsoft.Storage/storageAccounts/fileServices@2023-05-01' = {
name: 'default'
parent: stg
}
resource share 'Microsoft.Storage/storageAccounts/fileServices/shares@2023-05-01' = [for i in range(0, 3): {
name: 'exampleshare${i}'
parent: service
}]
リソース/モジュール コレクションの参照
Azure Resource Manager テンプレート (ARM テンプレート) references
関数は、リソース コレクションのランタイム状態を表すオブジェクトの配列を返します。 Bicep には明示的な references
関数がないため、シンボリック コレクションの使用は直接使用されるため、Bicep はコードの生成中に ARM テンプレート references
関数を利用する ARM テンプレートに変換します。
references
関数を使用してシンボリック コレクションを ARM テンプレートに変換する変換機能では、Bicep CLI バージョン 0.20.X 以降が必要です。 さらに、 bicepconfig.json ファイルで、 symbolicNameCodegen
設定を表示し、 true
に設定する必要があります。
整数インデックスの 2 つのサンプルの出力は、次のように書くことができます。
param ___location string = resourceGroup().___location
param storageCount int = 2
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, storageCount): {
name: '${i}storage${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
output storageInfo array = map(storageAcct, store => {
blobEndpoint: store.properties.primaryEndpoints
status: store.properties.statusOfPrimary
})
output storageAccountEndpoints array = map(storageAcct, store => store.properties.primaryEndpoints)
この Bicep ファイルは、 references
関数を使用する次の ARM JSON テンプレートにトランスパイルされます。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"languageVersion": "1.10-experimental",
"contentVersion": "1.0.0.0",
"parameters": {
"___location": {
"type": "string",
"defaultValue": "[resourceGroup().___location]"
},
"storageCount": {
"type": "int",
"defaultValue": 2
}
},
"resources": {
"storageAcct": {
"copy": {
"name": "storageAcct",
"count": "[length(range(0, parameters('storageCount')))]"
},
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-04-01",
"name": "[format('{0}storage{1}', range(0, parameters('storageCount'))[copyIndex()], uniqueString(resourceGroup().id))]",
"___location": "[parameters('___location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage"
}
},
"outputs": {
"storageInfo": {
"type": "array",
"value": "[map(references('storageAcct', 'full'), lambda('store', createObject('blobEndpoint', lambdaVariables('store').properties.primaryEndpoints, 'status', lambdaVariables('store').properties.statusOfPrimary)))]"
},
"storageAccountEndpoints": {
"type": "array",
"value": "[map(references('storageAcct', 'full'), lambda('store', lambdaVariables('store').properties.primaryEndpoints))]"
}
}
}
前述した ARM JSON テンプレートでは、languageVersion
を 1.10-experimental
に設定する必要があり、リソース要素は配列ではなくオブジェクトである点にご注意ください。
次のステップ
Bicep ファイルを作成する方法については、 Bicep ファイルの構造と構文に関するページを参照してください。