Docker network(個人的備忘録)

##ブリッジドライバーとは
単一のdockerホスト内で構成されるネットワークで、比較的小規模なネットワーク構成を組む場合に利用される。

##Docker Machineでdockerホストを1台起動してネットワークの動作を確認する。
```haml
-# Dockerホストの作成
% docker-machine create nw-vm1
-# 仮想マシンにsshでログインする
% docker-machine ssh nw-vm
-# 存在するネットワークの確認
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
94ade5c5f1ae        bridge              bridge              local
3723c4561df4        host                host                local
105e9024e5d5        none                null                local
```
ネットワークの動作は「DRIVER」の種別で異なる。デフォルトで3つ作られている。
コンテナはデフォルトで「bridge」ネットワークに属している。

## ネットワークの詳細確認
```haml
-# docker network inspect DRIVER名
$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "94ade5c5f1aed16a3637a2c40bed82ac50d51b8814737c5e9942d0f8e0a1fd4c",
        "Created": "2020-09-04T11:31:43.470419246Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
```
Configの欄を見るとネットワークのサブネットとデフォルトゲートウェイのidを確認することができる。ブリッジネットワークに接続されたコンテナは、このネットワーク内のipが割り当てられる。ゲートウェイのipは「docker0」インターフェースに割り当てられたipとなる。

## インターフェイスの情報の確認
```docker
## dockerホストにssh接続した状態
$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:78:70:eb brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe78:70eb/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:ae:f1:12 brd ff:ff:ff:ff:ff:ff
    inet 192.168.99.101/24 brd 192.168.99.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:feae:f112/64 scope link 
       valid_lft forever preferred_lft forever
4: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:77:b5:fe:32 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
```
Docker0のインターフェイスのipが確認できる。

## alpineコンテナの起動
```
$ docker run -itd —name alpine1 alpine /bin/sh
$ docker inspect bridge
```
"Containers”の欄にalpine1のコンテナが存在し、ipが割り当てられているのがわかる。
デフォルトのブリッジネットワークでは同じネットワークに存在するコンテナとipアドレス指定で通信することができる。

## もう一つのコンテナを立ち上げる。
```haml
-# alpineを元に「alpine2」のコンテナを立ち上げる
$ docker run -itd —name alpine2 alpine /bin/sh
-# コンテナにアタッチしてipを確認する。
$ docker attach alpine2
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
```
alpine2にはipが、172.17.0.3に割り当てられている。

## pingを飛ばしコンテナ間が接続されていることを確認する。
```
# ping -w 3 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.389 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.140 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.116 ms

--- 172.17.0.2 ping statistics ---
4 packets transmitted, 3 packets received, 25% packet loss
round-trip min/avg/max = 0.116/0.215/0.389 ms
```
alpine1と通信ができていることが確認できる。

## コンテナ名での通信もできる
デフォルトのネットワークでは、dockerデーモンでDNSの提供ができないため、コンテナ名で通信することができない。これはユーザー定義のブリッジネットワークを使用することで解決することができる。

## ユーザー定義のブリッジネットワークの作成
```haml
-# docker network create ネットワーク名
$ docker network create my_nw 
```
これで「my_nw」というブリッジネットワークが作成できる。

## コンテナ同士の接続
```haml
-# docker network connect ネットワーク名 コンテナ名
$ docker network connect my_nw alpine1
$ docker network connect my_nw alpine2
```
上記では「my_nw」というネットワークに「alpine1」、「alpine2」のコンテナを接続している。

##コンテナ作成時にユーザー定義のネットワークに接続する。
```haml
-# docker run -itd --name 新しいコンテナ名 --network ネットワーク名 元のコンテナ
$ docker run -itd --name alpine3 --network my_nw alpine
```
--networkの引数に接続したいネットワークを指定することで、最初からそのネットワークで接続された状態で起動する。ちなみにネットワークを指定して起動した場合はデフォルトのブリッジネットワークには接続されていない状態で起動する。

##alpine2にアタッチして、alpine1、alpine3にpingを飛ばす。
```haml
-# alpine2でアタッチする
$ docker attach alpine2
-# 結果は省略
# Ping -w 3 alpine1
# Ping -w 3 alpine3
```
コンテナ名で通信できていることが確認できる。ユーザー定義のブリッジネットワークでは、dockerデーモンの組み込みDNSが起動して、コンテナ名で名前解決してくれる。なお、コンテナは複数のネットワークに接続することができる。

##ネットワークからコンテナを切断する
```haml
-# docker net disconnect ネットワーク名 コンテナ名
$ docker network disconnect bridge alpine2
-# alpine2の詳細、確認
$ docker inspect alpine2
```
「bridge」ネットワークが切断されて、「my_nw」ネットワークのみ接続されている。
ブリッジネットワークはインターネットに出ることできるが、デフォルトで外部に公開されていないネットワークになる。-pで指定したポートを解放することで外部からコンテナの指定ポートへアクセスすることができる。

##ノンネットワークとは
Driverが「null」の状態のネットワーク。「null」driverに接続したコンテナはループバックインターフェース以外にネットワークインターフェースを持たない状態。ノンネットワークを接続するコンテナはその他のネットワークを切断した状態にしないといけない。

##ホストネットワークとは
「host」driverを使用したネットワーク。ホストネットワークに接続したコンテナはdockerホストと同じネットワークを持つ。ホストネットワークのコンテナでwebサーバを起動した場合、ホストマシンのipの80番でリッスンしているのと同じ動作になる。 -pを使用しなくてもコンテナを起動しただけでdockerホストのipの80番にアクセスすれば、コンテナの80番ポートに接続することができる。

##nginxの起動
```haml
-# dockerホストのip確認
% docker-machine ip nw-vm1
-# ssh接続
% docker-machine ssh nw-vm1
-# 「host」ネットワークを使ってnginxを起動
$ docker run -d —name web —network host nginx
```
Ipアドレスでアクセスし、nginxが起動していることが確認できる。