Docker for Windowsでホストネットワークの他のマシンにアクセスする方法

# 概要

　Docker for Windowsのコンテナからホストマシンが属するネットワーク上の他のマシンにアクセスする方法を残したいと思います。例えば、Windows上でソースをビルドするコンテナを運用していて、ビルドする際にホストマシンが属するネットワーク上のGitサーバからリソースを取得するといったシーンになります

# 方法

　結論から言いますと、Hyper-VにDocker Machineを作成することで実現できます

## なぜデフォルトではできないのか

Docker for Windowsで作成されるHyper-Vの仮想マシン「MobyLinuxVM」はNAT接続のネットワークアダプタのため、ホストネットワークを参照できない

可能であれば、Docker for Windowsのままで済ませたいが・・・
C:\Program Files\Docker\Docker\resources\MobyLinux.ps1を直接編集すればいけそう？

## 手順

1. Hype-Vの仮想スイッチマネージャーで外部接続の仮想スイッチを作成  
    参照：https://docs.docker.com/machine/drivers/hyper-v/#1-make-sure-hyper-v-is-enabled 
2. 以下のコマンドをコマンドプロンプト（**管理者権限**）でmy-machineというDocker Machineを作成
    `-d hyperv --hyperv-virtual-switch "external-switch"`は必須ですが、そのほかのパラメータは任意
    ※`external-switch`は前述で作成した仮想スイッチ名になります
    ※Hyper-V用の各種パラメータは[こちら](https://docs.docker.com/machine/drivers/hyper-v/)

    ```shell
    > docker-machine create -d hyperv --hyperv-virtual-switch "external-switch" --hyperv-memory 2048 --hyperv-cpu-count 2 my-machine

    Running pre-create checks...
(my-machine) Unable to get the local Boot2Docker ISO version:  Did not find prefix "-v" in version string
(my-machine) Default Boot2Docker ISO is out-of-date, downloading the latest release...
(my-machine) Latest release for github.com/boot2docker/boot2docker is v18.09.0
(my-machine) Downloading C:\Users\user\.docker\machine\cache\boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v18.09.0/boot2docker.iso...
(my-machine) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100%
Creating machine...
(my-machine) Unable to get the local Boot2Docker ISO version:  Did not find prefix "-v" in version string
(my-machine) Default Boot2Docker ISO is out-of-date, downloading the latest release...
(my-machine) Latest release for github.com/boot2docker/boot2docker is v18.09.0
(my-machine) Downloading C:\Users\user\.docker\machine\cache\boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v18.09.0/boot2docker.iso...
(my-machine) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100%
(my-machine) Copying C:\Users\user\.docker\machine\cache\boot2docker.iso to C:\Users\user\.docker\machine\machines\my-machine\boot2docker.iso...
(my-machine) Creating SSH key...
(my-machine) Creating VM...
(my-machine) Using switch "external-switch"
(my-machine) Creating VHD
(my-machine) Starting VM...
(my-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: docker-machine env my-machine
    ```
3. 作成したDocker MachineのDocker Daemonへの接続情報を取得

    ```shell
    > docker-machine env my-machine

    SET DOCKER_TLS_VERIFY=1
    SET DOCKER_HOST=tcp://192.168.1.51:2376
    SET DOCKER_CERT_PATH=C:\Users\user\.docker\machine\machines\my-machine
    SET DOCKER_MACHINE_NAME=my-machine
    SET COMPOSE_CONVERT_WINDOWS_PATHS=true
    REM Run this command to configure your shell:
    REM     @FOR /f "tokens=*" %i IN ('docker-machine env my-machine') DO @%i
    ```
4. Docker Clientの接続先を変更
   前述に表示されたコマンドを実行し、Docker Clientの接続先を一時的にDocker MachineのDocker Daemonに変更します
   恒久的に変更したい場合は、表示された変数（DOCKER_TLS、DOCKER_HOSTなど）を環境変数に登録してください

    ```shell
    > @FOR /f "tokens=*" %i IN ('docker-machine env my-machine') DO @%i
    ```
5. 接続確認
   なにかコンテナを立ち上げて、ホストマシンが属するネットワーク上にあるマシンにpingしてみてください
   問題なく疎通できれば完了です！


作成したDocker Machineを常用する場合は、「Docker for Windows」を起動する必要なくなり、代わりにdocker-machine startコマンドで起動する

# Docker Machineトラブルシューティング

## 現象(certificate signed by unknown authority)

```shell
NAME                ACTIVE   DRIVER   STATE     URL                        SWARM   DOCKER    ERRORS
my-docker-machine   -        hyperv   Running   tcp://172.17.120.43:2376           Unknown   Unable to query docker version: Get https://172.17.120.43:2376/v1.15/version: x509: certificate signed by unknown authority
```

## 対策

https://github.com/sparkfabrik/sparkdock/issues/14

```shell
> docker-machine regenerate-certs my-machine
```