Docker Filesで Windows Server Coreコンテナを作成してDocker for Windowsを始める

## 背景
Windows ServerもDockerへの対応がどんどん進み、その上で動かすアプリもコンテナに乗せたくなりました。
ただ、なかなかWindows系のDockerはイメージが掴みづらく、情報も少なめです。なんとなくDocker for Windowsをインストールするところまでは色々な記事を見れば出来るのですが、その先で躓いてしまっていました。
まずはdockerの基本の動作から入るべく、とっかかりとしてコンテナの作成から削除までやってみたいと思います。


## 事前準備

### Docker for Windowsのインストール
Docker for Windowsをインストールしておいてください。下記記事がかなり詳しく書いてあったのでお勧めです。

Docker for WindowsでDockerを学ぶ (バージョンCE 17.06.2)
https://qiita.com/rubytomato@github/items/eec2118e89ee9bd8d17a

### 「Switch to Windows containers...」
Docker for Windowsが起動したら、画面右下のタスクトレイにあるDockerアイコンを右クリックして、「Switch to Windows containers...」を

## Dockerfilesでコンテナイメージを作成して削除する

ものづくりは作って壊すところまでやれば大抵の雰囲気が掴めます。今回はまずコンテナイメージを作って削除してみましょう。

### Dockerfilesの作成
まずはどこでも良いので新しいフォルダを作成し、そこに「Dockerfile」という拡張子の無いファイルを準備します。Dockerfilesの中には、下記を記載して保存します。

``` Dockerfiles
FROM microsoft/windowsservercore
```

### Dockerfilesからコンテナイメージを作成
Dockerfilesを作成したら、あとはPowerShellを開いて作成したフォルダに移動し、下記コマンドを打てばOKです。

``` powershell
docker build -t ＜Dockerコンテナの名前＞ ＜フォルダパス＞
例）docker build -t hoge/fuga .
```

手元環境で実行すると下記のような感じでdockerコンテナのイメージが作成されます。もし元となるイメージの「microsoft/windowsservercore」が無ければ自動的にダウンロードされ、それを基に構築されます。


``` powershell
# Dockerfilesを基にコンテナイメージを構築する
PS C:\WinCoreSample> docker build -t win/core .
Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM microsoft/windowsservercore
latest: Pulling from microsoft/windowsservercore
3889bb8d808b: Pull complete
900b07d43172: Pull complete
Digest: sha256:d46df1d4cef6ea30976227b981dbb379543f77fc884ef8200b89a852f14bd5f8
Status: Downloaded newer image for microsoft/windowsservercore:latest
 ---> 64d9bc839037
Successfully built 64d9bc839037
Successfully tagged win/core:latest

# コンテナイメージの一覧を見る
PS C:\WinCoreSample> docker image ls
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
microsoft/windowsservercore   latest              64d9bc839037        3 days ago          11GB
win/core                      latest              64d9bc839037        3 days ago          11GB
```

ここで表示されている「64d9bc839037」がコンテナイメージIDで、win/coreと言うのがコンテナイメージ作成時に私が付けた名前です。名前はそのままリポジトリとして管理されているため、GitHubのように「/」で区切った名前を付けます。
ちなみに、コンテナイメージの元となる「microsoft/windowsservercore」も一覧に載っています。


### コンテナイメージの削除
せっかく作ったのにと思われるかもしれませんが、とりあえず削除出来るか試してみましょう。
削除は「docker image rm」コマンドで行います。

``` powershell
# コンテナイメージ削除
docker image rm ＜コンテナイメージ名＞
```

それでは実際に削除してみます。

``` powershell
PS C:\WinCoreSample> docker image rm win/core
Untagged: win/core:latest

# コンテナイメージの一覧を見る
PS C:\WinCoreSample> docker image ls
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
microsoft/windowsservercore   latest              64d9bc839037        3 days ago          11GB
```

先ほど作成したコンテナイメージが削除されました。

### コンテナイメージを作って削除するまとめ
試しにコンテナイメージの作成から削除まで通してやってみましょう。


