ipアドレスが決めうちになってる構成の時にいい感じにdockerでローカル開発環境を作るメモ

設定ファイルにipアドレスが書かれてるからネットワーク構成もそれに合わせないといけないよな〜なんて時があるので、そんな場合にネットワーク構成をそれに合わせてdockerのでローカル開発環境を作ろうというめもです。

# サンプル構成

下の例ではwebサーバが一つあり、そのサーバに192.168.123.100を割り当ててます。ついでなのでclientという名前の環境も作ってネットワークセグメントはwebとは別にしてます。


```yaml
version: '3'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.web
    image: web
    networks:
      web_segment:
        ipv4_address: 192.168.123.100

  client:
    build:
      context: .
      dockerfile: Dockerfile.cli
    image: client
    networks:
      - client_segment
      - web_segment
    extra_hosts:
      - "web.testserver.local:192.168.123.100"

networks:
  web_segment:
    driver: bridge
    ipam:
      config:
      -
        subnet: 192.168.123.0/24
  client_segment:
    driver: bridge
    ipam:
      config:
      -
        subnet: 192.168.221.0/24
```

# ネットワークの作成

ここでのポイントはservicesと同列の位置にある[networks](https://docs.docker.com/compose/compose-file/#aliases)です。具体的な設定は[ipam](https://docs.docker.com/compose/compose-file/#enable_ipv6)で行います。
ここでsubnetの定義をしてます。ここで設定したネットワークの設定をservicesにある項目のほうで使っています。ipamでのネットワーク設定ではsubnetくらいしか設定してません。ここのnetworksで設定するのはネットワークセグメントやドライバなどです。コンテナがどのネットワークを使うかはservicesにあるほうのコンテナのほうで行います。

ちなみにコマンドラインでネットワークを作るときは最小限でこんな感じです。

```
masami@fedora:~$ sudo docker network create --gateway 192.168.22.1 --subnet 192.168.22.0/24 nettest
98710ec5b4ca1c19d0c1c3fb42d6294ac170e28c63acb6ac69c6afca7e0dfe43
```

作成したネットワークを確認するとこうなります。

```
masami@fedora:~$ sudo docker network ls
NETWORK ID          NAME                         DRIVER              SCOPE
d526d647b658        bridge                       bridge              local
8834e6edd6a5        captest_default              bridge              local
9024ba2af993        docker-test_client_segment   bridge              local
b43e60ba2770        docker-test_web_segment      bridge              local
a508e1d80be0        host                         host                local
66a9b78f7c83        memlimittest_default         bridge              local
98710ec5b4ca        nettest                      bridge              local
e9b9a494cf26        none                         null                local
```

コマンドラインで作成したnettestの内容は以下のようになります。

```
masami@fedora:~$ sudo docker network inspect nettest
[
    {
        "Name": "nettest",
        "Id": "98710ec5b4ca1c19d0c1c3fb42d6294ac170e28c63acb6ac69c6afca7e0dfe43",
        "Created": "2018-10-25T11:46:26.698929821+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.22.0/24",
                    "Gateway": "192.168.22.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
```

docker-composeのほうで作成したネットワークはこうです。

```
masami@fedora:~$ sudo docker network inspect docker-test_client_segment
[
    {
        "Name": "docker-test_client_segment",
        "Id": "9024ba2af9936b6efb62df5dcc6fcf10e1f896dfece6d77379fd21bdbfee893b",
        "Created": "2018-10-25T11:29:25.637020828+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "192.168.221.0/24"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Containers": {},
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "client_segment",
            "com.docker.compose.project": "docker-test",
            "com.docker.compose.version": "1.22.0"
        }
    }
]
```

# コンテナのネットワーク設定

## web側の設定

webはweb_segmentを使って、ipアドレスを192.168.123.100で固定しています。

```
    networks:
      web_segment:
        ipv4_address: 192.168.123.100
```

## client側の設定

clientからwebへのアクセスはネットワークセグメントが違うのでどうやってセグメント越えようかな？と思ったのですが、単純にweb_segmentとclient_segmentを両方使うようにしました。こちらはipアドレスはdhcpで取得します。

```
    networks:
      - client_segment
      - web_segment
```

## 動作確認

これでwebのほうを起動した状態でclientのほうにログインしてwgetすればwebの方にアクセスできるのが確認できます。

クライアント側はこんな風になります。

webのほうにアクセスは当然できます。

```
masami@fedora:~/docker-test$ sudo docker-compose run client /bin/sh
/ # wget web.testserver.local
Connecting to web.testserver.local (192.168.123.100:80)
wget: server returned error: HTTP/1.1 404 Not Found
```

ネットワークを2個割り当ててるのでnicも2個あります。

```
/ # ip r
default via 192.168.221.1 dev eth0 
192.168.123.0/24 dev eth1 scope link  src 192.168.123.2 
192.168.221.0/24 dev eth0 scope link  src 192.168.221.2 
```

webのほうは1つしかネットワークを割り当ててないから1つですね。

```
masami@fedora:~/docker-test$ sudo docker-compose exec web /bin/sh
/ # ip r
default via 192.168.123.1 dev eth0 
192.168.123.0/24 dev eth0 scope link  src 192.168.123.100 
```

# すでにあるネットワークセグメントを使いたい場合

## dockerコマンドの場合

--networkオプションを使います。

```
masami@fedora:~/docker-test$ sudo docker run --network nettest -it alpine /bin/sh
/ # ip r
default via 192.168.22.1 dev eth0 
192.168.22.0/24 dev eth0 scope link  src 192.168.22.2 
/ # 
```

## docker-composeの場合

networksの設定のところで使いたいネットワーク名をネットワーク名として記述し、externalをtrueとします。

```
  nettest:
    external: true
```

コンテナ側は通常通りにネットワーク名を指定します。

```
  client2:
    image: alpine
    networks:
      - nettest
```

こうなります。

```
masami@fedora:~/docker-test$ sudo docker-compose run client2 /bin/sh
/ # ip r
default via 192.168.22.1 dev eth0 
192.168.22.0/24 dev eth0 scope link  src 192.168.22.2
```

# 後始末

要らなくなったネットワークは適宜消しましょう。。。