LoginSignup
21
34

More than 5 years have passed since last update.

【Windows】Docker Desktop for WindowsとVagrantの便利な環境を共存させる #1/3【Hyper-V】

Last updated at Posted at 2019-03-17

はじめに

最近、Windows 10にアップグレードしたことに伴い、ローカルの仮想マシン用のハイパーバイザを、もともと利用していたOracle VirtualBoxからHyper-Vに乗り換えました。
VirtualBoxとHyper-Vを切り替えて使うという選択肢もゼロではありませんでしたが、切り替えにはOS再起動を伴うので少々面倒です。
Windows 10でも引き続きVirtualBoxを使うという選択肢もありましたが、Docker Desktop for Windowsも使ってみたかったのでHyper-Vに乗り換えました。

やりたかったこと

Vagrant+VirtualBoxの環境を長年使っておりますが、VagrantはVirtualBoxをProviderとした場合、かなり柔軟にいろいろ設定が出来ます。
Hyper-Vに移行した場合でも、VMの操作については同様の使用感を実現したい、というのが大きな目的です。
要件を整理すると下記のようになりました。

  • Docker Desktop for Windowsを使う
    • 各Docker container内からInternetへ接続できるようにする
    • PublishしたPortは、ホストOSからの接続・ネットワーク外部のホストからの接続ができるようにする
    • Docker Containerが稼働するOS(MobyLinuxVM)のネットワークは192.168.252.0/23にする
  • Hyper-Vの仮想マシン(VM)を普通に使う
    • 各VMからInternetへ接続できるようにする(WinNATを利用)
    • 各VM間で通信できるようにする
    • VagrantでVMを作成・破棄できるようにする
    • ホストOSから任意のターミナルソフト(自分の場合はTeraTerm)を使って、VMにSSH接続する
    • Hyper-VのVMが稼働するネットワークは192.168.254.0/23にする
    • Vagrantfile内の設定をもとにVMに固定のプライベートIPアドレスを付与する(できない
  • 上記の環境を共存させる
  • 両環境のネットワークは可能であれば分離する(した)

TL;DR

  • Docker Desktop for Windowsについて
    • Docker Desktop for Windowsのセットアップは、特に難しいことを追加でやる必要はない
    • Docker Desktop for Windowsで起動したコンテナからInternetへの接続、「-p」オプションで公開したポートへの他のPCからの接続も特に難しいことは無い
    • Docker Desktop for WindowsのNATの仕組みは詳細不明(※詳細未調査。ただし、WinNATとの併存はできる模様)
  • Hyper-Vの仮想ネットワークについて
    • Hyper-Vの仮想マシンからInternetへ接続できるようにするには、幾つか手作業での設定(PowerShellベースの操作)が必要
    • Hyper-VのVM用ネットワークはWinNATを適用する
    • Hyper-Vの仮想ネットワークは、VirtualBoxやVMWareと比べて機能が少ない(NAT/NAPT/DHCPサーバ機能は無い)ので、いろいろと自前で設定する必要がある
    • VagrantはHyper-Vの仮想ネットワークを操作する機能が無い(※少なくとも2019/3/18現在の最新版である2.2.4では)
    • 「Default Switch」という機能が実装され、NAT/NAPT/DHCPサーバ機能が実装されているが、うちの環境では不安定で使えなかった(コントロールパネルのNetwork Connectionsに表示されたり消えたりを繰り返す)

最終的なネットワーク構成

試行錯誤の結果、最終的に下記のような構成に落ち着きました。
DockerDesktopForWindowsWithVagrantWithHyperV_01.PNG

構成のポイントは下記のとおりです。

  • Docker Desktop for Windows用のネットワーク(DockerNAT)
    • 192.168.252.0/23のネットワーク
    • 対応するVirtual Switch名は「DockerNAT」(※インストール時に自動で生成される)
    • ホストOS側のIPアドレスは192.168.252.1/23
    • Docker container用VM(MobyLinuxVM)のIPアドレスは192.168.252.2/23(※今回の観測上はこの値であった。このIPアドレスがどのように決定・設定されるかは不明。)
    • Docker container内からInternetへの接続が可能
  • Hyper-V通常VM用のネットワーク(Hyper-V Internal with WinNAT)
    • 192.168.254.0/23のネットワーク
    • 対応するVirtual Switch名は「Hyper-V Internal with WinNAT」(※任意に命名可)
    • ホストOS側のIPアドレスは192.168.254.1/23
    • ゲストOS側(上図のstdsv3)のIPアドレスはネットワークレンジ内であれば任意の値を設定可能。今回は192.168.254.13/23を設定。
    • WinNATの機能を利用し、このネットワーク内と外部ネットワークとの通信はNATするよう設定

実際に使う上で必要な通信パターンは、実質的に以下の4つとなりました。

  • ①各Docker containerからInternetへ接続
  • ②外部のホストから、Publishされたポートを経由してDocker containerに接続
  • ③各VMからPublishされたポートを経由してDocker containerに接続
  • ④各VMからInternetへ接続

これを図示したものが下記となります。
DockerDesktopForWindowsWithVagrantWithHyperV_02.PNG

環境

本稿は以下の環境で検証しました。

  • OS: Windows 10 Pro 10.0.17763 Build 17763
  • GitBash 2.21.0
  • Vagrant 2.2.4
  • Docker Desktop for Windows Community Edition (CE):
    • Version: 2.0.0.3 (31259)
    • Channel: stable
    • Build: 8853db3

概要

全体の流れは大きく以下のようになります。分量が多いので記事は分割しました。

手順

Docker Desktop for Windowsをセットアップする

Docker Desktop for Windowsのインストール

まずは、Docker Desktop for Windowsをインストールします。
インストール手順は下記公式ドキュメントに書いてありますので、これに従います。

Install Docker Desktop for Windows | Docker Documentation
https://docs.docker.com/docker-for-windows/install/

なお、Docker Desktop for Windowsをダウンロードするにあたり、Docker Hubのアカウント(というよりDocker ID)が必要となりますので、事前に登録しておきます。

Docker ID accounts | Docker Documentation
https://docs.docker.com/docker-id/

Hyper-Vからの見え方を確認する

インストールが完了し、Docker Desktop for Windowsの実行が完了したら、Hyper-V Managerを開きます。
下記のように「Virtual Machines」の一覧に「MobyLinuxVM」というインスタンスが追加されていることが確認できます。
DockerDesktopForWindows_HyperV_01.png

「MobyLinuxVM」を選択し、下のペインの「Networking」タブを押すと、「DockerNAT」というネットワーク(正確にはVirtual Switch)に接続されていることを確認できます。
DockerDesktopForWindows_HyperV_02.png

当該Virtual Switchの詳細を見てみましょう。右の「Actions」ペインから「Virtual Switch Manager...」をクリックします。下記のようなウィンドウがポップアップします。
「DockerNAT」というVirtual Switchがあるので、これをクリックします。
「Connection type」が「Internal Network」となっていることが確認できます。
DockerDesktopForWindows_HyperV_03.png

なお、Hyper-Vで作成できるVirtual Switchには3種類あります。挙動の違いは下記ドキュメントを参照してください。

Create a virtual switch for Hyper-V virtual machines | Microsoft Docs
https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/get-started/create-a-virtual-switch-for-hyper-v-virtual-machines

Docker Desktop for Windowsで利用するネットワークセグメントの変更

次に、タスクトレイのDockerアイコンから、「Settings」を開きます。
デフォルトでは下記の設定になっていると思います。

  • Subnet Address: 10.0.75.0
  • Subnet Mask: 255.255.255.0

DockerDesktopForWindows_Settings_Network_01.png

この値を下記のように変更したのち、Applyボタンを押します。
Networkの設定変更、Docker container用VM(MobyLinuxVM)、Hyper-VのVirtual Switchともに作り直しになるようで、かなり時間がかかるので気長に待ちます。体感では、十数分ぐらいといったところでしょうか。

  • Subnet Address: 192.168.252.0
  • Subnet Mask: 255.255.254.0

DockerDesktopForWindows_Settings_Network_02.png

以上で、Docker Desktop for Windowsのセットアップは完了です。

PowerShellからDocker Desktop for Windows用のネットワーク(DockerNAT)の設定を確認する

PowerShellからネットワーク関連の設定を参照することが可能です。
PowerShellをAdministrator権限で実行し、下記コマンドレットを実行してみます。

Get-VMSwitch

Get-VMSwitchで、存在するVirtual Switchの一覧を表示します。

Get-VMSwitch
PS C:\WINDOWS\system32> Get-VMSwitch

Name      SwitchType NetAdapterInterfaceDescription
----      ---------- ------------------------------
DockerNAT Internal

Get-NetAdapter

Get-NetAdapterで、存在するNIC(Network Adapter)の一覧を表示します。NICには「ifIndex」というUniqueなIDが付与されるようです。NICに何か設定変更をしたい場合、このifIndexの値で指定することが多いです。
Docker Desktop for Windowsのインストールにより、「vEthernet (DockerNAT)」というNICが自動で作られています。このNICの「ifIndex」は「26」であることが分かります。

Get-NetAdapter
PS C:\WINDOWS\system32> Get-NetAdapter

Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
----                      --------------------                    ------- ------       ----------             ---------
ローカル エリア接続       Realtek PCIe GBE Family Controller            9 Up           80-EE-73-2E-ED-3E         1 Gbps
vEthernet (DockerNAT)     Hyper-V Virtual Ethernet Adapter             26 Up           00-15-5D-14-25-0E        10 Gbps

Get-NetIPaddress

Get-NetIPaddressで、NICに付与されたIPアドレスを表示します。192.168.252.1が付与されていることが分かります。

Get-NetIPaddress
PS C:\WINDOWS\system32> Get-NetIPAddress -InterfaceIndex 26


IPAddress         : 192.168.252.1
InterfaceIndex    : 26
InterfaceAlias    : vEthernet (DockerNAT)
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 23
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Preferred
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : ActiveStore

Docker container内からInternetへの疎通を確認する

では実際に、Docker containerからInternetへ接続できるかどうかを確認していきます。
CentOS 7のDocker imageをもとにcontainerを実行し、net-utils及びbind-utilsをインストールして疎通を確認していきます。

CentOS 7のDocker imageをもとにcontainerを実行する

PowerShellを開き、「-ti」オプション付きでdocker runを実行し、プロセスとしてbashを起動させます。初回はDocker imageのダウンロードが行われるので、少し時間がかかるでしょう。
containerの実行が完了するとcontainerのシェルを操作できるようになります。

PS C:\WINDOWS\system32> docker run -ti centos bash
[root@7381948a82a5 /]#

net-utils及びbind-utilsをインストールする

containerのシェルからyum installを実行します。

[root@7381948a82a5 /]# yum install net-tools bind-utils -y
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
 * base: ftp.jaist.ac.jp
 * extras: ftp.jaist.ac.jp
 * updates: ftp.jaist.ac.jp

# ※途中省略

Running transaction
  Installing : GeoIP-1.5.0-13.el7.x86_64                                                                            1/4
  Installing : 32:bind-libs-9.9.4-73.el7_6.x86_64                                                                   2/4
  Installing : 32:bind-utils-9.9.4-73.el7_6.x86_64                                                                  3/4
  Installing : net-tools-2.0-0.24.20131004git.el7.x86_64                                                            4/4
  Verifying  : 32:bind-utils-9.9.4-73.el7_6.x86_64                                                                  1/4
  Verifying  : GeoIP-1.5.0-13.el7.x86_64                                                                            2/4
  Verifying  : net-tools-2.0-0.24.20131004git.el7.x86_64                                                            3/4
  Verifying  : 32:bind-libs-9.9.4-73.el7_6.x86_64                                                                   4/4

Installed:
  bind-utils.x86_64 32:9.9.4-73.el7_6                    net-tools.x86_64 0:2.0-0.24.20131004git.el7

Dependency Installed:
  GeoIP.x86_64 0:1.5.0-13.el7                             bind-libs.x86_64 32:9.9.4-73.el7_6

Complete!

containerのネットワーク設定を確認する・Internetへの接続を確認する

IPアドレス設定・ルーティングテーブルなどの設定を確認し、Internetへの接続ができるかどうかを確認します。

ifconfigコマンドを実行し、付与されたIPアドレスを確認します。今回は172.17.0.2/16が付与されていることを確認できます。

ifconfig
[root@1787083910dc /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 8790  bytes 12845100 (12.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3116  bytes 172364 (168.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

netstat -rnでルーティングテーブルを見てみます。172.17.0.1がDefault Gatewayになっていることが確認できます。

netstat -rn
[root@1787083910dc /]# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG        0 0          0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0

適当なInternet上のホストにpingします。ここでは8.8.8.8を利用します。

ping
[root@1787083910dc /]# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=37 time=18.3 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=37 time=14.3 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=37 time=14.1 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 14.156/15.612/18.334/1.931 ms

キャッシュされたARPテーブルを見てみます。Default Gatewayである172.17.0.1のMACアドレスが保持されていることを確認できます。

arp -a
[root@1787083910dc /]# arp -a
gateway (172.17.0.1) at 02:42:e0:c7:e4:c3 [ether] on eth0

名前解決ができるかどうかdigコマンドを利用して試してみます。問題なく名前解決することができました。
併せてDNSリゾルバとして192.168.65.1が利用されていることが確認できます。

dig
[root@1787083910dc /]# dig google.com

; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 199
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             291     IN      A       216.58.197.206

;; Query time: 14 msec
;; SERVER: 192.168.65.1#53(192.168.65.1)
;; WHEN: Sun Mar 17 06:14:05 UTC 2019
;; MSG SIZE  rcvd: 55

resolv.confの内容を確認してみます。やはり192.168.65.1が指定されていることが確認できました。

/etc/resolv.conf
[root@1787083910dc /]# cat /etc/resolv.conf
# This configuration is written to the config.iso
nameserver 192.168.65.1
search ******** # ホストOSの設定が反映される
domain ******** # ホストOSの設定が反映される

Docker container外のホストからcontainerへの疎通ができるかどうか確認する

最後に、適当なDocker conainerを起動させ、ホストOS・他のPCから接続できるかどうかを確認します。
nginxのイメージを使います。

nginxのDocker imageをもとにcontainerを実行する

PowerShellを開き、nginxのイメージを指定してdocker runを実行します。今回は、公開するPortを8080、container側のPortを80として実行します
実行後、エラー等が表示されなければ恐らく成功です。

PS C:\Users\mta> docker run -p 8080:80 nginx

ホストOSからnginxへの疎通を確認する

ホストOSでGitBashを実行し、curl等でTCP/8080にHTTPアクセスして、nginxのWelcomeページが返却されるかどうか確認します。
IPアドレスは、127.0.0.1、物理NICに振られているアドレス(今回の場合は10.1.1.34)それぞれ確認します。

127.0.0.1
$ curl http://127.0.0.1:8080/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
物理NIC
$ curl http://10.1.1.34:8080/
<!DOCTYPE html>

※途中省略

</html>

以上で、Docker containerの疎通確認は終了です。container内からInternetへの接続ができること、ホストOSからcontainerに接続できることを確認しました。
外部のほかのホストからcontainerに接続できるかどうかについては、次の作業で確認します。

ちなみにcontainerから見えるネットワーク設定は、LinuxにDockerをインストールした場合と変わらないようです。

Hyper-V通常VM用のネットワーク(Hyper-V Internal with WinNAT)を設定する

※続きます

【Windows】Docker Desktop for WindowsとVagrantの便利な環境を共存させる #2/3【Hyper-V】

21
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
34