Packerを使ってWindowsのBox作成

概要

Packer を使って,Windows の Box ファイルを作成する. 仮想環境で Windows がほしい時があります.私は,ホスト PC が Ubuntu なので特に必要としています.しかし,Windows の Box は配布されていないので,今までは,「VirtualBox で構築」→→「Vagrant packageで出力」をしていました.それでも個人的に使うには悪くないのですが,Windows の Box もコマンド一つで自動生成して,プロビジョングまでしたいと思っていました. Packer はユーザが用意した設定ファイルを元に,iso や vof,Docker images を作成し,プロビジョニングまで行うことができます. 例えば,CentOS の ISO イメージから,構成管理ツールでプロビジョニングして Box ファイルとして出力と言った具合です. 今回は,この Packer を使って,Windows の ISO ファイルから Box ファイルを作成します.

環境

インストールについては,他のサイトを参照
Windows の人もでもできます.

環境構築

Windows の Box を作成するにあたり,Packer の設定ファイルが必要となる. ありがたいことに GitHub に Packer-Windows というリポジトリが存在する.これを使えばすべてが上手くいく.

packer-windows のダウンロード

git clone https://github.com/joefitzgerald/packer-windows.git

packer-windows のもろもろ

各種ディレクトリとファイルは以下の通り.

README にあるとおり,以下の Windows のエディションに対応している.

Windows ISO ファイルのダウンロード

使用したい Windows のお試し版を以下からダウンロードしisoディレクトリに保存する.
ちなみに,64bit しか対応していないので注意が必要(多分) https://www.microsoft.com/ja-jp/evalcenter/
ここでは,Window8.1 の日本語版を想定して説明する.

Build 時に ISO ファイルのハッシュ値が必要となる.ダウンロードした時に提示された場合,それを使用する.

sha1sum iso/win81_X64FRE_ENTERPRISE_EVAL_JA-JP-IR3_CENA_X64FREE_JA-JP_DV9.ISO

設定

日本語版の Windows を選択した場合,Packer-Windows/answer_files/81/Autounattend.xmlcomponent要素の言語をすべてja-JPに変更する.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
            <SetupUILanguage>
                <UILanguage>ja-JP</UILanguage>
            </SetupUILanguage>
            <InputLocale>ja-JP</InputLocale>
            <SystemLocale>ja-JP</SystemLocale>
            <UILanguage>ja-JP</UILanguage>
            <UILanguageFallback>ja-JP</UILanguageFallback>
            <UserLocale>ja-JP</UserLocale>
        </component>

また,デフォルトでは,Box を作成時に Windows Update を実行する設定となっている.README にある通り,この処理はマシンパワーと時間を必要とするので,今回は実行しない設定とする.Packer-Windows/answer_files/81/Autounattend.xml のWITH WINDOWS UPDATESセクションをコメントアウトし,WITHOUT WINDOWS UPDATESセクションのコメントアウトを外す. 変更後の該当箇所は以下のようになる.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
                <!-- WITHOUT WINDOWS UPDATES -->
                <SynchronousCommand wcm:action="add">
                    <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\openssh.ps1 -AutoStart</CommandLine>
                    <Description>Install OpenSSH</Description>
                    <Order>99</Order>
                    <RequiresUserInput>true</RequiresUserInput>
                </SynchronousCommand>
                <!-- END WITHOUT WINDOWS UPDATES -->
                <!-- WITH WINDOWS UPDATES -->
                <!--
                <SynchronousCommand wcm:action="add">
                    <CommandLine>cmd.exe /c a:\microsoft-updates.bat</CommandLine>
                    <Order>98</Order>
                    <Description>Enable Microsoft Updates</Description>
                </SynchronousCommand>
                <SynchronousCommand wcm:action="add">
                    <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\win-updates.ps1</CommandLine>
                    <Description>Install Windows Updates</Description>
                    <Order>100</Order>
                    <RequiresUserInput>true</RequiresUserInput>
                </SynchronousCommand>
                -->
                <!-- END WITH WINDOWS UPDATES -->

