こんにちは、臼田です。
みなさん、リモート開発してますか?(挨拶
今回は、以前利用してみたMicrosoft Dev Boxで起動するOSイメージをいい感じにカスタマイズするために、Azure Image Builderと連携させてみました。
以前の記事はこちら
概要
Microsoft Dev BoxはWindowsの開発環境をリモートPCとして作成し、開発者が自由に利用できるサービスです。デフォルトで用意されているイメージを利用することもできますが、組織の中で共通のセットアップをしておけばより楽に利用できます。
というわけで、Microsoft Dev BoxではAzure VM Image Builderを利用してセットアップしたイメージを利用することができます。
Azure VM Image Builder を使用して開発ボックスを構成する – Microsoft Dev Box | Microsoft Learn
今回はこの手順を実施してみます。
やってみた
概ね手順は以下のとおりです。
- 環境準備
- Azure Compute Galleryの作成
- イメージ定義の作成
- イメージテンプレートの作成
- イメージのビルド
- ギャラリーの連携
- DevBoxの作成
詳細な手順には上述した記事から派生して、以下の手順も含まれます。
Azure Compute Gallery を構成する – Microsoft Dev Box | Microsoft Learn
すでにMicrosoft Dev Boxの環境は用意されている前提で進めます。
前半の手順はPowerShellのCLI手順ですが、その一番の理由は、途中に出てくるイメージテンプレートの作成が、現状GUIで実施する手段がなく、APIでしか利用できない点にあります。(知らないとかなりハマります)
環境準備
ここの手順から実施していきます。が、1,2は基本的な環境準備のため不要な場合も多いです。必要な場合のみ実施しましょう。
これから実行するコマンドのための変数を準備していきます。サンプルに習い、今回私の環境では以下のようにしました。リソースグループや作成したい名前に合わせて適宜変更してください。
# Get existing context $currentAzContext = Get-AzContext # Get your current subscription ID $subscriptionID=$currentAzContext.Subscription.Id # Destination image resource group $imageResourceGroup="DevBox-usuda" # Location $location="japaneast" # Image distribution metadata reference name $runOutputName="aibCustWinManImg01" # Image template name $imageTemplateName="vscodeWinTemplate"
以下のようにAzure Cloud Shellにて実行していきます。

以降のコマンドもそのまま流し込みます。
# Set up role definition names, which need to be unique $timeInt=$(get-date -UFormat "%s") $imageRoleDefName="Azure Image Builder Image Def"+$timeInt $identityName="aibIdentity"+$timeInt # Add an Azure PowerShell module to support AzUserAssignedIdentity Install-Module -Name Az.ManagedServiceIdentity # Create an identity New-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName -Location $location $identityNameResourceId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).Id $identityNamePrincipalId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).PrincipalId
Azure Compute Galleryの作成
続いてAzure Compute Galleryを作成します。以下のコマンドで作成します。リージョンやリソース名は適宜変更しましょう。
# Gallery name $galleryName= "devboxGallery" # Image definition name $imageDefName ="vscodeImageDef" # Additional replication region $replRegion2="japanwest" # Create the gallery New-AzGallery -GalleryName $galleryName -ResourceGroupName $imageResourceGroup -Location $location
イメージ定義の作成
イメージを作成するための定義を作成します。
$SecurityType = @{Name='SecurityType';Value='TrustedLaunch'} $features = @($SecurityType) # Create the image definition New-AzGalleryImageDefinition -GalleryName $galleryName -ResourceGroupName $imageResourceGroup -Location $location -Name $imageDefName -OsState generalized -OsType Windows -Publisher 'myCompany' -Offer 'vscodebox' -Sku '1-0-0' -Feature $features -HyperVGeneration "V2"
イメージテンプレートの作成
さてここからが本題です。Dev Boxで利用するためのイメージには以下の条件があります。
コンピューティング ギャラリー イメージの要件 – https://learn.microsoft.com/ja-jp/azure/dev-box/how-to-configure-azure-compute-gallery#compute-gallery-image-requirements
- 第 2 世代
- Hyper-V v2
- Windows OS
- Windows 10 Enterprise バージョン 20H2 以降
- Windows 11 Enterprise バージョン 21H2 以降
- 一般化された VM 画像
- 3 つの sysprep オプション
/generalize /oobe /mode:vm
を使用してイメージを作成する必要があります。 詳細については、「 Sysprep のコマンド ライン オプション」をご覧ください。- 開発ボックスの作成時間を短縮するには:
DISM.exe /Online /Set-ReservedStorageState /State:Disabled
コマンドを使用して、イメージでの、予約済みストレージの状態の機能を無効にします。 詳細については、DISM ストレージの予約コマンド ライン オプションに関するページを参照してください。- イメージ作成時に
defrag
とchkdsk
を実行し、完了するまで待ちます。 そして、スケジュール済みタスクのchkdisk
とdefrag
を無効にします。- 単一セッション VM イメージ (複数セッション VM イメージはサポートされていません。)
- 復旧パーティションはありません。回復パーティションを削除する方法については、Windows Server コマンドの delete partition を参照してください。
- 既定の 64 GB OS ディスク サイズ。OS ディスクのサイズは自動的に、Windows 365 ライセンスの SKU の説明で指定されているサイズに調整されます。
- イメージ定義では、セキュリティの種類としてトラステッド起動が有効になっている必要があります。 セキュリティの種類は、イメージ定義を作成するときに構成します。
今回は手順に従ってイメージを作成します。Windows 11に対してChoco/VScodeをインストールします。カスタマイズする場合にはここを変更するのですが、うまく起動しないことも多いので注意しましょう。
手順にあるテンプレートのJSONをコピーして、作業環境上で適当なファイル名で保存します。
その後、テンプレートを以下のコマンドで置き換えます。ファイル名はよしなに。
$templateFilePath = "mytemplate.txt" (Get-Content -path $templateFilePath -Raw ) -replace '<subscriptionID>',$subscriptionID | Set-Content -Path $templateFilePath (Get-Content -path $templateFilePath -Raw ) -replace '<rgName>',$imageResourceGroup | Set-Content -Path $templateFilePath (Get-Content -path $templateFilePath -Raw ) -replace '<runOutputName>',$runOutputName | Set-Content -Path $templateFilePath (Get-Content -path $templateFilePath -Raw ) -replace '<imageDefName>',$imageDefName | Set-Content -Path $templateFilePath (Get-Content -path $templateFilePath -Raw ) -replace '<sharedImageGalName>',$galleryName| Set-Content -Path $templateFilePath (Get-Content -path $templateFilePath -Raw ) -replace '<region1>',$location | Set-Content -Path $templateFilePath (Get-Content -path $templateFilePath -Raw ) -replace '<region2>',$replRegion2 | Set-Content -Path $templateFilePath ((Get-Content -path $templateFilePath -Raw) -replace '<imgBuilderId>',$identityNameResourceId) | Set-Content -Path $templateFilePath
置き換えたらテンプレートを作成します。
New-AzResourceGroupDeployment -ResourceGroupName $imageResourceGroup -TemplateFile $templateFilePath -Api-Version "2020-02-14" -imageTemplateName $imageTemplateName -svclocation $location
イメージのビルド
イメージテンプレートが作成できたら実際にビルドします。以下のコマンドを実行します。
Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $imageResourceGroup -ResourceType Microsoft.VirtualMachineImages/imageTemplates -ApiVersion "2020-02-14" -Action Run
実行確認が出てくるので進めます。

正常に通ると以下のようにポータルでもビルドの開始が確認できます。

結構時間がかかりますがしばらくすると完了します。ちなみにイメージをサンプル以外でカスタマイズしてうまくいかないときは、ここからビルド時のログが確認できるので深堀りしましょう。読み解くにはPackerのログを見る知識も必要です。(N敗)

うまく行っていれば、ギャラリー上にもイメージ定義やイメージ(イメージバージョン)の状態が確認できます。

ギャラリーの連携
イメージが作成できたらギャラリーをDevBoxのデータセンターと連携していきます。デベロッパーセンターのAzure Conmute Galleryから追加します。以降が下記手順です。
Azure Compute Gallery を構成する – Microsoft Dev Box | Microsoft Learn
まずはデベロッパーセンターにユーザー割り当てIDを追加します。こちらの手順を参考にIDを作成します。名前は適当に。

作成したらデベロッパーセンターに追加します。

続いてギャラリーに対するロールの割り当てですが、手順にはGUIで操作する場合自動で割当があると2024/02/18時点で記載がありますが、どうやらうまくいかないようなのでCLI手順と同じこの割り当てを行います。
ギャラリー側のアクセス制御(IAM)から先ほど作成したユーザー割り当てIDを共同作成者とします。こうして、

こうして、

こうです。

割り当てできたら、連携していきましょう。デベロッパーセンターから追加します。

右側でギャラリーを選択して追加。

できました。
DevBoxの作成
これで準備完了です。実際にDev Boxを作成して利用できるか確認しましょう。
Dev Boxの定義を作成します。

ちゃんと追加したギャラリーとイメージが選択できます。

定義が作成できました。続いてプロジェクトのプールでDev Box定義をアタッチしたものを作成します。

先程作成したDev Box定義を選択してよしなに作成します。

出来上がったら、開発者のポータルからDev Boxを作成します。先ほど用意したイメージが選べます。

これまた時間を置いて作成されました。

アクセスしてみます。私はRDPを利用します。

無事アクセスできました。

まとめ
Azure Image Builderを利用して任意で作成したカスタムイメージを、Microsoft Dev Boxで利用してみました。結構長い手順ですが、何よりイメージテンプレートの作成がCLIでしかできないところがハマりポイントです。ボトルネックになるので全部GUIを用意してほしいですね。
イメージ作成部分は難易度が高く、どのような条件でうまくいくのかは私もまだよくわかっていません。とりあえずこの手順であれば成功するのでまとめてみました。
うまくイメージをビルドして快適な環境を作りたいですね。