環境は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/16
がdocker0
に割り当てられると、当然ながらホスト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/docker
をEnvironmentFile
に指定する必要がある。
[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.yml
のunits
で設定する。
#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
- DOCKER_OPTS do not work in config file /etc/default/docker · Issue #9889 · docker/docker
- Configuring and running Docker