CentOS7 + DockerでNAT設定し、コンテナにアクセスする

# 概要
前回、[CentOS7 + DockerでGitBucketを構築する](https://qiita.com/tsumasakky/items/ff653426ea3bc7dbcbfb)でGitBucketを構築したので、これCentOS - Docker間のNAT設定を行い、外部からコンテナへアクセスする（絵きったな）

※夕方書いたので？適当すぎて参考にならない可能性あり orz
　随時更新予定！

![dockernetwork.png](https://qiita-image-store.s3.amazonaws.com/0/147118/5239130f-4229-7d38-f03b-f34fc9c2c4c0.png)



# 環境
CentOS 7.3.1611
Docker 18.03.1-ce

# docker0ブリッジのネットワーク設定

IPアドレス割り当てたかったから割り当てたのだ（早口言葉）

はい。

Dockerをインストールした後、`ifconfig`コマンドを実行すると、docker0というネットワークインターフェースが増えています。これのIPアドレスを変更していきます。

下記ファイルを編集してください。（ファイルが存在しない場合は新規作成します。）

```terminal:terminal
$ sudo vi /etc/docker/daemon.json
```
```terminal:daemon.json
{
  "bip": "192.168.0.1/24",
  "fixed-cidr": "192.168.0.0/24"
}
```

```terminal:terminal
$ sudo systemctl daemon-reload
```

[Docker0 ブリッジのカスタマイズ](http://docs.docker.jp/v1.12/engine/userguide/networking/default_network/custom-docker0.html) より
> bip
--bip-CIDER は bridge0 ブリッジに対して特定の IP アドレスとネットマスクを指定、ここでは 192.168.1.5/24 のような通常の CIDR で指定します。

> fixed-cidr
docker0 サブネットが使う IP 範囲を、 172.167.1.0/28 のような標準的な CIDR 形式で指定します。この範囲は IPv4 で固定する（例： 10.20.0.0/16 ）必要があり、ブリッジの IP 範囲（ docker0 あるいは --bridge で指定 ）のサブセットである必要もあります。例えば --fixed-cidr=192.168.1.0/25 を指定したら、コンテナの IP アドレスは前半の 192.168.1.0/24 サブネットから割り当てられます。

このようにしてdocker0に`192.168.0.1`を割り当てます。
ちなみにこのときのeth0のIPアドレスは`172.16.18.100`です。

# 現状
IPアドレス
eth0: 172.16.18.100
docker0: 192.168.0.1
GitBucketコンテナ: 192.168.0.2

やりたいのは･･･
クライアントからhttp://172.16.18.100/ にアクセス
↓
NATで172.16.18.100:80 -> 192.168.0.2:8080 にフォワード
です。

コンテナのIPアドレスはコンテナ起動時に都度割り振られます。
空いているアドレスから割り振るようで、現状コンテナが1つしかないので
毎回上記のアドレスとなっています。今回はひとまずIP固定は行っていません。

# NAT設定

NAT設定方法を調べてみるといくつかやり方があるみたいですが、CentOS7はNetworkManagerとfirewalldで設定できます。

```terminal:terminal
yum -y install NetworkManager
yum -y install firewalld
```

firewalldで各インターフェースを"zone"に登録します。
zoneについては下記サイトを参考にしました。
[firewalldの設定方法（基本設定編）](https://www.server-memo.net/centos-settings/firewalld/firewalld.html#i)

今回はインターフェース:eth0をexternalに、インターフェース:docker0をinternalに設定します。

## 1. 各IFのzoneを設定

```terminal:terminal
$ nmcli c mod eth0 connection.zone external
```
```terminal:terminal
$ nmcli c mod docker0 connection.zone internal
```

各IFの情報は`/etc/sysconfig/network-scripts/ifcfg-[IF名]`で確認できます。

```terminal:terminal
$ cat /etc/sysconfig/network-scripts/ifcfg-docker0
DEVICE=docker0
STP=no
TYPE=Bridge
BOOTPROTO=none
IPADDR=192.168.0.1
PREFIX=24
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV4_DNS_PRIORITY=100
IPV6INIT=yes
IPV6_AUTOCONF=no
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
IPV6_DNS_PRIORITY=100
NAME=docker0
UUID=00858b8d-a6d4-4c7b-9e01-e22541dfbcb1
ONBOOT=no
ZONE=internal
```
docker0の場合、`ZONE=internal`としっかり設定されていますね。

## 2. IPマスカレード設定
external側のゾーンにIPマスカレードの設定を行います。
設定は一時的なもので、再起動するとリセットされるため、「--permanent」コマンドで永続化します。

externalに登録されているインターフェースを確認するには下記のコマンドが便利です。

```terminal:terminal
$ firewall-cmd --list-all --zone=external
  external (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:
```
`interfaces: eth0`
`masquerade: yes`
となっていればOKです。

## 3. 転送設定
CentOSの80番ポートにきたアクセスを192.168.0.2:8080にフォワードします。

```terminal:terminal
$ firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.0.2 --permanent
```

firewalldを再起動してから確認します。

```terminal:terminal
$ firewall-cmd --reload
```


```terminal:terminal
$ firewall-cmd --list-all --zone=external
external (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports: port=80:proto=tcp:toport=8080:toaddr=192.168.0.2
  sourceports:
  icmp-blocks:
  rich rules:
```

`forward-ports: port=80:proto=tcp:toport=8080:toaddr=192.168.0.2`
となっていればOKです。

## 4. サービスの追加
externalゾーンはデフォルトでssh接続のみを許可していため、http通信を可能とするため、httpサービスを追加します。

```terminal:terminal
$ firewall-cmd --zone=external --add-service=http --permanent
```

再起動して･･･

```terminal:terminal
$ firewall-cmd --reload
```

確認！できてます！

```terminal:terminal
$ firewall-cmd --list-all --zone=external
  external (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: http ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports: port=80:proto=tcp:toport=8080:toaddr=192.168.0.2
  sourceports:
  icmp-blocks:
  rich rules:
```

`services: http ssh`
のように、サービスにhttpが追加されました。

# 接続確認
ブラウザからhttp://172.16.18.100/ にアクセスすると、表示されました！NAT設定完了です！

# 感想
まだまだ運用していくには課題がたくさん･･･（パフォーマンス、セキュリティ等･･･）
随時更新します！（多分）