bridge
、host
、none
のネットワークがありますbridge
のネットワークをブリッジネットワークと記載しますbridge
というブリッジネットワークが作成されますbridge
ネットワークのネットワークインターフェースがdocker0
^docker0になりますdocker run
などでネットワークを指定しない場合は、コンテナはデフォルトのブリッジネットワークであるbridge
に配置されます今回はブリッジネットワークを新規に作成して、Dockerネットワークの通信を見ていきます。
ユーザーが作成したブリッジネットワークをユーザー定義ブリッジネットワークと呼びます。
作成するネットワークは以下のようになります。
まずは新規にブリッジネットワークを作成する前のホスト
のネットワークインターフェースとルートテーブルを確認しておきます。
以降コマンドの発行結果は本記事に直接関係のない内容を適宜省略しています。
ネットワークインターフェースを確認します。
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 06:b5:10:1f:21:cd brd ff:ff:ff:ff:ff:ff
inet 10.3.0.183/24 brd 10.3.0.255 scope global dynamic eth0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:bc:b0:20:a7 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
ネットワークインターフェースは3つです。
1: lo
: ループバックのネットワークインターフェース(172.0.0.1
)2: eth0
:ホストのデフォルトのネットワークインターフェース(10.3.0.183/24
)(デフォルトゲートウェイと接続された10.3.0.183/24
のネットワークインターフェース)4: docker0
:Dockerをインストールした時に作成されるデフォルトのブリッジネットワークインターフェース(172.17.0.1/16
)ルートテーブルを確認します。
$ route -ne
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.3.0.1 0.0.0.0 UG 0 0 0 eth0
10.3.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.3.0.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
新しくブリッジネットワークを作成します。
ネットワーク名はsample
にします。
$ sudo docker network create sample
29faca36a6b4...
ホスト
に仮想ブリッジ(br-29faca36a6b4
)が作成されますホスト
に仮想ブリッジのネットワークインターフェース(br-29faca36a6b4
)が作成されます例ではブリッジとブリッジのネットワークインターフェースが同じ名前になっています。
ブリッジを確認します。
$ sudo brctl show
bridge name bridge id STP enabled interfaces
br-29faca36a6b4 8000.0242846801c8 no
ブリッジbr-29faca36a6b4
が作成されています。
ネットワークインターフェースを確認します。
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 06:b5:10:1f:21:cd brd ff:ff:ff:ff:ff:ff
inet 10.3.0.183/24 brd 10.3.0.255 scope global dynamic eth0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:bc:b0:20:a7 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
5: br-29faca36a6b4: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:c1:07:54:7f brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-29faca36a6b4
br-29faca36a6b4
インターフェース(172.168.0.1)が追加されています。
ルートテーブルを確認します。
$ route -ne
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.3.0.1 0.0.0.0 UG 0 0 0 eth0
10.3.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.3.0.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-29faca36a6b4
ルートテーブルに172.18.0.0/16
のルートが追加されています。
sample
ネットワークにコンテナを追加します。
コンテナ名はcontainer1
にします。
$ sudo docker run -itd --name container1 --net sample ubuntu:latest
daf864877355...
$ sudo docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
daf864877355 ubuntu:latest "bash" 2 days ago Up 58 minutes container1
ネットワークインターフェースを確認します。
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 06:b5:10:1f:21:cd brd ff:ff:ff:ff:ff:ff
inet 10.3.0.183/24 brd 10.3.0.255 scope global dynamic eth0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:bc:b0:20:a7 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
5: br-29faca36a6b4: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default <--- sampleの仮想ネットワークインターフェース
link/ether 02:42:c1:07:54:7f brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-29faca36a6b4
7: veth7a0c3b1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-29faca36a6b4 state UP group default
link/ether 12:b9:a1:ec:09:76 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::10b9:a1ff:feec:976/64 scope link
ホスト
にコンテナ(container1)とブリッジを接続するveth(仮想イーサネット)のブリッジ側ネットワークインターフェースveth7a0c3b1@if6
が追加されています。
(仮想イーサネットは両端にネットワークインターフェースを持つます。)
コンテナ内のネットワークインターフェースを確認します。
$ sudo docker exec -it container1 /bin/bash
root@daf864877355:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
コンテナにeth0@if7
ネットワークインターフェースが作成されています。eth0@if7
ネットワークインターフェースはブリッジ側のveth7a0c3b1@if6
ネットワークインターフェースと接続されています^@interface。
コンテナのルートテーブルを確認します。
ゲートウェイに172.18.0.1
が設定されています。
$ route -ne
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 172.18.0.1 0.0.0.0 UG 0 0 0 eth0
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
コンテナを追加します。
コンテナ名はcontainer2にします。
$ sudo docker run -itd --name container2 --net sample ubuntu:latest
31abe1533cfe...
$ sudo docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
31abe1533cfe ubuntu:latest "bash" 2 days ago Up About an hour container2
ネットワークインターフェースを確認します。
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 06:b5:10:1f:21:cd brd ff:ff:ff:ff:ff:ff
inet 10.3.0.183/24 brd 10.3.0.255 scope global dynamic eth0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:bc:b0:20:a7 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
5: br-29faca36a6b4: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default <--- sampleの仮想ネットワークインターフェース
link/ether 02:42:c1:07:54:7f brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-29faca36a6b4
7: veth7a0c3b1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-29faca36a6b4 state UP group default <----- container1のネットワークインターフェース
link/ether 12:b9:a1:ec:09:76 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::10b9:a1ff:feec:976/64 scope link
9: veth2a5f404@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-29faca36a6b4 state UP group default <----- container2のネットワークインターフェース
link/ether 3a:aa:3b:e3:ed:9b brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::38aa:3bff:fee3:ed9b/64 scope link
ホスト
にコンテナ(container2)とブリッジを接続するvethのブリッジ側ネットワークインターフェース(veth2a5f404@if8)が追加されています。
コンテナ内のネットワークインターフェースを確認します。
$ sudo docker exec -it container2 /bin/bash
root@31abe1533cfe:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
コンテナにブリッジのveth2a5f404@if8
ネットワークインターフェースと接続されたeth0@if9
が作成されていることが分かります。
コンテナのルートテーブルを確認します。
ゲートウェイに172.18.0.1
が設定されています。
root@31abe1533cfe:/# route -ne
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 172.18.0.1 0.0.0.0 UG 0 0 0 eth0
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
コンテナを2つ追加したので、ブリッジbr-29faca36a6b4
の現状を確認してみます。
$ brctl show br-29faca36a6b4
bridge name bridge id STP enabled interfaces
br-29faca36a6b4 8000.0242c107547f no veth2a5f404
veth7a0c3b1
コンテナを2つ追加したのでブリッジとコンテナを繋ぐ2つのveth用のネットワークインターフェースがそれぞれveth2a5f404
、veth7a0c3b1
として追加されています。
ここまででsampleネットワークに閉じた通信はブリッジおよびネットワークインターフェースを使って通信できるようになりました。
container1からcontainer2にpingを発行してsampleネットワーク内の通信をみます。 ICMP echo requestパッケットは以下順番でネットワークインターフェースを通ってcontainer2に到達します。
eth0@if7
ネットワークインターフェースveth7a0c3b1@if6
ネットワークインターフェースbr-29faca36a6b4
ネットワークインターフェースveth2a5f404@if8
ネットワークインターフェースeth0@if9
ネットワークインターフェースICMP echo replyは逆の順序を通ってcontainer2からcontainer1に到達します。
参考までにtcpdump
でそれぞれのインターフェースの通信をキャプチャします。
eth0@if7
ネットワークインターフェースをキャプチャ# tcpdump -tnl -i eth0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
IP 172.18.0.2 > 172.18.0.3: ICMP echo request, id 1, seq 1, length 64
veth7a0c3b1
ネットワークインターフェースをキャプチャ$ sudo tcpdump -tnl -i veth7a0c3b1 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth7a0c3b1, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 172.18.0.2 > 172.18.0.3: ICMP echo request, id 1, seq 1, length 64
br-29faca36a6b4
ネットワークインターフェースをキャプチャ$ sudo tcpdump -tnl -i br-29faca36a6b4 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-29faca36a6b4, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 172.18.0.2 > 172.18.0.3: ICMP echo request, id 2, seq 1, length 64
veth2a5f404
ネットワークインターフェースをキャプチャ$ sudo tcpdump -tnl -i veth2a5f404 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth2a5f404, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 172.18.0.2 > 172.18.0.3: ICMP echo request, id 1, seq 1, length 64
# tcpdump -tnl -i eth0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
IP 172.18.0.2 > 172.18.0.3: ICMP echo request, id 1, seq 1, length 6
最後にbridgeネットワークと外部の通信について確認します。
ブリッジネットワークは、(ブリッジネットワークの)br-29faca36a6b4
ネットワークインターフェースからホスト
のeth0
ネットワークインターフェースを経由して外部と通信します。
IPマスカレードによってホストのIPに変換されまてホストのeth0
から送信されます。
※ IPマスカレードはNATのLinuxの実装です。
iptableを確認してます。
$ sudo iptables -t nat -nL -v
Chain PREROUTING (policy ACCEPT 21 packets, 1034 bytes)
pkts bytes target prot opt in out source destination
22 938 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 13 packets, 554 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 50 packets, 4834 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 50 packets, 4834 bytes)
pkts bytes target prot opt in out source destination
8 480 MASQUERADE all -- * !br-29faca36a6b4 172.18.0.0/16 0.0.0.0/0
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- br-29faca36a6b4 * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
IPマスカレードの該当部分は以下のようになります。
Chain POSTROUTING (policy ACCEPT 50 packets, 4834 bytes)
pkts bytes target prot opt in out source destination
8 480 MASQUERADE all -- * !br-29faca36a6b4 172.18.0.0/16 0.0.0.0/0
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
container1から93.184.216.34(example.org)にpingを発行してsampleネットワークと外部との通信を確認します。
eth0@if7
ネットワークインターフェースveth7a0c3b1@if6
ネットワークインターフェースbr-29faca36a6b4
ネットワークインターフェースeth0
ネットワークインターフェースICMP echo replyは逆の順序でcontainer2のeth0@if7
ネットワークインターフェースに届きます。
eth0@if7
ネットワークインターフェースをキャプチャsudo docker exec -it container1 /bin/bash
root@daf864877355:/# tcpdump -tnl -i eth0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
IP 172.18.0.2 > 93.184.216.34: ICMP echo request, id 5, seq 1, length 64
IP 93.184.216.34 > 172.18.0.2: ICMP echo reply, id 5, seq 1, length 64
veth7a0c3b1@if6
ネットワークインターフェースをキャプチャ$ sudo tcpdump -tnl -i veth7a0c3b1 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth7a0c3b1, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 172.18.0.2 > 93.184.216.34: ICMP echo request, id 5, seq 1, length 64
IP 93.184.216.34 > 172.18.0.2: ICMP echo reply, id 5, seq 1, length 64
br-29faca36a6b4
ネットワークインターフェースをキャプチャsudo tcpdump -tnl -i br-29faca36a6b4 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-29faca36a6b4, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 172.18.0.2 > 93.184.216.34: ICMP echo request, id 8, seq 1, length 64
IP 93.184.216.34 > 172.18.0.2: ICMP echo reply, id 8, seq 1, length 64
IPマスカレードによってIPが10.3.0.183に書き換えられて送信。
sudo tcpdump -tnl -i eth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 10.3.0.183 > 93.184.216.34: ICMP echo request, id 9, seq 1, length 64
IP 93.184.216.34 > 10.3.0.183: ICMP echo reply, id 9, seq 1, length 64
以上となります。
https://qiita.com/BooookStore/items/5862515209a31658f88c
上記記事が大変参考になる。
基本そのまま実行すればよい。
net.ipv4.ip_forward = 1
も忘れずにDocker コンテナは通常rootユーザーでもip route add
などが禁止されています。docker run
のときにオプション--cap-add=NET_ADMIN
を指定します。
routerコンテナをsample1とsample2に接続します。
routerのIPは172.18.0.3
と172.19.0.3
とします。
sample1ネットワークにコンテナを追加します。
追加したコンテナのIPアドレスは172.18.0.4
とします。
追加したコンテナ(172.18.0.4
)にルートを追加します。
※ 設定したルートはip route save
を実行しないと一時的なもので再起動で消えます。
# ip route add 172.19.0.0 via 172.18.0.3 dev eth0
# ip route
default via 172.18.0.1 dev eth0
172.18.0.0/16 dev eth0 proto kernel scope link src 172.18.0.4
172.19.0.0 via 172.18.0.3 dev eth0
sample2ネットワークにコンテナを追加します。
追加したコンテナのIPアドレスは172.19.0.2
とします。
追加したコンテナ(172.18.0.2
)にルートを追加します。
$ ip route add 172.18.0.0/16 via 172.19.0.3 dev eth0
ルートテーブルを確認します。
# ip route add 172.18.0.0/16 via 172.19.0.3 dev eth0
# ip route
default via 172.19.0.1 dev eth0
172.18.0.0/16 via 172.19.0.3 dev eth0
172.19.0.0/16 dev eth0 proto kernel scope link src 172.19.0.2
コンテナ(172.18.0.4
)とコンテナ(172.19.0.2
)の疎通を確認します。
root@8ac398b06b04:/# ping -c 3 172.19.0.2
PING 172.19.0.2 (172.19.0.2) 56(84) bytes of data.
64 bytes from 172.19.0.2: icmp_seq=1 ttl=63 time=0.101 ms
64 bytes from 172.19.0.2: icmp_seq=2 ttl=63 time=0.082 ms
64 bytes from 172.19.0.2: icmp_seq=3 ttl=63 time=0.081 ms
--- 172.19.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2031ms
rtt min/avg/max/mdev = 0.081/0.088/0.101/0.009 ms