WindowsでDocker Machineを試してみる

# 概要
Windows10にDocker環境を構築したのでいろいろ試してみた
その中で今回は、Docker Machineでやったこととコマンドのまとめ
具体的には、自分のローカルマシンのHyper-V上にDocker Machineを使ってDockerの実行環境を構築

DockerとDocker Machineの関連は以下を参照

　[Dockerの基本機能と全体像のイメージを整理してみる](https://qiita.com/fkooo/items/934c7b6f1f0c0e8d1b21 "Dockerの基本機能と全体像のイメージを整理してみる")

動作環境とDocker Machine環境構築方法は以下を参照
（Docker for Windowsをインストールすれば同梱されているためDocker Machineはそのまま使える）

* Windows 10 Pro 64bit
* Docker for Windows

　[WindowsでDocker環境を試してみる](https://qiita.com/fkooo/items/d2fddef9091b906675ca "WindowsでDocker環境を試してみる")

## Docker Machineとは

* ホストマシンにDockerの実行環境をコマンドで構築できる（Docker Engine をインストールしてDockerマシンを作ることができる）ツール
* 構築環境は手元のWindows、Mac等に限定されずクラウド環境にも構築できる
* クラウド環境はAmazon Web Services/Microsoft Azure/Google Compute Engine等々をサポート
* Docker Hubと連携して、自分の手元のマシンで開発環境のDockerイメージを作成、Docker Hubに保存、Docker Machineで構築したAWSのDocker実行環境に同じ開発環境を作成する。等ができるようになる
⇒つまりDockerを複数のマシン／クラウドといったマルチホスト環境で運用できるようになる

　[公式サイト Docker Machine](http://docs.docker.jp/machine/ "Docker Machine")
　[公式サイト サポート環境](http://docs.docker.jp/machine/drivers/ "サポート環境")

## およその作業時間

1時間

## 参考書籍

[プログラマのためのDocker教科書](https://amzn.to/2U1xbWn "プログラマのためのDocker教科書")　第7章
<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4798153222/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4798153222&linkCode=as2&tag=docker_start_003-22&linkId=11b5e01bf21af0d0d4ca8d0aa4d8a3d7"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4798153222&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL110_&tag=docker_start_003-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=docker_start_003-22&l=am2&o=9&a=4798153222" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
わかりやすくてDockerの入門書的な良本です^^
みんな購入していて売れ行き好調なのか第2版が発売されていたのでリンク更新

[【Kindle版】プログラマのためのDocker教科書](https://amzn.to/3eGcXuP "【Kindle版】プログラマのためのDocker教科書")
<a target="_blank"  href="https://www.amazon.co.jp/gp/product/B07BHK5KX7/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B07BHK5KX7&linkCode=as2&tag=docker_start_003-22&linkId=3571c3bc2f80367138417d5f33e4bea2"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B07BHK5KX7&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL110_&tag=docker_start_003-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=docker_start_003-22&l=am2&o=9&a=B07BHK5KX7" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />


[Docker Machine 入門(Hyper-Vの場合)](https://qiita.com/ohhara_shiojiri/items/801a24a2c94ff93be82d "Docker Machine 入門(Hyper-Vの場合)")
手順から構成まで大いに参考にさせて頂きました^^;

## 使用コマンド一覧

```bat
docker-machine create -d ドライバ名 作成するマシン名
docker-machine ls
docker-machine ssh マシン名
docker-machine scp マシン名:ダウンロードファイル 格納フォルダ
docker-machine ip マシン名
docker-machine inspect マシン名
docker-machine env マシン名
docker-machine start マシン名
docker-machine stop マシン名
docker-machine kill マシン名
docker-machine rm マシン名
```

## 事前準備
初期状態のHyper-Vでは、仮想スイッチがDockerNATしかないためIPアドレスを使った接続ができない。必要であれば、Hyper-Vの仮想スイッチを追加する

### 仮想スイッチ追加手順
Hyper-Vマネージャーを起動して、右側のメニューの仮想スイッチマネージャーを選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/188544/878c3399-2199-75b1-3fdd-4b7e189a1909.png)

新しい仮想ネットワークスイッチで「外部」を選択し「仮想スイッチの作成」をクリック
表示される仮想スイッチのプロパティで任意の名前を指定し、外部ネットワークで自身の環境のネットワークカードを選択後、OKをクリック
PCを再起動する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/188544/fd1ec0f9-0b91-5a2a-b4e3-6dae55b2eab6.png)

　[公式サイト Hyper-Vドライバの手順](https://docs.docker.com/machine/drivers/hyper-v/ "Hyper-Vドライバの手順")

## docker-machine create -d ドライバ名 作成するマシン名

Hyper-V上にVMを作成しboot2dockerイメージのインストール、SSH、仮想スイッチ、仮想ディスクの設定を一度にやってくれるコマンド
PowerShellを管理者として起動して実行する

```bat
> docker-machine create -d hyperv --hyperv-virtual-switch "VirtualSW" machine
Running pre-create checks...
Creating machine...
(machine) Copying C:\Users\user\.docker\machine\cache\boot2docker.iso to C:\Users\user\.docker\machine\machines\machin
e\boot2docker.iso...
(machine) Creating SSH key...
(machine) Creating VM...
(machine) Using switch "virtualSW"
(machine) Creating VHD
(machine) Starting VM...
(machine) Waiting for host to start...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe env machine
```
今回、マシン名"machine"で作成
「--hyperv-virtual-switch」はオプション。デフォルトでは一番目に見つかったものが設定されるが念のため明示的に指定

その他オプションは[公式ページ](https://docs.docker.com/machine/drivers/hyper-v/#usage "公式ページ")を参照

![image.png](https://qiita-image-store.s3.amazonaws.com/0/188544/d154f537-1e71-15fc-b702-2766265f6800.png)

### 注意
一度createして再度同じ仮想スイッチを使って別のマシンをcreateすると以下のエラーが発生
（原因はよくわからず最初に作成したマシンを削除してやり直しても同じエラーが発生、、、）

```bat
(machine) Waiting for host to start...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Error creating machine: Error detecting OS: OS type not recognized
```

仮想スイッチを削除、また新しく仮想スイッチを作り直しPC再起動したら成功した

## docker-machine ls

Docker Machineで管理しているマシンの一覧／状態を表示するコマンド

```bat
> docker-machine ls
NAME      ACTIVE   DRIVER   STATE     URL                       SWARM   DOCKER        ERRORS
machine   -        hyperv   Running   tcp://192.168.0.XX:2376           v17.12.0-ce
```

## docker-machine ssh マシン名

Docker Machineで作成したマシンにSSHで接続するコマンド

```
> docker-machine ssh machine
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 17.12.0-ce, build HEAD : 378b049 - Wed Dec 20 23:39:20 UTC 2017
Docker version 17.12.0-ce, build c97c6d6
```

## docker-machine scp マシン名:ダウンロードファイル 格納フォルダ

Docker Machineで作成したマシンからSCPでファイルをダウンロードするコマンド

```bat
> docker-machine scp machine:/home/docker/log.log .
You must have a copy of the scp binary locally to use the scp feature
```

ローカル環境にscpがなかったためエラーになったが、できるはず^^;


## docker-machine ip マシン名

Docker Machineで作成したマシンのIPアドレスを確認するコマンド

```bat
> docker-machine ip machine
192.168.0.XX
```

## docker-machine inspect マシン名

Docker Machineで作成したマシンのCPUやメモリなど構成の詳細を確認するコマンド
構成情報がJSON形式で返却される

```bat
> docker-machine inspect machine
{
    "ConfigVersion": 3,
    "Driver": {
        "IPAddress": "192.168.0.XX",
        "MachineName": "machine",
        "SSHUser": "docker",
        "SSHPort": 22,
～～～省略～～～
        "VSwitch": "virtualSW",
        "DiskSize": 20000,
        "MemSize": 1024,
        "CPU": 1,
        "MacAddr": "",
        "VLanID": 0
    },
～～～省略～～～
```

## docker-machine env マシン名

通常、Dockerコマンド実行にはDockerマシンにSSHで接続後、Dockerマシン上でコマンド実行する必要がある。このコマンドは、SSH接続不要でホストマシン上で特定のDockerマシンに直接コマンド実行するために環境変数を設定するコマンド
docker-machine env と & C: から始まるコマンド２つを実行する必要がある

```bat
> docker-machine env machine
$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://192.168.0.XX:2376"
$Env:DOCKER_CERT_PATH = "C:\Users\user\.docker\machine\machines\machine"
$Env:DOCKER_MACHINE_NAME = "machine"
$Env:COMPOSE_CONVERT_WINDOWS_PATHS = "true"
# Run this command to configure your shell:
# & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env machine | Invoke-Expression

> & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env machine | Invoke-Expression
```

Dockerマシン上じゃなくても直接コマンド実行できるようになる

```bat
> docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
50aff78429b1: Pull complete
f6d82e297bce: Pull complete
275abb2c8a6f: Pull complete
9f15a39356d6: Pull complete
fc0342a94c89: Pull complete
Digest: sha256:ec0e4e8bf2c1178e025099eed57c566959bb408c6b478c284c1683bc4298b683
Status: Downloaded newer image for ubuntu:latest

> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              00fd29ccc6f1        2 weeks ago         111MB

```


戻すときは-uを指定する

```bat
PS C:\WINDOWS\system32> docker-machine env -u
Remove-Item Env:\\DOCKER_TLS_VERIFY
Remove-Item Env:\\DOCKER_HOST
Remove-Item Env:\\DOCKER_CERT_PATH
Remove-Item Env:\\DOCKER_MACHINE_NAME
# Run this command to configure your shell:
# & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env -u | Invoke-Expression

> & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env -u | Invoke-Expression
```
## docker-machine start マシン名

マシンの起動コマンド
最初はdocker-machine createでマシンがそのまま起動するが、stop/killで停止した場合に使用する

```bat
> docker-machine start machine
Starting "machine"...
(machine) Waiting for host to start...
Machine "machine" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
```

## docker-machine stop マシン名

マシンの停止コマンド

```bat
> docker-machine stop machine
Stopping "machine"...
(machine) Waiting for host to stop...
Machine "machine" was stopped.
```

## docker-machine kill マシン名

マシンの停止コマンド
stopで停止できない場合に使用する

```bat
> docker-machine kill machine
Killing "machine"...
(machine) Waiting for host to stop...
Machine "machine" was killed.
```

## docker-machine rm マシン名

マシンの削除コマンド
削除確認があるので y を入力

```bat
> docker-machine rm machine
About to remove machine
WARNING: This action will delete both local reference and remote instance.
Are you sure? (y/n): y
(machine) Waiting for host to stop...
Successfully removed machine
```

## まとめ
クラウドを含めいろいろな環境を使うマルチホスト環境がコマンドだけで簡単にできるのは大きい
また、今回の作業を通して少しずつDockerの動きが理解できてきた
今後やってみる予定のKubernetes等の理解に役立つはず