前回の「Dockerのネットワークをbridgeで外と繋げる」では、マシン1台を例に説明しましたが、複数台でも同じように外へ繋ぐことができます。ただ、ゲートウェイの設定部分に少だけ工夫が必要なので、そこだけ注意が必要です。
では参考に、下記のような構成を例にして説明します。
Host | IP Address |
---|---|
MacBook | 192.168.33.1 |
host1(VirtualBox) | 192.168.33.10 |
host2(VirtualBox) | 192.168.33.11 |
container1(on host1) | 192.168.33.21 |
container2(on host1) | 192.168.33.22 |
container3(on host2) | 192.168.33.23 |
container4(on host2) | 192.168.33.24 |
Vagrantfile
を準備する
Vagrant.configure(2) do |config|
config.vm.define "host1" do |host1|
host1.vm.box = "ubuntu/trusty64"
host1.vm.hostname = "host1"
host1.vm.network "private_network", ip: "192.168.33.10"
end
config.vm.define "host2" do |host2|
host2.vm.box = "ubuntu/trusty64"
host2.vm.hostname = "host2"
host2.vm.network "private_network", ip: "192.168.33.11"
end
config.vm.provider "virtualbox" do |v|
v.memory = "2048"
# ネットワークアダプタに変更を加える
v.customize ['modifyvm', :id, '--nictype1', 'Am79C973']
v.customize ['modifyvm', :id, '--nicpromisc1', 'allow-all']
v.customize ['modifyvm', :id, '--nictype2', 'Am79C973']
v.customize ['modifyvm', :id, '--nicpromisc2', 'allow-all']
end
# bridge-utilsをインストールする
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get -y install bridge-utils
SHELL
end
Dockerマシンを作る
# host1とhost2を立ち上げます
$ vagrant up
# host1をDockerマシンにします
$ docker-machine create \
--driver "generic" \
--generic-ip-address 192.168.33.10 \
--generic-ssh-user vagrant \
--generic-ssh-key .vagrant/machines/host1/virtualbox/private_key \
--generic-ssh-port 22 \
host1
# host2をDockerマシンにします
$ docker-machine create \
--driver "generic" \
--generic-ip-address 192.168.33.11 \
--generic-ssh-user vagrant \
--generic-ssh-key .vagrant/machines/host2/virtualbox/private_key \
--generic-ssh-port 22 \
host2
host1にブリッジdocker1
とネットワークshared_nw
を作る
# host1にログインします
$ vagrant ssh host1
# eth1のIPアドレスを削除します
$ sudo ip addr del 192.168.33.10/24 dev eth1
# "shared_nw"と"docker1"を作ってサブネットとゲートウェイを
# 設定します
$ sudo docker network create \
--driver bridge \
--subnet=192.168.33.0/24 \
--gateway=192.168.33.10 \
--opt "com.docker.network.bridge.name"="docker1" \
shared_nw
# docker1をeth1に接続します
$ sudo brctl addif docker1 eth1
ここで理解しておきたい点は、docker network create
の際にdocker1
に192.168.33.10がアサインされることです(ifconfig docker1
で確認できます)。次のステップでは少しだけ工夫してhost2
のコンテナに対してもこのIPアドレスをゲートウェイに指定します。
host2にブリッジdocker1
とネットワークshared_nw
を作る
# host2にログインします
$ vagrant ssh host2
# eth1のIPアドレスを削除します
$ sudo ip addr del 192.168.33.11/24 dev eth1
# "shared_nw"と"docker1"を作ってサブネットとゲートウェイを
# 設定します
$ sudo docker network create \
--driver bridge \
--subnet=192.168.33.0/24 \
--gateway=192.168.33.10 \
--opt "com.docker.network.bridge.name"="docker1" \
shared_nw
# docker1にアサインされてしまった192.168.33.10を削除して
# 192.168.33.11をアサインします
$ sudo ip addr del 192.168.33.10/24 dev docker1
$ sudo ip addr add 192.168.33.11/24 dev docker1
# docker1をeth1に接続します
$ sudo brctl addif docker1 eth1
コンテナを作る
host2からログアウトしてMacBookに戻ります。それからhost1とhost2のshared_nw
上に固定IPでコンテナを作ります。環境の切替を簡単化するために$on_host1
と$on_host2
に設定を入れておくと便利です。
$ on_host1=$(docker-machine config host1)
$ on_host2=$(docker-machine config host2)
$ docker $on_host1 run --name container1 --net shared_nw --ip 192.168.33.21 -dt ubuntu
$ docker $on_host1 run --name container2 --net shared_nw --ip 192.168.33.22 -dt ubuntu
$ docker $on_host2 run --name container3 --net shared_nw --ip 192.168.33.23 -dt ubuntu
$ docker $on_host2 run --name container4 --net shared_nw --ip 192.168.33.24 -dt ubuntu
設定がうまく行っていれば、ちゃんとpingが通ります。試しにcontainer1のシェルから下記のような手順で確認できます。
$ docker $on_host1 ps | grep container1
# 例:container1のIDがf90891c5448eだった場合
$ docker $on_host1 exec -it f90891c5448e bash
$ ping -c 3 192.168.33.1 # --> macbook
$ ping -c 3 192.168.33.10 # --> host1
$ ping -c 3 192.168.33.11 # --> host2
$ ping -c 3 192.168.33.22 # --> container2
$ ping -c 3 192.168.33.23 # --> container3
$ ping -c 3 192.168.33.24 # --> container4
$ ping -c 3 www.google.com
この構成でいけば、ネットワークの見通しがすっきりしているので、オンプレミスのDocker導入がスムーズになりそうですね。
ネットワークの設定を恒久的にする
再起動後も設定が残るようにするために、ここでも少し工夫が必要になります。まずはhost1
とhost2
の/etc/network/interfaces
のeth1
の設定を下記のように変更します。
auto eth1
iface eth1 inet manual
pre-up ifconfig $IFACE up
post-down ifconfig $IFACE down
それから/etc/rc.local
のexit 0
の前に下記のコマンドを付け足します。
brctl addif docker1 eth1
ip addr del 192.168.33.10/24 dev docker1
ip addr add 192.168.33.11/24 dev docker1
brctl addif docker1 eth1
実際に再起動して確認してみてください。
この程度のハックであれば、そんなにメンテナンスの手間にはならないと思うのですが、もう少しいい方法を知っている(あるいは見つけた)方はコメントを下さい。よろしくお願いします。
後片付け
テストが終わって要らなくなったDockerマシンは下記の手順で削除できます。
$ docker $on_host1 stop $(docker ps -aq)
$ docker $on_host1 rm $(docker ps -aq)
$ docker $on_host2 stop $(docker ps -aq)
$ docker $on_host2 rm $(docker ps -aq)
$ docker-machine rm host1
$ docker-machine rm host2
$ vagrant destroy
理解を深める
Dockerのbridgeについて理解を深めたい方は下記リンクの"Building your own bridge"と"How Docker networks a container"を読むと勉強になります。