SharePoint Frameworkの開発環境をDocker上に構築する（Nano Server編）

**2017/3/17 追記**
Windows 10上でNano Serverのイメージを使用する際は、Visual Studio SubscriptionなどのWindows Serverの所有権が必要です。ご注意ください。
[Microsoft ソフトウェア追補ライセンス条項](https://docs.microsoft.com/ja-jp/virtualization/windowscontainers/images-eula)
**2017/3/1 追記ここまで**

**2017/3/11 追記**
最後のNano Serverのイメージにモジュールをコピーするところを修正しました。
**2017/3/11 追記ここまで**

SharePoint Framework(SPfx)が2017/2/23にGAしてたので、手元の環境のアップデート・備忘録も兼ねて纏めてみました。タイトルで **Nano Server編** としているのは、Nano Server上に作るからです。Nano ServerじゃなくてLinuxのイメージ上に作ることも、もちろんできます。 

本投稿は、Stefan Schererさんの以下の内容を参考にしました。
[How to build a Node.js Nano Server Docker base image](https://stefanscherer.github.io/how-to-build-nodejs-nanoserver-image/)

# 動機
nodeとかSPfx自体ちょこちょこアップデートがあるので、なるべくホスト側に入れたくなかったから。
あとはコンテナのイメージにしてしまえば、複数バージョンでも簡単に共存ができそうだから。

# 忙しい人向け
waldekmさんがDocker Hubでイメージを公開されているので、それを使うのが手っ取り早いです。
Macで動いたってコメントが付いているので、Linuxベースで作ってるみたいですね。

[Docker Hub - waldekm/spfx](https://hub.docker.com/r/waldekm/spfx/)
>In the command line (on macOS):
> `cd [your project]`
> `docker run -h spfx -it --rm --name ${PWD##*/} -v $PWD:/usr/app/spfx -p 5432:5432 -p 4321:4321 -p 35729:35729 waldekm/spfx `

>In the command line (on Windows, assuming your project is located at c:\projects\spfx-helloworld):
> `cd c:\projects\spfx-helloworld`
> `docker run -h spfx -it --rm --name spfx-helloworld -v /c/projects/spfx-helloworld:/usr/app/spfx -p 5432:5432 -p 4321:4321 -p 35729:35729 waldekm/spfx `

# 動作環境
本手順は以下の環境で確認しています。
- Windows 10 Pro Insider Preview(Build 15048)
- Docker Version 17.03.0-ce

# 全体の流れ
Nano Serverのイメージに直接nodeのインストールとかはできないため、以下の手順で作っていきます。
1. Server CoreのイメージにNode.JSをインストール
2. Yeomanやgulp、SharePoint generatorをインストール
3. node環境一式をNano Serverのイメージにコピー

## Server CoreのイメージにNode.JSをインストール
まずは以下のようなDockerfileを用意します。

```Bash:Dockerfile
FROM microsoft/windowsservercore

ENV NPM_CONFIG_LOGLEVEL info  
ENV NODE_VERSION 6.10.0

RUN powershell -Command \
    wget -Uri https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-x64.msi -OutFile node.msi -UseBasicParsing ; \
    Start-Process -FilePath msiexec -ArgumentList /q, /i, node.msi -Wait ; \
    Remove-Item -Path node.msi
```

nodeの6.10.0は、この記事を書いている2017/3/10時点でのLTS最新版バージョンです。
windowsservercoreのイメージを取ってくるところからエラーになった場合は、DockerがWindows Containersで動いているか確認してみてください。

Dockerfileを用意したらビルドします。
`docker build -t node:6.10.0 .`
タグとかはお好みで。

できたイメージの`node -v`を実行して、きちんと6.10.0になっているか確認します。
`docker run -it --rm node:6.10.0 node -v`

## Yeomanやgulp、SharePoint generatorをインストール
上記の手順で作ったイメージをベースに、必要なツールをインストールしていくために、以下のようなDockerfileを用意します。
イメージを分けずに、前のDockerfileとあわせて一つのDockerfileに全部書いても良いと思います。

```Bash:Dockerfile
FROM node:6.10.0

RUN npm install -g npm
RUN npm install -g yo gulp
RUN npm install -g @microsoft/generator-sharepoint@1.0.0
```

Previewの頃は`install -g npm@3`となってましたが、GA後は`@3`の記載が削除されました。　[*コミットログ](https://github.com/SharePoint/sp-dev-docs/commit/0cfa47a09197d092c01538e1ddcbe902723df9a6)
また、windows-build-toolsに関しても、インストールが不要になったようです。　[*コミットログ](https://github.com/SharePoint/sp-dev-docs/commit/6704be82c562971f1edd24e08e7e37eef65e8a99)
generatorは`@latest`とすれば最新版を取ってきてくれます。
[Set up your SharePoint client-side web part development environment](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment)

Dockerfileを用意したらビルドします。
`docker build -t node:6.10.0-spfx1.0.0 .`
これもタグとかはお好みで。

## node環境一式をNano Serverのイメージにコピー
イメージを起動して必要なファイルをホスト側にコピーしていきます。

```
docker run --name=spfx node:6.10.0-spfx1.0.0
docker cp "spfx:C:\Program Files\nodejs" nodejs
docker cp "spfx:C:\Users\ContainerAdministrator\AppData\Roaming\npm" npm
docker stop spfx
```

Nano Serverにnodejs, npmのフォルダを取り込むために、以下のDockerfileを用意します。

** 2017/3/11 Dockerfileを修正 **

```diff:Dockerfile
FROM microsoft/nanoserver

-COPY nodejs /windows/system32/
+COPY ["nodejs", "/Program Files/nodejs/"]
-COPY npm /Users/ContainerAdministrator/AppData/Roaming/
+COPY ["npm", "/Users/ContainerAdministrator/AppData/Roaming/npm/"]

-RUN setx PATH %PATH%;C:\windows\system32;C:\Users\ContainerAdministrator\AppData\Roaming
+RUN setx PATH "%PATH%;C:\Program Files\nodejs\;C:\Users\ContainerAdministrator\AppData\Roaming\npm"
```

ビルドしてようやく完成です。
`docker build -t spfx:1.0.0 .`

## プロジェクトを作る
作成したイメージを使って、SharePoint Frameworkのプロジェクトを作成できることを確認します。

コンテナを起動します。
` docker run -it --rm spfx:1.0.0 powershell`

Hello Worldを作ってみます。

```
mkdir helloworld
cd helloworld
yo @microsoft/sharepoint
```

無事にプロジェクトが作成できました。
![2017031001.PNG](https://qiita-image-store.s3.amazonaws.com/0/40644/fd0c144c-1aee-6205-99c0-95b5cbab3e1a.png)

実際に開発する際は、起動する際に`-v`でホスト側とフォルダを共有したり、`-p`でポートを割り当てたりすることになります。

# おまけ
Nano Serverだと、Server Coreに比べてイメージのサイズがだいたい10分の1ぐらいになります。
![2017031002.PNG](https://qiita-image-store.s3.amazonaws.com/0/40644/ba41816b-f6a2-75b5-8dc8-14afa910f1bc.png)