``` powershell
# Dockerfilesを基にコンテナイメージを構築する
PS C:\WinCoreSample> docker build -t win/core .
Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM microsoft/windowsservercore
 ---> 64d9bc839037
Successfully built 64d9bc839037
Successfully tagged win/core:latest

# コンテナイメージの一覧を見る
PS C:\WinCoreSample> docker image ls
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
microsoft/windowsservercore   latest              64d9bc839037        3 days ago          11GB
win/core                      latest              64d9bc839037        3 days ago          11GB

# コンテナイメージを削除する
PS C:\WinCoreSample> docker image rm win/core
Untagged: win/core:latest

# コンテナイメージの一覧を見る
PS C:\WinCoreSample> docker image ls
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
microsoft/windowsservercore   latest              64d9bc839037        3 days ago          11GB
PS C:\work\leaf_projects\docker\wincore>

```

既に元となるコンテナイメージがあるので、初回と比べると物凄く速く実行が出来たかと思います。

## コンテナイメージからコンテナを作って削除する


### コンテナの作成
さて、試しにコンテナイメージからコンテナを作成してみます。作成するには下記のコマンドを使います。

``` powershell
docker run --name ＜コンテナ名＞ -it ＜コンテナイメージ名＞ ＜コンテナで起動するコマンド＞
```

手元環境で動かすとコンテナが起動され、しばらく待つとコンテナ内で起動したPowerShellがそのまま表示されます

``` powershell
PS C:\WinCoreSample> docker run --name wincore -it win/core powershell

Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\>
```

### 作ったコンテナでHello World!

取り急ぎハロワしてみましょう。

``` powershell
PS C:\> echo 'Hello World!'
Hello World!
```

ついでにIPアドレスも見てみます。この辺りはただのpowershellなので気負わずに適当に遊んでみると良いです。

``` powershell
PS C:\> ipconfig

Windows IP Configuration
Ethernet adapter Ethernet 2:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : ＜IPv6アドレス＞
   IPv4 Address. . . . . . . . . . . : ＜IPv4アドレス＞
   Subnet Mask . . . . . . . . . . . : ＜サブネットマスク＞
   Default Gateway . . . . . . . . . : ＜デフォルトゲートウェイ＞
```

### コンテナをコンテナの中から停止する
遊び終わったらさよならします。これもPowerShellなので単に「exit」すれば終了してくれます。

``` powershell
PS C:\> exit
PS C:\WinCoreSample>
```

PowerShell上でPowerShellを開いていたような形なので、一見フォルダが移動しただけに見えますが、ちゃんと終了して、元のホストマシンのPowerShell上に戻ることが出来ました。

試しに、ちゃんと終了しているか確認してみましょう。
コンテナの一覧を見るためには下記のコマンドを使います。

``` powershell
# 起動中のコンテナ一覧を表示
docker ps

# 停止しているコンテナ一覧を表示
docker ps -a
```
「docker ps」では何も表示されず、「docker ps -a」では今回作成したwincoreコンテナが「Exited」というSTATUSで表示されていることを確認できます。

``` powershell
PS C:\WinCoreSample> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
PS C:\WinCoreSample> docker ps -a
CONTAINER ID        IMAGE               COMMAND                   CREATED             STATUS                           PORTS               NAMES
2df0512ec24e        win/core            "powershell"              9 minutes ago       Exited (0) 3 minutes ago                             wincore
```

このようにDockerコンテナはコンテナ作成時に指定したコンテナ上のプログラム（今回はpowershell）が停止すると、コンテナ自体も停止します。

### コンテナをもう一度起動する

もう一度コンテナを起動し、同じようにpowershellに入る際には下記のようにします。
ちなみにコンテナ起動時に実行するコマンドは、コンテナ作成時に既に指定しているので「docker start」時に再度指定する必要はありません。


``` powershell
#コンテナを起動
docker start ＜コンテナ名＞

#コンテナでpowershellを起動して侵入する
docker exec -it ＜コンテナ名＞ powershell
```

ちょっとやってみましょう。

``` powershell
#コンテナを起動
PS C:\WinCoreSample> docker start wincore
wincore

#コンテナでpowershellを起動して侵入する
PS C:\WinCoreSample> docker exec -it wincore powershell

#コンテナ上のPowerShellが表示される
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\> 

#コンテナ上のPowerShellを終わらせる
PS C:\> exit
PS C:\WinCoreSample> 

#コンテナ一覧を見る
PS C:\WinCoreSample> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
2df0512ec24e        win/core            "powershell"        21 minutes ago      Up 2 minutes                            wincore
```

「あれ？今回はコンテナが終了していない」と言うのがミソです。
「docker run」や「docker start」をした際に「-i」オプションを入れていないと、コンテナが起動した際のpowershellに入ることができません。「docker exec」では、コンテナ起動時のコマンドとは別のプロセスとして、コンテナ上のコマンドを実行しています。

