Windows Server 2016 TP3 での Docker (3) コンテナの起動、Dockerfile からのイメージ作成

# はじめに
[前回](http://qiita.com/Arturias/items/4d1c441f09546c37a126) で Docker の実行環境を Azure 上に構築できたので、今回は次のように Docker を使ってみます。

* コンテナの起動、削除などの基本的な操作
* Dockerfile から Web サーバーとして動作するイメージを作成して起動させる

今回の全体的な構成はこうです。
![WinCont00.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/e1345680-4dbe-e8f8-6def-0e8e76526d2e.png)



なお、今回はホスト側(Windows Server 2016 TP3)とコンテナ側の両方で操作をするので、どちらで操作しているのか分かるような表記にしました。

```text:ホスト側
C:\>コマンド・・・
```

```text:コンテナ側
C:\>コマンド・・・
```

それでは、まず Azure 上の Windows Server 2016 TP3 の VM に RDP 接続しておきます。
![Azure03b.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/50ff2a4a-eba2-567c-0162-7b752b952476.png)



# 基本的な操作
最初に Docker イメージを表示。

```text:ホスト側
C:\>docker images
REPOSITORY          TAG             IMAGE ID        CREATED         VIRTUAL SIZE
windowsservercore   latest          0d53944cb84d    11 days ago     9.697 GB
windowsservercore   10.0.10514.0    0d53944cb84d    11 days ago     9.697 GB
```

後でコンテナを起動した際にホストとコンテナの情報を比較したいので、ホスト側のコンピュータ名やIPアドレスを確認しておきます。

```text:ホスト側
C:\>hostname
WS2016Cont

C:\>ipconfig
Windows IP Configuration

Ethernet adapter vEthernet (Virtual Switch):
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::ccad:a9c:abb4:a480%10
   IPv4 Address. . . . . . . . . . . : 172.16.0.1
   Subnet Mask . . . . . . . . . . . : 255.240.0.0
   Default Gateway . . . . . . . . . :

Ethernet adapter Ethernet 4:
   Connection-specific DNS Suffix  . : cloud-je.l4.internal.cloudapp.net
   Link-local IPv6 Address . . . . . : fe80::185:ebdf:1a01:8bca%16
   IPv4 Address. . . . . . . . . . . : 100.74.44.50
   Subnet Mask . . . . . . . . . . . : 255.255.254.0
   Default Gateway . . . . . . . . . : 100.74.44.1
```

そして、コンテナを起動。cmd.exe(コマンドプロンプト) を実行するだけのコンテナです。
ただ、**コンテナの起動が完了するまで 30～40秒**かかりました。 まだプレビュー版なので、今後改善されていくのでしょう。

```text:ホスト側
C:\>docker run -it --name test01 windowsservercore cmd
```

起動するとこんな感じになります。
![WinCont01.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/eb3dd6c6-1388-6867-60c6-8bea9cf3c691.png)

コンテナ内のコンピュータ名とIPアドレスを見てみると、コンピュータ名はホスト側と同じ WS2016Cont であることが分かります。Linux の場合はホスト側とコンテナ側でそれぞれホスト名が異なりますが、これは TP3 での制約かも？

```text:コンテナ側
C:\Windows\system32>hostname
WS2016Cont

C:\Windows\system32>ipconfig
Windows IP Configuration

Ethernet adapter vEthernet (Virtual Switch-24b8185ae434c661104c4c37f8841b4e1fca598cf28b40777bc3588352927a0d-0):

   Connection-specific DNS Suffix  . : cloud-je.l4.internal.cloudapp.net
   Link-local IPv6 Address . . . . . : fe80::2c0c:e10c:8e37:296d%21
   IPv4 Address. . . . . . . . . . . : 172.16.0.2
   Subnet Mask . . . . . . . . . . . : 255.240.0.0
   Default Gateway . . . . . . . . . : 172.16.0.1
```

また、ローカルシステムアカウントで動作しているようです。

```text:コンテナ側
C:\Windows\system32>whoami
nt authority\system
```

では、いったん ```exit``` コマンドで cmd.exe を抜けて、コンテナを停止させます。
ホスト側では ```docker ps -a``` で停止させたコンテナを表示できます。

```text:ホスト側
C:\>docker ps -a
CONTAINER ID      IMAGE           COMMAND      CREATED           STATUS                      PORTS      NAMES
24b8185ae434      windowsserve    "cmd"        7 minutes ago     Exited (0) 15 seconds ago              test01
```

最後にコンテナを削除しておきます。

```text:ホスト側
C:\>docker rm test01
test01
```

# Dockerfile からのイメージ作成
今度は Dockerfile からイメージを作成してみます。 Web サーバーである Nginx を組み込んだイメージを作成して、そのイメージからコンテナを起動し、Nginx にアクセスします。

まず、ホスト側に作業用ディレクトリを作成。

```text:ホスト側
C:\>mkdir build
C:\>cd build
```

Notepad を起動して Dockerfile を作成します。

```
C:\build>notepad
```

Dockerfile は以下のような内容です。Windows 版の nginx をダウンロードして解凍、そして起動させるものです。

```text:Dockerfile
FROM windowsservercore
RUN mkdir C:\nginx
RUN powershell.exe -Command wget -uri "http://nginx.org/download/nginx-1.9.3.zip" -OutFile C:\nginx\nginx-1.9.3.zip
RUN powershell.exe -Command Expand-Archive -Path C:\nginx\nginx-1.9.3.zip -DestinationPath C:\nginx -Force
ENTRYPOINT "cd C:\nginx\nginx-1.9.3 & nginx.exe"
```

書き終わったら C:\build\Dockerfile として保存(ただし、C:\build\Dockerfile.txt として保存されるかも)。
そして、イメージのビルドを実行。

```text:ホスト側
C:\build>docker build -t nginx_win -f Dockerfile.txt .
```

Dockerfile が Dockerfile.txt として保存されていたので、-f でファイル名を指定してます。もちろん -f を使うのではなく、Dockerfile.txt を Dockerfile にリネームしてもOKです。なお、ビルドが完了するまでには数分かかります。

ビルド完了後、イメージを表示すると作成できていることが分かります。

```text:ホスト側
C:\build>docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
nginx_win           latest              2dcb24c6b099        About a minute ago   9.791 GB
windowsservercore   latest              0d53944cb84d        11 days ago          9.697 GB
windowsservercore   10.0.10514.0        0d53944cb84d        11 days ago          9.697 GB
```

さっそくコンテナを起動したいところですが、その前に HTTP の通信が通るように設定をします。
まず、ホスト上で Windows Firewall を無効化。

```text:ホスト側
C:\build>netsh advfirewall set allprofiles state off
```

それと、Microsoft Azure のポータルで、VM への HTTP 通信が通るようにエンドポイントの設定をします。
もし、下図のように、VM のエンドポイントに TCP 80 が登録されてなければ、「追加」を押します。
![WinCont10.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/b2f968a4-7929-0e59-d286-2b19c71c7afb.png)

追加後、変更が反映されるまで待ちます。
![WinCont13.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/961acb64-28b7-7462-8a62-beb1fce49b4d.png)

そして、作成したイメージからコンテナを起動します。

```text:ホスト側
C:\build>docker run -d -p 80:80 --name test02 nginx_win
```

コンテナの起動後、ブラウザでVM(ホスト)にアクセスしてみます。
VM の DNS名は、Azure ポータル上から確認可能。
![WinCont15.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/852230a7-0bb3-6342-8f2e-bb2786514bf4.png)

ブラウザでその DNS 名にアクセスすると、コンテナ上で動作している Nginx から応答が返ってくるのが分かります。
![WinCont20.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/256a0e9f-9567-29ab-cf87-2d7e9b2e29d6.png)

# 参考サイト
https://msdn.microsoft.com/virtualization/windowscontainers/quick_start/manage_docker