Windows Container で Chocolatey を使って構築を自動化する

Windows 10 や Windows Server 2016 では、Container (Docker) を使えるようになっています。このコンテナの構築のときに Chocolatey を使えると楽になるだろうな、ということで、試してみました。

## Chocolatey とは？

Windows において、RHEL の Yum のようにコマンドラインベースで各種サードパーティのアプリケーションをインストールすることができるツールです。Git をはじめとして、[様々なアプリケーション](https://chocolatey.org/packages)が対応されています。

詳しくは、[公式サイト](https://chocolatey.org/)やネット上の記事を見てください。普通に使う用途でも超便利です。

## 制約事項

残念ながら、Chocolatey のスクリプト内で利用されている .NET Framework の System.Net.WebClient が NanoServer では使えなかったため、ServerCore イメージしか利用することができませんでした。

## 今回の記事の実行環境

* Windows 10 (10.0.17134.228)
* Docker for Windows (18.06.1-ce)

## やり方

### Docker Image の Pull

まずは、Windows ServerCore のイメージを Pull しておきます。

```cmd
> docker pull microsoft/windowsservercore
```

### 最初の Dockerfile の作成

```docker:Dockerfile
FROM microsoft/windowsservercore

RUN powershell -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command \
"iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
```

とりあえず、動作確認として Chocolatey をインストールするだけです。

### とりあえず Build

```cmd
> docker build -t wscchoco .
Sending build context to Docker daemon   5.12kB
Step 1/2 : FROM microsoft/windowsservercore
 ---> 0534c30e0e3e
Step 2/2 : RUN powershell -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
 ---> Running in cc7c1a127853
Getting latest version of the Chocolatey package for download.
Getting Chocolatey from https://chocolatey.org/api/v2/package/chocolatey/0.10.11.
Downloading 7-Zip commandline tool prior to extraction.
Extracting C:\Users\ContainerAdministrator\AppData\Local\Temp\chocolatey\chocInstall\chocolatey.zip to C:\Users\ContainerAdministrator\AppData\Local\Temp\chocolatey\chocInstall...
Installing chocolatey on this machine
Creating ChocolateyInstall as an environment variable (targeting 'Machine')
  Setting ChocolateyInstall to 'C:\ProgramData\chocolatey'
WARNING: It's very likely you will need to close and reopen your shell
  before you can use choco.
Restricting write permissions to Administrators
We are setting up the Chocolatey package repository.
The packages themselves go to 'C:\ProgramData\chocolatey\lib'
  (i.e. C:\ProgramData\chocolatey\lib\yourPackageName).
A shim file for the command line goes to 'C:\ProgramData\chocolatey\bin'
  and points to an executable in 'C:\ProgramData\chocolatey\lib\yourPackageName'.

Creating Chocolatey folders if they do not already exist.

WARNING: You can safely ignore errors related to missing log files when
  upgrading from a version of Chocolatey less than 0.9.9.
  'Batch file could not be found' is also safe to ignore.
  'The system cannot find the file specified' - also safe.
chocolatey.nupkg file not installed in lib.
 Attempting to locate it from bootstrapper.
PATH environment variable does not have C:\ProgramData\chocolatey\bin in it. Adding...
WARNING: Not setting tab completion: Profile file does not exist at
'C:\Users\ContainerAdministrator\Documents\WindowsPowerShell\Microsoft.PowerShe
ll_profile.ps1'.
Chocolatey (choco.exe) is now ready.
You can call choco from anywhere, command line or powershell by typing choco.
Run choco /? for a list of functions.
You may need to shut down and restart powershell and/or consoles
 first prior to using choco.
Ensuring chocolatey commands are on the path
Ensuring chocolatey.nupkg is in the lib folder
Removing intermediate container cc7c1a127853
 ---> d0b59b0d9f34
Successfully built d0b59b0d9f34
Successfully tagged wscchoco:latest
```

### 実行してみる

```cmd
> docker run -it --name wscchoco01 wscchoco powershell
```

しばらくするとコンテナ内の PowerShell が起動するので、きちんと使えるかどうか確かめてみます。

```ps
> choco version
Chocolatey v0.10.11

DEPRECATION NOTICE - choco version command is deprecated and will be
 removed in version 1.0.0. Please use `choco upgrade pgkname --noop`
 instead.
_ Chocolatey:ChocolateyVersionCommand - Noop Mode _
chocolatey v0.10.11 is the latest version available based on your source(s).

Chocolatey can upgrade 0/1 packages.
 See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).
```

大丈夫そうですね。
＃choco version コマンドは deprecate になるのか・・・

### 環境に合わせて Dockerfile を編集

Git をインストールするようにしてみます。

```docker:Dockerfile
FROM microsoft/windowsservercore

RUN powershell -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command \
"iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
RUN choco install -y git
RUN refreshenv
```

最後の refreshenv コマンドは、cmd.exe の環境変数等を再読み込みするコマンドです。インストール対象によっては、このコマンドを実行しないと、継続したシェル (cmd.exe) でインストールしたコマンドが実行できません。詳しくは[こちら](https://github.com/chocolatey/choco/wiki/CommandsInstall)を参照。

### Build

ビルドします。Dockerfile 的に前のキャッシュが使えれば、ちょっとだけ早くなります。

```cmd
> docker build -t wscchoco .
Sending build context to Docker daemon   5.12kB
Step 1/4 : FROM microsoft/windowsservercore
 ---> 0534c30e0e3e
Step 2/4 : RUN powershell -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
 ---> Using cache
 ---> d0b59b0d9f34
Step 3/4 : RUN choco install -y git
 ---> Running in 80e2ae9af06c
Chocolatey v0.10.11
Installing the following packages:
git
By installing you accept licenses for the packages.
Progress: Downloading git.install 2.19.0... 100%
Progress: Downloading chocolatey-core.extension 1.3.3... 100%
Progress: Downloading git 2.19.0... 100%

chocolatey-core.extension v1.3.3 [Approved]
chocolatey-core.extension package files install completed. Performing other installation steps.
 Installed/updated chocolatey-core extensions.
 The install of chocolatey-core.extension was successful.
  Software installed to 'C:\ProgramData\chocolatey\extensions\chocolatey-core'

git.install v2.19.0 [Approved]
git.install package files install completed. Performing other installation steps.
Using Git LFS
Installing 64-bit git.install...
git.install has been installed.
git.install installed to 'C:\Program Files\Git'
  git.install can be automatically uninstalled.
Environment Vars (like PATH) have changed. Close/reopen your shell to
 see the changes (or in powershell/cmd.exe just type `refreshenv`).
 The install of git.install was successful.
  Software installed to 'C:\Program Files\Git\'

git v2.19.0 [Approved]
git package files install completed. Performing other installation steps.
 The install of git was successful.
  Software install location not explicitly set, could be in package or
  default install location if installer.

Chocolatey installed 3/3 packages.
 See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).
Removing intermediate container 80e2ae9af06c
 ---> 1c2e33113255
Step 4/4 : RUN refreshenv
 ---> Running in 873b10aea90a
Refreshing environment variables from registry for cmd.exe. Please wait...Finished..
Removing intermediate container 873b10aea90a
 ---> b0057163b278
Successfully built b0057163b278
Successfully tagged wscchoco:latest
```

### 実行

```cmd
> docker run -it --name wscchoco02 wscchoco powershell
```

同様に、しばらくするとコンテナ内の PowerShell が起動するので、きちんと git コマンドが使えるかどうか確かめてみます。

```ps
> git --version
git version 2.19.0.windows.1
```

いけました。

## 終わりに

こんな感じで、Dockerfile 内に記述することで、RHEL の Yum とかでできているのと同じように、様々なアプリケーションをインストールすることができます。

今回は Git のインストールで止めていますが、Dockerfile の続きに `RUN git clone <URL>` などを記載すれば git clone も実行できるので、色々と構築方法が広がりそうです。