### コンテナをコンテナの外から停止する
コンテナは起動時のコマンドが終了するまでは起動したままなので、ちゃんと終了させておきましょう。終了は下記の「docker kill」コマンドで行えます。

``` powershell
docker kill ＜コンテナ名＞
```


### コンテナの起動⇒終了まで
実際に通して実行するとこんな感じです。

``` powershell

# Dockerコンテナを起動する
PS C:\WinCoreSample> docker start wincore
wincore

#起動中のDockerコンテナの一覧を見る　⇒　起動したコンテナが見れる
PS C:\WinCoreSample> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
2df0512ec24e        win/core            "powershell"        2 hours ago         Up 3 seconds                            wincore

#Dockerコンテナを終了させる
PS C:\WinCoreSample> docker kill wincore
wincore

#起動中のDockerコンテナの一覧を見る　⇒　ない
PS C:\WinCoreSample> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

#終了しているもの含めてDockerコンテナの一覧を見る　⇒　終了したコンテナが見れる
PS C:\WinCoreSample> docker ps -a
CONTAINER ID        IMAGE               COMMAND                   CREATED             STATUS                              PORTS               NAMES
2df0512ec24e        win/core            "powershell"              2 hours ago         Exited (4294967295) 5 seconds ago                       wincore

```

なんとなく、コンテナ管理がイメージ出来てきました。

### コンテナの削除
後はコンテナの削除です。コンテナの削除は下記の「docker rm」コマンドで行います。

``` powershell
# 停止しているコンテナの削除
docker rm ＜コンテナ名＞
```

### コンテナの作成・起動⇒終了⇒削除

実際に作るところから流れでやってみましょう。今回はコンテナ作成時にはPowerShellを起動せず、いったん作成して後から「docker exec」でPowerShellを起動して侵入してみます。

``` powershell
# コンテナを作成して起動する。
PS C:\WinCoreSample> docker run --name wincore -t win/core

# コンテナが起動する。Ctrl+Cで抜ける
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\>

#コンテナでpowershellを起動して侵入する
PS C:\WinCoreSample> docker exec -it wincore powershell

#コンテナ上のPowerShellが表示される
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\> 

#コンテナ上のPowerShellを終わらせる
PS C:\> exit
PS C:\WinCoreSample>

# 起動中のコンテナを確認する
PS C:\WinCoreSample> docker ps
CONTAINER ID        IMAGE               COMMAND                    CREATED             STATUS              PORTS               NAMES
1ddf975c83f9        win/core            "c:\\windows\\system32…"   19 seconds ago      Up 5 seconds                            wincore

# 起動中のコンテナを終了させる
PS C:\WinCoreSample> docker kill wincore
wincore

#起動中のDockerコンテナの一覧を見る　⇒　ない
PS C:\WinCoreSample> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

#終了しているもの含めてDockerコンテナの一覧を見る　⇒　終了したコンテナが見れる
PS C:\WinCoreSample> docker ps -a
CONTAINER ID        IMAGE               COMMAND                   CREATED             STATUS                              PORTS               NAMES
2df0512ec24e        win/core            "powershell"              2 hours ago         Exited (4294967295) 5 seconds ago                       wincore

# 停止したコンテナを削除する
PS C:\WinCoreSample> docker rm wincore
wincore

#終了しているもの含めてDockerコンテナの一覧を見る　⇒　ない
PS C:\WinCoreSample> docker ps -a
CONTAINER ID        IMAGE               COMMAND                   CREATED             STATUS                              PORTS               NAMES
```


なんとなくDockerでコンテナを扱う雰囲気が掴めてきたでしょうか。

次はこのコンテナでApache/PHPを動かしてみます。

[Docker Filesで Windows Server Coreコンテナを作成してApache/PHPを動かす](https://qiita.com/tobi50/items/b46221988f0debb214cb)


## その後の更新（2019/1/2）
どうやらWindows Server 2019のイメージがある様子。

``` powershell
docker pull mcr.microsoft.com/windows/servercore:ltsc2019
```

Windows Server 2019 Now Available
https://blogs.technet.microsoft.com/virtualization/2018/11/13/windows-server-2019-now-available/

Windows Server 2019 の Docker Image と MCR への移行
https://blog.shibayan.jp/entry/20181116/1542361140