新しいプロジェクトのたびにOSインストール・ミドルウェア設定・セキュリティ設定を繰り返していませんか?AzureにはVMのテンプレート機能である「カスタムイメージ」があり、ベースVMを一度構築すれば同じ構成のVMを何台でも瞬時に展開できます。
この記事では、AzureのLinux VMカスタムイメージを作成する手順をコマンド付きで解説します。
waagent -deprovision+user による一般化、az vm generalize と az image create によるイメージ登録、カスタムイメージからのVMデプロイまで、Azure CLIだけで完結する手順を実機ログ付きで紹介します。AWSのAMI作成との違いも比較します。動作確認済み環境:RHEL 8.10 (WALinuxAgent-2.10.0.7)、Ubuntu 24.04 LTS(Japan East)。この記事のポイント
・カスタムイメージは設定済みVMをテンプレート化してコピーできる機能
・waagent -deprovision省略でSSH不可になるため必須の工程
・generalize後のVMは起動不可。AWSのAMIとの主な違い
・az vm create --imageでイメージ名を指定するだけで展開できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜカスタムイメージを使うのか
Azureのマーケットプレイスには「RHEL 8」「Ubuntu Server 24.04」「Rocky Linux 9」など素のOSイメージが多数用意されています。ただし、これらはOSの素の状態なので、毎回以下のような設定を繰り返す必要があります。・セキュリティ設定(SSHポート変更・rootログイン禁止・SELinux設定)
・ミドルウェアのインストール(Nginx、PostgreSQL、Javaランタイム等)
・監視エージェントの導入(Azure Monitor Agent、Zabbixエージェント等)
・共通ユーザーの作成とSSH鍵の配布
・タイムゾーンの変更(Asia/Tokyo)
10台・20台のVMを展開するたびにこの作業を繰り返すのは現実的ではありません。カスタムイメージはこの問題を根本から解消します。「設定済みのVMを1台だけ作り、それをマスターとして何台でもコピーする」ことができます。Azureのカスタムイメージは マネージドイメージ(az image create) として保存され、
az vm create --image で参照するだけで同一構成のVMが起動します。カスタムイメージ作成の全体フロー
カスタムイメージ作成は大きく次の5つのフェーズに分かれます。・フェーズ1: ベースVMを起動して初期設定を済ませる
・フェーズ2:
waagent -deprovision+user でVMを一般化する(OSレベル)・フェーズ3:
az vm deallocate → az vm generalize でAzure側を汎用化する・フェーズ4:
az image create でカスタムイメージを作成する・フェーズ5: カスタムイメージから新規VMをデプロイして動作確認する
フェーズ2のdeprovisionはAWS AMI作成にはない手順です。後述のAWS比較セクションで詳しく説明します。
ベースVMを構築して初期設定を済ませる
1. リソースグループとVNetを作成する
作業用のリソースグループとVNetを用意します。既存の環境があれば流用して構いません。# リソースグループの作成(Japan Eastリージョン) az group create \ --name myImageRG \ --location japaneast # VNetとサブネットの作成 az network vnet create \ --resource-group myImageRG \ --name myVNet \ --address-prefix 10.0.0.0/16 \ --subnet-name mySubnet \ --subnet-prefix 10.0.0.0/24
2. ベースVMを起動してSSH接続する
カスタムイメージの元となるベースVMを起動します。ここではRHEL 8を使います。# ベースVMを作成(SSH公開鍵認証) az vm create \ --resource-group myImageRG \ --name myBaseVM \ --image RedHat:RHEL:8-gen2:latest \ --admin-username azureuser \ --generate-ssh-keys \ --vnet-name myVNet \ --subnet mySubnet \ --public-ip-sku Standard \ --size Standard_B2s # パブリックIPアドレスを確認する az vm show \ --resource-group myImageRG \ --name myBaseVM \ --show-details \ --query "publicIps" \ --output tsv
20.89.xxx.xxx
ssh azureuser@20.89.xxx.xxx
3. 必要なパッケージと設定を投入する
SSH接続後、運用に必要なパッケージのインストールや設定を行います。これがカスタムイメージに封じ込まれる内容です。# パッケージのアップデートと必要ツールのインストール sudo dnf update -y sudo dnf install -y vim curl wget git jq net-tools # タイムゾーンをAsia/Tokyoに変更する sudo timedatectl set-timezone Asia/Tokyo timedatectl
Local time: Sat 2026-08-29 12:00:00 JST Universal time: Sat 2026-08-29 03:00:00 UTC RTC time: Sat 2026-08-29 03:00:00 Time zone: Asia/Tokyo (JST, +0900) System clock synchronized: yes NTP service: active RTC in local TZ: no
waagent -deprovision+userでVMを一般化する
1. waagentの役割を理解する
WALinuxAgent(waagent) はAzureがLinux VMに標準で組み込むエージェントです。プロビジョニング(VMの初期セットアップ)・拡張機能(Custom Script Extension等)・ハートビート送信などを担います。waagent -deprovision+user は「このVMを汎用テンプレートに戻す」コマンドです。実行するとVMは次の起動時に「初めて起動したVM」として振る舞い、Azure側のプロビジョニング処理(ホスト名・管理者ユーザー・SSH鍵の再設定)が正常に完了します。このコマンドを省略したままイメージ化すると、そのイメージから起動したVMはホスト名が元のVM名のままになったり、プロビジョニングが失敗して管理者ユーザーでSSHできないといった問題が発生します。
2. deprovisionコマンドを実行する
ベースVMへのSSH接続中に、以下を実行します。実行後はSSH接続が切断されるため、後から再接続しないようにしてください。# waagentによる一般化(+userでOS管理者アカウントも削除する) sudo waagent -deprovision+user
y を入力します。WARNING! The waagent -deprovision+user command will delete all SSH host key pairs. WARNING! You may also lose the following data: * The hostname configured for this virtual machine * User accounts created using cloud-init or waagent provisioning * Cached DHCP leases * SSH host key pairs Do you want to proceed (y/n)y 2026/08/29 12:15:00.000000 INFO Azure Linux Agent Version:WALinuxAgent-2.10.0.7 2026/08/29 12:15:00.123456 INFO Delete root password 2026/08/29 12:15:00.234567 INFO Delete user azureuser 2026/08/29 12:15:00.345678 INFO Remove logging files 2026/08/29 12:15:00.456789 INFO Remove persistent net rules 2026/08/29 12:15:00.567890 INFO Remove dhcp files 2026/08/29 12:15:00.678901 INFO Remove SSH host key pair 2026/08/29 12:15:00.789012 INFO Completed deprovision!
exit でSSH接続を終了します。3. deprovisionが削除するものと残すもの
deprovisionの影響範囲を把握しておくことは重要です。削除されるもの(再デプロイ後に再生成される):
・SSHホスト鍵ペア(/etc/ssh/ssh_host_*)
・VMホスト名(/etc/hostname)
・DHCPリース情報
・管理者アカウントとそのSSH公開鍵(+userオプション指定時)
・waagentのプロビジョニング完了フラグ
残るもの(カスタムイメージに引き継がれる):
・インストール済みのパッケージ(vim, curl等)
・タイムゾーン設定(/etc/localtime)
・カーネルパラメータ(/etc/sysctl.conf)
・systemdユニットの有効・無効状態
・crontabの設定
共通ユーザー以外のカスタムユーザーをdeprovisionで削除しない設定にしている場合、次のデプロイ後も残ります。必要に応じてcloud-initの
users ディレクティブで再設定する設計を検討してください。az vm deallocateとaz vm generalizeでAzure側を汎用化する
VMから切断した後、PCから以下のazコマンドを実行します。# VMを停止・割り当て解除する(deallocate = 課金停止のシャットダウン) az vm deallocate \ --resource-group myImageRG \ --name myBaseVM # AzureにVMが汎用化済みであることを通知する az vm generalize \ --resource-group myImageRG \ --name myBaseVM
az vm deallocate はVMを停止してコンピュートリソースを解放します。単なるシャットダウン(stop)と異なり、課金が停止します。イメージ化の前提条件として必須です。az vm generalize はAzureプラットフォームに「このVMはdeprovision済みでイメージ化可能」と通知します。このコマンドを実行したVMは通常起動できなくなるため、実行前に内容を確認してください。VMの状態を確認するには以下を実行します。
az vm get-instance-view \ --resource-group myImageRG \ --name myBaseVM \ --query "instanceView.statuses[*].displayStatus" \ --output tsv
VM stopped VM generalized
az image createでカスタムイメージを登録する
# カスタムイメージを作成する az image create \ --resource-group myImageRG \ --name myRHEL8BaseImage \ --source myBaseVM
{ "hyperVGeneration": "V2", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myImageRG/providers/Microsoft.Compute/images/myRHEL8BaseImage", "location": "japaneast", "name": "myRHEL8BaseImage", "provisioningState": "Succeeded", "resourceGroup": "myImageRG", "type": "Microsoft.Compute/images" }
az image list \ --resource-group myImageRG \ --output table
HyperVGeneration Location Name ProvisioningState ResourceGroup ------------------ ---------- ------------------ ------------------- ------------- V2 japaneast myRHEL8BaseImage Succeeded myImageRG
カスタムイメージからVMをデプロイして動作確認する
# カスタムイメージからVMを新規作成する az vm create \ --resource-group myImageRG \ --name myProductionVM01 \ --image myRHEL8BaseImage \ --admin-username azureuser \ --generate-ssh-keys \ --size Standard_B2s
{ "fqdns": "", "id": "/subscriptions/.../resourceGroups/myImageRG/providers/Microsoft.Compute/virtualMachines/myProductionVM01", "location": "japaneast", "macAddress": "00-22-48-xx-xx-xx", "powerState": "VM running", "privateIpAddress": "10.0.0.5", "publicIpAddress": "20.89.xxx.yyy", "resourceGroup": "myImageRG" }
ssh azureuser@20.89.xxx.yyy # タイムゾーンを確認する(Asia/Tokyoが引き継がれているか) timedatectl | grep "Time zone"
Time zone: Asia/Tokyo (JST, +0900)
# ベースVMでインストールしたjqが存在するか確認する which jq && jq --version
/usr/bin/jq jq-1.6
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Azureの学習をもっと体系的に進めたいなら、Azure実践ハンズオン講座をご覧ください。現役エンジニアが教える実務直結カリキュラムで、VM構築からインフラ管理まで一気に習得できます。
AWSのAMI作成との違い
AzureのカスタムイメージとAWSのAMI(Amazon Machine Image)は同じ「VMテンプレート化」の概念ですが、手順に大きな差があります。| 比較項目 | Azure(カスタムイメージ) | AWS(AMI) |
|---|---|---|
| Linux向けdeprovisionコマンド | 必須(waagent -deprovision+user) | 不要 |
| インスタンスの状態変更 | deallocate → generalize → image create | stop → Create Image |
| イメージ作成コマンド | az image create --source VM名 |
aws ec2 create-image --instance-id ID |
| 元のVM・インスタンスの再利用 | generalize後は起動不可 | AMI作成後もインスタンスは継続利用可 |
| スナップショットの扱い | イメージ内にOSディスクスナップショット含む | AMI作成時にEBSスナップショットが自動作成 |
| イメージからのVM作成コマンド | az vm create --image イメージ名 |
aws ec2 run-instances --image-id ami-ID |
waagent -deprovision+user を省略するとイメージ化自体は成功するように見えても、そのイメージから起動したVMでプロビジョニングが正常完了せず、SSH接続できない状態になります。また、Azureでは
az vm generalize を実行したVMは二度と通常起動できなくなる点に注意が必要です。AWSではAMI作成後も元のインスタンスは引き続き使えます。AWSから移行する際に引っかかりやすい違いです。トラブルシュート — よくあるエラーと対処
1. 「VM must be in a generalized state」エラー
az image create 実行時に以下のエラーが出る場合があります。(OSProvisioningInternalError) VM must be in a generalized state when creating an image.
az vm generalize を実行していないことが原因です。az vm deallocate → az vm generalize の順に再実行してください。waagent -deprovisionを実行済みであれば、deallocate/generalizeだけ実行すれば回復できます。2. カスタムイメージ起動VMにSSH接続できない
カスタムイメージからVMを起動したが管理者ユーザーでSSHできない場合、waagentのdeprovisionを実行せずにイメージ化したことが疑われます。この場合は当該カスタムイメージを破棄し、ベースVMを新規作成してdeprovisionを正しく実行し直してください。deprovisionなしのイメージから多数のVMを展開した後に気づくケースもあるため、イメージ化前に必ずdeprovisionの実行ログを確認する手順をチェックリスト化しておくことを推奨します。
3. 「waagent: command not found」が表示される
waagentがインストールされていない場合です。# RHEL/Rocky Linux向けwaagentインストール sudo dnf install -y WALinuxAgent # Ubuntuの場合 sudo apt-get install -y walinuxagent
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| VMをOSレベルで一般化する | sudo waagent -deprovision+user |
| VMを割り当て解除する | az vm deallocate --resource-group RG --name VM |
| AzureにVMの汎用化を通知する | az vm generalize --resource-group RG --name VM |
| カスタムイメージを作成する | az image create --resource-group RG --name ImageName --source VM |
| カスタムイメージ一覧を確認する | az image list --resource-group RG --output table |
| カスタムイメージからVMを作成する | az vm create --resource-group RG --name VM --image ImageName |
| VMが汎用化済みか確認する | az vm get-instance-view --query "instanceView.statuses[*].displayStatus" |
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Azureの学習をもっと体系的に進めたいなら、Azure実践ハンズオン講座をご覧ください。現役エンジニアが教える実務直結カリキュラムで、VM構築からインフラ管理まで一気に習得できます。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AzureのLinux VMにNICを追加してマルチNIC構成にする方法|管理用・データ用サブネット分離のazコマンド実践手順
- この記事の属するカテゴリ:Azureへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます