2017年3月17日金曜日

docker のネットワーク機能を試してみた

概要

勉強がてら docker のネットワーク機能について基本な操作を行ってみました
既存のネットワークの挙動の確認と独自のネットワークを定義してアタッチするところまで行っています

環境

  • Mac OS X 10.12.3
  • Docker on Mac 17.03.0-ce, build 60ccb22

ネットワークを確認する

まずはデフォルトで用意されているネットワークを確認してみましょう

  • docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
fb949b0d7786        bridge              bridge              local
365cbf8a882f        host                host                local
64103726a5d5        none                null                local

こんな感じで 3 つのネットワークが用意されています
docker run をするときに --net オプションがありこれを使うことでコンテナが所属するネットワークを指定することができます
特に指定しない場合は bridge が選択されるようです

では、この 3 つのネットワークの挙動を確認していきます

ネットワークを指定してコンテナを作成する

bridge

まずは bridge を指定します

  • docker run --rm -p 8080:80 --net bridge --name web1 nginx

これで作成した場合バインドしたポートで Mac (ホストマシン (192.168.100.105)) からコンテナへの通信ができ、moby VM からブリッジネットワークを使ってのコンテナへの通信もできます
また、コンテナからホストマシンへの通信もできます
更に NAT でインターネットに接続することもできます

  • ホストマシンから
    • curl localhost:8080
  • moby から
    • ping 172.17.0.2
  • コンテナから
    • ping 172.17.0.1
    • ping 192.168.100.105
    • apt update

注意点として今回 Docker on Mac でやっているのでホストマシンからコンテナへの ping に関しては moby VM にログインしてから試してください

moby へのログインは以下でできます

  • screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty

host

次に host を試します
--net オプションの部分を host に変更します

  • docker run --rm -p 8080:80 --net host --name web1 nginx

これで作成した場合、コンテナはホストマシンと同じネットワークインタフェースを使用します
なので、moby VM からコンテナへの通信とコンテナからホストマシンへの通信、NAT でのインターネットに接続はできます

  • moby から
    • ping 172.17.0.2
  • コンテナから
    • ping 172.17.0.1
    • ping 192.168.100.105
    • apt update

null

次に null を試します
--net オプションの部分を none に変更します
null ドライバで作成しれたネットワークの none を指定しています

  • docker run --rm -p 8080:80 --net none --name web1 nginx

この場合、どこからもコンテナにアクセスできなくなります
また、コンテナからホストやインターネットへの通信できなくなります

コンテナに exec して確認してみるとわかりますが、通信するための IP アドレスが何も振られていないことがわかると思います

ネットワークを定義する

デフォルトの 3 つのネットワークの挙動はつかめてので次に独自のネットワークを作成してみます
今回は bridge ドライバを使って定義します

  • docker network create my_network

で作成できます
確認するとネットワークが増えていることが確認できます

  • docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
526531de15db        bridge              bridge              local
365cbf8a882f        host                host                local
4aa22f6b0e5c        my_network          bridge              local
64103726a5d5        none                null                local

詳細を確認するには inspect を使います

  • docker network inspect my_network
[
    {
        "Name": "my_network",
        "Id": "4aa22f6b0e5c3759d80bd717410c9aef70e50a853c4076e9bf972f5ba5132f3a",
        "Created": "2017-03-16T23:51:03.617896532Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

Subnet や Gateway はデフォルトで設定されました
既存の bridge ネットワークと比較すると Options が空なだけで後は同じ感じでした

定義したネットワークに接続する

では、定義したネットワークをコンテナに接続してみます
初めに説明すると host と none に対しては接続できませんでした

  • host に対して接続しようとした場合
Error response from daemon: Container sharing network namespace with another container or host cannot be connected to any other network
  • none に対して接続しようとした場合
Error response from daemon: Container cannot be connected to multiple networks with one of the networks in private (none) mode

なので、bridge に接続しているコンテナに対して my_network を接続してみます

  • docker run --rm -p 8080:80 --net bridge --name web1 nginx
  • docker network connect my_network web1

という感じです
insepct で my_network の情報を確認すると Containers の項目が増えていることがわかると思います (以下 inspect 結果の一部抜粋)

"Containers": {
    "cca88927fa6e267e8e552c8a446b5363a29f60f04b2bf534e4cf3cc43fed4047": {
        "Name": "web1",
        "EndpointID": "2bda4228d7930af5ca558aae0e32be545f63018ada5718d80b3daa86bd524fc7",
        "MacAddress": "02:42:ac:12:00:02",
        "IPv4Address": "172.18.0.2/16",
        "IPv6Address": ""
    }
},

また、172.18 帯でも通信できることが確認できると思います
念のためもう一つ my_network に接続しているコンテナを作成してみましょう

  • docker run –rm -p 8081:80 –net my_network –name web2 nginx

で web2 に exec してリーチャビリティを確認すると 172.18 では web1 にアクセスできるが、172.17 ではアクセスできないことが確認できると思います

  • docker exec -it web2 /bin/bash
root@815fc91e6040:/# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.143 ms
--- 172.18.0.3 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.143/0.143/0.143/0.000 ms

root@815fc91e6040:/# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

その他のネットワークドライバ

今回は bridge, host, null という 3 種類のドライバを試しましたが、Docker on Mac では別のドライバも用意されています

  • docker info | grep -A 2 Plugins:
Plugins: 
 Volume: local
 Network: bridge host ipvlan macvlan null overlay

ipvlan, macvlan, overlay というのが他にもあるようです
また、ドライバは自分で定義することもできます
この辺りはまた別途検証して紹介できればと思います

最後に

Docker on Mac でネットワーク機能を試してみました
Mac の場合ちょっと特殊な VM が動作しているので少しややこしくなりましたが概念的には他のマシンで試しても同じだと思います

基本は bridge になるかと思います
あとは swarm などを使った場合にホストをまたがってコンテナ同士を通信させるのに overlay を使う感じかなと思います
それ以外のドライバも試してみたいな思っています

参考サイト

0 件のコメント:

コメントを投稿