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


概要

前回、CentOS7 + DockerでGitBucketを構築するでGitBucketを構築したので、これCentOS - Docker間のNAT設定を行い、外部からコンテナへアクセスする(絵きったな)

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

環境

CentOS 7.3.1611
Docker 18.03.1-ce

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

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

はい。

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

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

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

Docker0 ブリッジのカスタマイズ より

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
yum -y install NetworkManager
yum -y install firewalld

firewalldで各インターフェースを"zone"に登録します。
zoneについては下記サイトを参考にしました。
firewalldの設定方法(基本設定編)

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

1. 各IFのzoneを設定

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

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

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
$ 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
$ firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.0.2 --permanent

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

terminal
$ firewall-cmd --reload
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
$ firewall-cmd --zone=external --add-service=http --permanent

再起動して・・・

terminal
$ firewall-cmd --reload

確認!できてます!

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設定完了です!

感想

まだまだ運用していくには課題がたくさん・・・(パフォーマンス、セキュリティ等・・・)
随時更新します!(多分)