docker
CoreOS

Dockerコンテナが使用するIPレンジを変更する

More than 1 year has passed since last update.

環境はCentOS6.x以上もしくはCoreOS。Docker Docsに記載されている内容を実践して、少し知見を付け加えたものです。

前提:Dockerコンテナのネットワーク構成

Dockerサービスを起動すると自動的にdocker0と呼ばれるbridgeが作成され、すべてのコンテナはこのブリッジに接続される。

$ ip a show docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ba:8a:43:a5 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:baff:fe8a:43a5/64 scope link
       valid_lft forever preferred_lft forever

docker0はホスト側と競合しないIPレンジを自動で引っ張ってきて、自身のIPもそこから割り当てる。コンテナが起動されると、コンテナのeth0はveth(Virtual Ethernet)としてdocker0に接続され、先のIPレンジから固有のIPアドレスが付与される。

$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242ba8a43a5       no              veth114c2f3
                                                        veth11751c2
                                                        veth34ea7d8
$ docker inspect `docker ps -ql`|grep "IPAddress"
        "IPAddress": "172.17.0.34",

docker0が使用するIPはランダムではないらしく、動作を見た限りでは基本的に172.17.42.1/16が割り当てられている。

コンテナ用IPレンジの変更

172.17.0.0/16docker0に割り当てられると、当然ながらホストOSのルーティングテーブルも書き換わる。/16とかなり広いレンジのクラスBアドレスが割り当てられることから、既存ネットワークとの関係でこれが不都合となることは往々にしてある。その場合にはIPレンジを任意のものとすることができる。

追記(2016-06-07)

以下手順ではDocker用のブリッジをすべて手動で作成してからDockerを起動しているが、Dockerは起動時にブリッジを自動生成するため、オプションだけでブリッジのIPレンジを変えることができる。/etc/default/dockerでの起動オプションに、--fixed-cidr=192.168.1.0/25オプションでコンテナ用IPレンジが指定できる。

参照:Customize the docker0 bridge

ブリッジの手動作成

まず、すでにDockerが起動している場合はサービスを停止し、docker0のブリッジを破棄する。

$ sudo systemctl stop docker
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0

次に、新たな仮想ブリッジを手動で作成し、コンテナで使用したいIPレンジからIPアドレスを割り当てる。

$ sudo brctl addbr bridge0
$ sudo ip a add 192.168.1.1/24 dev bridge0
$ sudo ip link set dev bridge0 up

Docker起動オプションの設定

あとはオプション-b=bridge0を与えてDockerサービスを再起動すれば良い話だが、サービス起動時に永続的にオプションを付加させるため、/etc/default/dockerにこれを追記する。

$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker

systemd

さらにCentOS7やCoreOSで、Dockerがsystemd管理下にある場合、unitファイルを編集して/etc/default/dockerEnvironmentFileに指定する必要がある。

docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=docker.socket early-docker.target network.target
Requires=docker.socket early-docker.target

[Service]
EnvironmentFile=-/etc/default/docker
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
ExecStart=/usr/lib/coreos/dockerd daemon --host=fd:// $DOCKER_OPTS $DOCKER_OPT_BIP $DOCKER_OPT_MTU $DOCKER_OPT_IPMASQ

[Install]
WantedBy=multi-user.target

cloud-config.yml

CoreOSの場合はunitファイルの直接編集ができないため、cloud-config.ymlunitsで設定する。

cloud-config.yml
#cloud-config
coreos:
  units:
    - name: docker.service
      content: |
        [Unit]
        Description=Docker Application Container Engine
        Documentation=http://docs.docker.com
        After=docker.socket early-docker.target network.target
        Requires=docker.socket early-docker.target

        [Service]
        EnvironmentFile=-/etc/default/docker
        MountFlags=slave
        LimitNOFILE=1048576
        LimitNPROC=1048576
        ExecStart=/usr/lib/coreos/dockerd daemon --host=fd:// $DOCKER_OPTS $DOCKER_OPT_BIP $DOCKER_OPT_MTU $DOCKER_OPT_IPMASQ

        [Install]
        WantedBy=multi-user.target

サービス起動。

# CentOS6.x
$ sudo service docker start
# CentOS7.x
$ sudo systemctl daemon-reload
$ sudo systemctl start docker
# CoreOS
$ sudo coreos-cloudinit --from-file /usr/share/oem/cloud-config.yml
$ sudo systemctl start docker

TODO

ブリッジ作成を手でやってしまったので、起動時に自動生成できないか検討する。
先の追記で達成。

参考

Docker Network

/etc/default/docker

cloud-config.yml