さわっておぼえるDocker入門🐳#3（コンテナの仮想ネットワーク）


# はじめに

Dockerコンテナがどのようにネットワークを構成しているかを確認します。


# 目的

**Dockerを触りながら、コンテナ同士のネットワークを確認する**

今回は、下記の操作を行います。

- コンテナのIPアドレスを確認
- コンテナ用の仮想ネットワークを確認
- 仮想ネットワークのファイアウォールを確認
- 新しい仮想ネットワークの作成
- コンテナを新しいネットワークで起動
- コンテナを別のネットワークに接続する
- コンテナのDNSを確認する

# 環境

- macOS Mojave 10.14.6
- Docker engine 19.03.5


# まずはDockerのインストール

https://www.docker.com/


# コンテナをアレコレしてみる


## まずはコンテナを起動

以下のコマンドは、nginxのコンテナを起動します。

- `-p`オプションによって、`80:80`のポートを開いています。
- `-d`オプションによって、バックグラウンドでコンテナが起動します。
- `--name`オプションによって、`nginx`と名付けました。


```bash
docker container run -p 80:80 -d --name nginx nginx
```

## `container port`

以下のコマンドを実行することで、指定したコンテナのどのポートが通信を受け付けているか確認できます。

```bash
docker container port nginx
```

## `--format {{.NetworkSettings.IPAddress}}`

コンテナのIPアドレスを確認するには、以下のコマンドを実行します。

```bash
docker container inspect --format {{.NetworkSettings.IPAddress}} nginx
# 172.17.0.2
```

`172.17.0.2`とIPアドレスが表示されました。
これはどこから来ているのでしょうか。


### ホストのIPアドレスとコンテナのIPアドレス

試しに、ホストのIPアドレスを調べてみます。

```bash
ifconfig en0
#en0: flags=8888<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
#	ether 8a:88:88:54:67:8f 
#	inet6 fe88::897:4382:278d:2dfa%en0 prefixlen 64 secured scpeid 0x8 
#	inet 192.168.11.13 netmask 0xffffff00 broadcast 192.168.11.255
#	nd6 options=201<PERFORMNUD,DAD>
#	media: autoselect
#	status: active
```

どうもホストのIPとは異なるIPアドレスがコンテナに割り当てられているようです。


### 仮想ネットワーク「ブリッジ」

結論から言うと、コンテナのIPアドレスは
コンテナ用の仮想ネットワークのIPアドレスから割り当てられています。

コンテナが新しく作られると、そのコンテナは「ブリッジ」と呼ばれるデフォルトの仮想ネットワークに紐づけられます。

ブリッジは、ホストOSのイーサネットインターフェースに繋がっているので、コンテナも外との通信ができるようになっています。

先ほどコンテナを起動する際に指定した`-p 80:80`は、

ホストOSのポート80番を開き、80番ポートへの通信は全て仮想ネットワーク「ブリッジ」を通じてコンテナに転送されています。


### 仮想ネットワークのファイアウォール

反対に`-p`オプションを指定しなければ、コンテナは外と通信できないことになります。
これは簡易的なファイアウォールであり、
こちらから`-p`で通信を許可しない限り、コンテナは基本的にプライベートなものです。


#### コンテナを追加したら

もし、ここに新しいコンテナを追加するとどうなるでしょうか。
なお今回は、**`-p`オプションを使用しないでコンテナを起動します。**

```bash
docker container run -d --name second nginx
```


最初のnginxコンテナと同じく、ブリッジにコンテナは接続されています。
**同じ「ブリッジ」ネットワークにいるので、一つ目のコンテナと二つ目のコンテナは互いに通信が可能**です。


しかし、二つ目のコンテナは`-p`オプションを使用していないので、ホストOS側ではどのポートも通信を待ち受けていません。
したがって、**二つ目のコンテナは外部からは遮断されたコンテナということになります。**

