docker のネットワーク (docker0) 設定変更

docker のデフォルトのネットワークアドレスを変更します。
ホスト側は `docker0` ネットワークインターフェースの IP アドレス変更、docker コンテナ側のネットワークアドレス(プール)の範囲を変更します。(IPv4 のみ)

# 前提 (docker バージョン)

```shell_session:docker&nbsp;バージョン
$ docker --version
Docker version 19.03.6, build 369ce74
$
```

- - -
~~【2020/03/21 追記】
**注:** 本稿で確認したのは x86_64 Ubuntu 18.04 上ですが、Rasbpian (buster) 上の docker で本稿の手順を試したところ、ネットワークが変更できず、dockerd が起動できませんでした。その場合は、`daemon.json` ファイルを削除してください。~~

【2020/03/22 追記】
icc (Inter-Container Communication) の設定が true のまま残っている場合には、エラーが発生しました。
「[docker のネットワーク (docker0) 設定変更 (icc 変更編) - Qiita](https://qiita.com/msi/items/ff03237c1e5f4cebad43)」に変更方法を書きましたので、そちらもご参照ください。
- - -

# ネットワーク(範囲)の変更
参照: [Configure and troubleshoot the Docker daemon | Docker Documentation](https://docs.docker.com/config/daemon/)
参照: [Customize the docker0 bridge | Docker Documentation](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/custom-docker0/)

以下の手順で、ネットワークの変更を行います。

1. 現状の確認
2. 設定ファイルの作成
3. dockerd の再起動
4. 設定反映の確認


## 現状の確認
まずは、設定変更前の状態を確認しておきます。

コマンド `ip addr show dev docker0` と `docker network inspect bridge` を実行して設定状態を確認します。

```shell_session:docker0インタフェースの確認&nbsp;(ip&nbsp;addr&nbsp;show&nbsp;dev&nbsp;docker0)
$ ip addr show docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:a3:f4:1d:e1 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
$
```

```json:docker&nbsp;brigdeの確認&nbsp;(docker&nbsp;network&nbsp;inspect&nbsp;bridge&nbsp;と&nbsp;ip&nbsp;addr&nbsp;show&nbsp;docker0)
$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "1aa4683e24270539e0d55f04fb90256e3110ece305e6c6b37408e202fc49d33e",
        "Created": "2020-02-14T22:11:59.222703633+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",         <- ネットワークレンジ
                    "Gateway": "172.17.0.1"            <- brigde (docker0) の IPアドレス
                }
            ]
        },
        "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": {}
    }
]
$ 
```

デフォルトでは、ホストの bridge (docker0) のアドレスが `172.17.0.1`、割り当てのネットワーク範囲が `172.17.0.0/16` になっています。

## 設定ファイルの作成

`docker0` インターフェース (bridge) は、`dockerd` によって作成されます。
IP アドレスを変更するには下の2つの方法があります。

1. 設定ファイルに記述する。
2. 起動時の引数で指定する。

ここでは、設定ファイルで変更する方法を記載しておきます。

daemon の設定ファイルは下の通りです。

* Linux: `/etc/docker/daemon.json`
* Windows: `C:\ProgramData\docker\config\daemon.json`

デフォルトでは存在しないので、作成します。

```json:/etc/docker/daemon.json&nbsp;(新規作成)
{
        "bip": "172.20.0.254/24"
}
```

上の例では、ホスト側の (bridge) IP アドレスを `172.20.0.254` に、docker クライアントのアドレスプール (ネットワークアドレス) を `172.20.0.0/24` に設定します。
`bip` の "`172.20.0.254/24`" は 24ビットマスクの (`172.20.0.254` を含む範囲の) ネットワークアドレスです。

`--option=` で指定するオプション (_option_) は `daemon.json` に記述できます。

上の設定は、dockerd の起動オプションに `--bip=172.20.0.254/24` を指定したのと同じ意味になります。

同じネットマスクで `fixed-cidr` を設定している例を見かけますが、`bip` のネットワークレンジ(範囲)と CIDR のレンジが同じであれば、`fixed-cidr` を指定する必要はありません。


## dockerd の再起動

設定が終わったら、`dockerd` を再起動します。

```shell_session:再起動
$ sudo systemctl restart docker
```


## 設定変更後の確認

実施した設定で、ブリッジの設定が変更されていることを確認します。

デフォルトのホスト側ネットワークインタフェースは `docker0` ですので、これを確認します。

```shell_session:インタフェースの変更確認&nbsp;(ip&nbsp;addr&nbsp;show&nbsp;dev&nbsp;docker0)
$ ip addr show dev docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:00:cf:b5:ba brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.254/24 brd 172.20.0.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::c1fd:cbf0:c006:8663/64 scope link
       valid_lft forever preferred_lft forever
$
```

ブリッジ (bridge) を確認します。

```json:bridge&nbsp;の変更確認&nbsp;(docker&nbsp;network&nbsp;inspect&nbsp;bridge)
$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "784e35bf73471e88a2bd8450e91c2de6b5c297875a78ca2b34af74a1772296c8",
        "Created": "2020-02-15T01:16:39.444039309+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.20.0.254/24",
                    "Gateway": "172.20.0.254"
                }
            ]
        },
        "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": {}
    }
]
```

## `fixed-cidr` の併用

`fixed-cidr` を指定するのは、`bip` で指定したネットワークレンジよりも狭い範囲を指定する場合です。

例えば、bridge の IP アドレスを `172.20.0.254` (ネットワークアドレスを 24ビットマスク `172.20.0.0/24` = `172.20.0.0` ～ `172.20.0.255`) にし、CIDR レンジを 25ビットマスク `172.20.0.128/25` (`172.20.0.128` ～ `172.20.0.255`) とするような場合です。

```json:/etc/docker/daemon.json&nbsp;fixed-cidr&nbsp;例1&nbsp;(ネットマスクの値が異なっているところがポイント)
{
        "bip": "172.20.0.254/24",
        "fixed-cidr": "172.20.0.128/25"
}
```

これは、dockerd の起動オプションに `--bip=172.20.0.254/24 --fixed-cidr=172.20.0.128/25` を指定したのと同じ意味になります。

`bip` に合わせて、`172.20.0.254/25` と記載することもできます。

```json:/etc/docker/daemon.json&nbsp;fixed-cidr&nbsp;例2&nbsp;(ネットマスクの値が異なっているところがポイント)
{
        "bip": "172.20.0.254/24",
        "fixed-cidr": "172.20.0.254/25"
}
```

例1の記載方法でも、例2の記載方法でも、反映される設定は同一です。

```json:dockerd再起動とbridge設定確認
$ sudo systemctl restart docker && docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "711fc4ed0209dd8e2e34b4f922286db4f3f205f1f471dbadf706839883dd99d7",
        "Created": "2020-02-15T14:45:57.486131257+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.20.0.254/24",
                    "IPRange": "172.20.0.128/25",
                    "Gateway": "172.20.0.254"
                }
            ]
        },
        "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": {}
    }
]
```

---

以下は、補足。

# ネットワーク設定の確認

ネットワーク設定を確認します。

## ホストの `docker0` インタフェース
docker が使える環境 (docker daemon が動いている環境) では、ホストのネットワークインタフェースとして、デフォルトでは `docker0` が構成されています。

```shell_session:docker0&nbsp;インターフェース
$ ip addr show dev docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:00:cf:b5:ba 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
    inet6 fe80::c1fd:cbf0:c006:8663/64 scope link
       valid_lft forever preferred_lft forever
$
```

デフォルトでは、上の例のようにネットワークアドレスが `172.17.0.0/16` (= `172.17.0.0/255.255.0.0`) となり、ホストの `docker0` インタフェースのアドレスは `172.17.0.1` に設定されます。

## docker のデフォルト設定の確認
docker のネットワーク設定を確認するには `docker network` コマンドを使います。

```text:man&nbsp;docker-network(1)
DOCKER(1)                                                            DOCKER(1)

NAME
       docker-network - Manage networks

SYNOPSIS
       docker network

DESCRIPTION
       Manage networks

OPTIONS
       -h, --help[=false]
           help for network

SEE ALSO
       docker(1), docker-network-connect(1), docker-network-create(1),
       docker-network-disconnect(1), docker-network-inspect(1),
       docker-network-ls(1), docker-network-prune(1), docker-network-rm(1)

Docker Community                   Feb 2020                          DOCKER(1)
```

### docker ネットワークドライバの一覧
`docker network ls` コマンドで docker ネットワークドライバの一覧を確認します。

```text:man&nbsp;docker-network-ls(1)
DOCKER(1)                                                            DOCKER(1)

NAME
       docker-network-ls - List networks

SYNOPSIS
       docker network ls [OPTIONS]

DESCRIPTION
       Lists all the networks the Engine daemon knows about. This includes the
       networks that span across multiple hosts in a cluster, for example:

                  $ docker network ls
                  NETWORK ID          NAME                DRIVER          SCOPE
                  7fca4eb8c647        bridge              bridge          local
                  9f904ee27bf5        none                null            local
                  cf03ee007fb4        host                host            local
                  78b03ee04fc4        multi-host          overlay         swarm

       Use the --no-trunc option to display the full network id:

              $ docker network ls --no-trunc
              NETWORK ID                                                         NAME                DRIVER
              18a2866682b85619a026c81b98a5e375bd33e1b0936a26cc497c283d27bae9b3   none                null
              c288470c46f6c8949c5f7e5099b5b7947b07eabe8d9a27d79a9cbf111adcbf47   host                host
              7b369448dccbf865d397c8d2be0cda7cf7edc6b0945f77d2529912ae917a0185   bridge              bridge
              95e74588f40db048e86320c6526440c504650a1ff3e9f7d60a497c4d2163e5bd   foo                 bridge
              63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161   dev                 bridge

＜略＞
OPTIONS
       -f, --filter=
           Provide filter values (e.g. 'driver=bridge')

       --format=""
           Pretty-print networks using a Go template

       -h, --help[=false]
           help for ls

       --no-trunc[=false]
           Do not truncate the output

       -q, --quiet[=false]
           Only display network IDs

SEE ALSO
       docker-network(1)

Docker Community                   Feb 2020                          DOCKER(1)
```

```shell_session:docker&nbsp;ネットワークドライバ一覧&nbsp;(docker&nbsp;network&nbsp;ls)
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1aa4683e2427        bridge              bridge              local
85fa1cc162f0        host                host                local
756cc38e0f4e        none                null                local
$
```

### docker bridge の確認
`docker network inspect` コマンドで上に表示された `bridge` を指定して設定を確認します。

```json:docker&nbsp;brigdeの確認&nbsp;(docker&nbsp;network&nbsp;inspect&nbsp;bridge)
$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "1aa4683e24270539e0d55f04fb90256e3110ece305e6c6b37408e202fc49d33e",
        "Created": "2020-02-14T22:11:59.222703633+09:00",
        "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": {}
    }
]
$
```

デフォルトの設定は `172.17.0.0/16` ネットワークになっています。

```json
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
```

参考: [Customize the docker0 bridge | Docker Documentation](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/custom-docker0/)