【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