- 一つ目の外部と通信できるコンテナはWebサーバーなどに使用できるパブリックなコンテナ
- 二つ目のコンテナはインターネットには繋がっていないプライベートなコンテナなので、DBなどに使えます



## `network ls`

仮想ネットワークを確認するには、以下のコマンドを実行します。
「bridge」ネットワーク、つまりデフォルトのコンテナ用ネットワークが確認できるかと思います。

```bash
docker network ls
```


## `network inspect`

指定したネットワークの状態を確認します。
以下のコマンドは`bridge`ネットワークの状態を確認するコマンドです。

```bash
docker network inspect bridge
```

bridgeネットワーク内にどのコンテナが存在しているかも、ここから確認することができます。

```
$~ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "48a7de8fa4625a82b06468c37a5446a044a",
        ...
        "IPAM": {
            ...
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        ...
        "Containers": {
            "92827df330b042420f96619ce2476127c9d2c1": {
                "Name": "nginx",
                ...
                "IPv4Address": "172.17.0.2/16",
                ...
            },
            "c76508a92f8ed89d054b4bbba16e3f64ecb48b": {
                "Name": "second",
                ...
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },
```

また、`IPAM(IP address management)`を確認することで、サブネットのデフォルトIPアドレスを確認できます。
ここでは、
`"Subnet": "172.17.0.0/16"`となっていますね。


コンテナのIPアドレスは

- 一つ目のコンテナ：`"172.17.0.2/16"`
- 二つ目のコンテナ：`"172.17.0.3/16"`

となっています。

コンテナのIPが、サブネットのIPアドレスの範囲内にありますので、
ちゃんとサブネット内にコンテナが存在していることがここからも確認できます。


## `network create`

では今度は、デフォルトの「ブリッジ」ではなく自分で仮想ネットワークを作ります。

以下のコマンドを実行することで`mynet`という名前の仮想ネットワークを作成できます。


```bash
docker network create mynet
```


## `--network`

`--netowork`オプションを使用することで、指定したネットワークでコンテナを起動することができます。


```bash
docker container run -d --name proxy --network mynet nginx
```


## `network connect`

コンテナを別のネットワークに繋げることもできます。

```bash
docker network connect 2ed32 92827
```

-  `2ed32`（新しい`mynet`ネットワークのID）
-  `92827`（ブリッジネットワークの`nginx`コンテナのID）

ここでは、ブリッジネットワークの`nginx`コンテナを`mynet`ネットワークに繋げています。

コンテナが移動したわけでははないので、

ブリッジにも`nginx`コンテナは繋がっていますし
`mynet`にも繋がっている状態になっています。



## `network disconnect`

もちろん、接続を断つコマンドもあります。
が、今回は省略します。


## コンテナのDNS

このように、ブリッジをはじめとするコンテナ用サブネットや、コンテナそのものにはIPアドレスが割り当てられていますが、**コンテナを運用する上でIPアドレスを使用することは推奨されていません。代わりにコンテナやネットワークにつけた名前を使用します。**

なぜなら、コンテナは作ったり、削除したり、移動したりするからです。
また、コンテナを立ち上げる順番なども、運用する環境によって変わってしまうかもしれません。

そうした環境においてはIPアドレスは常に一定ではありません。

しかし、DockerにはDNSが標準で組み込まれていますので、
（これまでも使用してきたように）名前を使用してコンテナやネットワークを指定することができますし、そのほうが安定します。


# まとめ


- コンテナのIPアドレスを確認
- コンテナ用の仮想ネットワークを確認
- 仮想ネットワークのファイアウォールを確認
- 新しい仮想ネットワークの作成
- コンテナを新しいネットワークで起動
- コンテナを別のネットワークに接続する
- コンテナのDNSを確認する


上記の内容を、実際に手を動かしながら確認することで、
コンテナがホストOS上に作られた仮想ネットワーク上で動いていることがざっくり分かりました。