Build

以下のコマンドで Box を作成できる. 今回は,VirtualBox の Box のみを作成している.

1
packer build -only virtualbox-iso -var 'iso_url=./iso/win81_X64FRE_ENTERPRISE_EVAL_JA-JP-IR3_CENA_X64FREE_JA-JP_DV9.ISO' -var 'iso_checksum_type=sha1' -var 'iso_checksum=0b9df1902e2719bea0249c76331cd884bdbb542e' windows_81.json

作成された Box ファイルは,カレントディレクトリにwindows_81_virtualbox.boxとして出力される. 私のノート PC では,2時間くらいかかった.このプロセスは,マシンパワーに依存するので,個人差がでると思われる.

Vagrantfile

*.template という Vagrantifile がもともと用意されているが,使い勝手が悪いので,以下のようにまとめた Vagrantfile を使用する.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# coding: utf-8
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.boot_timeout = 600
  config.vm.communicator = "winrm"

  # Admin user name and password
  config.winrm.username = "vagrant"
  config.winrm.password= "vagrant"
  config.ssh.forward_agent = true

  config.vm.guest = :windows
  config.windows.halt_timeout = 15

  config.vm.network :forwarded_port, guest: 3389, host: 3389, id: "rdp", auto_correct: true
  config.vm.network :forwarded_port, guest: 22, host: 2222, id: "ssh", auto_correct: true

  private_ip = {
    win7: '192.168.252.20',
    win81: '192.168.252.21',
    win10: '192.168.252.22'
  }
  # --------------------------------------------------
  # windows_7
  # --------------------------------------------------
  config.vm.define 'windows_7' do |win7|
    win7.vm.define "vagrant-windows-7"
    win7.vm.box = ".//windows_7_virtualbox.box"
    win7.vm.network :private_network, ip: private_ip[:win7], auto_config: true
    virtualbox_conf( win7, memory: "2048", cpu: "2" )
  end

  # --------------------------------------------------
  # windows_81
  # --------------------------------------------------
  config.vm.define 'windows_81' do |win81|
    win81.vm.define "vagrant-windows-81"
    win81.vm.box = "./windows_81_virtualbox.box"
    win81.vm.network :private_network, ip: private_ip[:win81], auto_config: true
    virtualbox_conf( win81, memory: "2048", cpu: "2" )
  end

  # --------------------------------------------------
  # windows_10
  # --------------------------------------------------
  config.vm.define 'windows_10' do |win10|
    win10.vm.define "vagrant-windows-10-preview"
    win10.vm.box = "./windows_10_virtualbox.box"
    win10.vm.network :private_network, ip: private_ip[:win10], auto_config: true
    virtualbox_conf( win10, memory: "2048", cpu: "2" )
  end

  def virtualbox_conf( config, memory: "1024", cpu: "1", gui: true)
    config.vm.provider "virtualbox" do |vb|
      # Display the VirtualBox GUI when booting the machine
      vb.gui = gui

      # Customize the amount of memory on the VM
      vb.customize ["modifyvm", :id, "--memory", memory, "--cpus", cpu, "--ioapic", "on"]

      # VM DNS off
      vb.customize ["modifyvm", :id, "--natdnsproxy1", "off"]

      # Windows
      vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ]
    end
  end

起動

1
vagrant up window_81

ssh や rdp もできるのがスバラッ!!

1
2
vagrant ssh window_81
vagrant rdp window_81

まとめ

Windows の Box ファイルを Packer を用いて作成しました. Windows に対して,vagrant sshvagrant rdpができるのは便利だと思います. 今回は,元々の Packer の設定ファイルに記述されているプロビジョニングしか行いませんでしたが,Packer は Ansible にも対応しているので,頑張ればゴールデンイメージを作成できるのではないかと思います.
夢が広がります.

参考

「Packer」で Docker 用のイメージファイルを作ってみよう
Packer で Vagrant 用の Box を作成したときのメモ
Packer で Windows の Box (vmware-iso) を作成するまで