🦐

【Bicep】PowerShellからデプロイするときに詰まったポイントまとめ

に公開

はじめに

BicepからAzureリソースを構築しようとしました。
az deployment group create コマンドでデプロイするときに、上手くデプロイできない場面が複数あったため共有します。

環境

  • Windows 11
  • PowerShell
  • Azure CLI
ディレクトリ構成
Iac/
├─ deployments/
│    └─ main.bicep
└─ modules/
└─ vnet.bicep, appservice.bicep, etc...

つまづいたポイント

1. Bash と PowerShell の違い

よく紹介されているコマンド例は Bash 前提だった。

az deployment group create \
-g MyResourceGroup \
-f ./main.bicep \
-p storageAccountName=mystorage namePrefix=demo

これをそのまま PowerShell で実行すると…

  • \ が認識されない(PowerShellでは改行はバッククォート ` )
  • | がパイプとして解釈されてしまう (NODE|18-lts → エラー)

結果 → '-g' はコマンドレットではありません'18-lts' は内部コマンドではありません のエラー。

2. ディレクトリ移動の二重実行

シンプルなミス。
すでに Iac/deployments にいるのに、さらに cd .\deployments を実行。
→ パスが Iac/deployments/deployments となり「フォルダが存在しない」エラー。

3. PowerShell の引数解釈

Azure CLI では --parameters @file.json が正しい文法ですが、PowerShell では @ が配列リテラルとして解釈されてしまいパースエラー。

# NG
--parameters @.\parameters.dev.json

# OK(ダブルクォートで囲む)
--parameters "@.\parameters.dev.json"

また、PowerShell のハッシュテーブル (@{}) を直接渡すのも不可。

$psParams = @{
  storageAccountName = 'mystorage'
}
az deployment group create --parameters $psParams
# → Unable to parse parameter: System.Collections.Hashtable

解決策

方法1: JSON パラメータファイルを使う

parameters.dev.jsonファイルをdeploymentsに追加し、下記コマンドを実行する

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": { "value": "mystorage12345" },
    "namePrefix": { "value": "demo" },
    "webAppName": { "value": "demo-web" },
    "appServicePlanSku": { "value": "B1" },
    "linuxFxVersion": { "value": "NODE|18-lts" }
  }
}

コマンド:

az deployment group create `
  --resource-group MyResourceGroup `
  --template-file .\main.bicep `
  --parameters "@.\parameters.dev.json"

なぜ解決するのか?

PowerShell は @ を配列リテラルとして解釈するが、クォートで囲むことで文字列として渡せる。
JSON ファイルは Azure CLI が直接パースするので、PowerShell の解釈が入らず安全。
複数環境(dev/prod)での切り替えも楽になる。

パースとは

パース(parse)とは

文字列などのデータを解析して、意味のある形に変換すること

今回の場合は:
PowerShellはファイルの中身には一切触らず、"@.\parameters.dev.json" という文字列だけをAzureCLI(az)に渡す。渡されたaz側が、そのJSONファイルを開いて自分で解釈するということになる
参考:https://it-infomation.com/parse/

配列リテラルとは

配列リテラルとは

プログラミングで 配列(Array) を直接書き出すための表記方法のことです。
例えば数字のリストを一気に作りたいときに使います。

PowerShell の場合

PowerShell では @() を使うと配列リテラルになります。

# 配列リテラルの例
$numbers = @(1, 2, 3, 4)

$numbers[0]   # => 1
$numbers[1]   # => 2

また、単に @() だけじゃなく、@ で始まる色々なリテラル表記があります。

  • @() → 配列リテラル
  • @{} → ハッシュテーブルリテラル(連想配列)
  • @' ... '@ → ヒアストリング(複数行文字列)

ここでの詰まりポイント

Azure CLI では「@file.json」と書くと「ファイルを読み込む」という意味。
でも PowerShell では先頭の @ を「配列リテラル」と解釈してしまい、
--parameters @.\parameters.dev.json「CLI にファイルを渡す」 ではなく
**「PowerShell の配列式」**として解釈されてエラーになる。

方法2: PowerShell のパースを止める

az --% deployment group create --resource-group MyResourceGroup --template-file .\main.bicep --parameters linuxFxVersion=NODE|18-lts

なぜ解決するのか?

--% を付けると PowerShell がそれ以降を解析せず、そのまま文字列として CLI に渡す。
そのため | もパイプ扱いされず、CLI に素直に NODE|18-lts が渡る。
ただし --% を使うとコマンド補完や変数展開も効かないので、使いどころは限定的。

方法3: 値を変数に入れて渡す

$fx = "NODE|18-lts"
az deployment group create --resource-group MyResourceGroup --template-file .\main.bicep --parameters linuxFxVersion=$fx

なぜ解決するのか?

NODE|18-lts を変数に格納することで、PowerShell が途中の | をコマンド分割せず、変数展開で安全に CLI に渡せる。
CLI には「NODE|18-lts」という単一の文字列が届く。

まとめ

  • Bash と PowerShell は行継続や記号解釈が違う
  • cd の二重実行でパスが崩れることもある
  • --parameters @file.jsonダブルクォート必須
  • JSONファイルでパラメータ管理するのが一番安定した

おわりに

  • PowerShell で Azure CLI を使うと、CLI の文法とシェルの文法が衝突するのが落とし穴でした。
  • 「どのCUI(PowerShell, Bash, Azure Cloud Shell)」を使うかによってコマンドの書き方が変わる点も学びました。
    今度、T先輩に「Bicepデプロイはどのシェルを使っていますか?」と聞いてみようと思います。
ヘッドウォータース

Discussion