ブリッジの一般的な意味。
ブリッジ(Bridge/L2スイッチ) ネットワークをデータリンク層で延長する装置
-- マスタリングTCP/IP 入門編 p38
コンテナから外部へはセグメントをまたぐ(例 docker0 172.16.0.0/16 から ホストのネットワーク 10.3.0.0/16)ためにパケット転送net.ipv4.ip.forward=1
が使われて10.3.0.0/16から外にる際にIPマスカレード(NAT)が使われます。
// 有効
$ sudo sysctl -w net.ipv4.ip_forward=1
// 無効
$ sudo sysctl -w net.ipv4.ip_forward=0
Docker Network(例 172.16.0.0/16
)がホストネットワーク(例 10.3.0.0/16)を通してが外部と通信できるのはnet.ipv4.ip.forward
が有効になっているため。
同じPCの場合net.ipv4.ip.forward
がtrueなら転送される。
https://tanke25616429.hatenablog.com/entry/2021/01/17/011553
ホストOSのnet.ipv4.ip.forward
はDockerが自動で有効化する。
コンテナのカーネルパラメータは起動後には変更できない。
変更するには起動時に--sysctl
オプションで設定する。
$ docker run --sysctl net.ipv4.ip_forward=1 someimage
ref. 実行時に名前空間のカーネル・パラメータ(sysctl)を設定
IPマスカレードのわかりやすい記事。
http://blog.livedoor.jp/harukisan7/archives/17114894.html?utm_source=pocket_mylist
docker0とeth0は、DockerホストのOS機能であるiptablesによるIPマスカレードが行われています。
ホストのネットワークインターフェースdocker0
とeth0
はホスト
のiptables
でIPマスカレードを実現しています。
sudo iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.19.0.0/16 0.0.0.0/0
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
https://docs.docker.jp/engine/userguide/networking/default_network/binding.html
上記ドキュメントで分かりやすく解説されています。
コンテナが外部から内部への接続を受け付けたいならdocker run
のp
または--publish
オプション、Docker Compose
のports
プロパティでポートを公開します。
Dockerがiptables
にDNAT
を追加します。
例えばNginx
コンテナをrun
するときにp
オプションで8000
を指定したときの例です(コンテナは172.17.0.2
で稼働していると仮定します)。
$ docker run -d --name web -p 8000:80 nginx:latest
$ iptables -t nat -L -n
.....
Chain DOCKER-INGRESS (2 references)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8000 to:172.17.0.2:80
.....
任意の場所(0.0.0.0
)からのポート8000
でのアクセスを172.17.0.2
のポート80
に接続します。
bridge
ネットワークに接続bridge
ネットワークのネットワークインターフェースはdocker0
^docker0bridge
ネットワークに接続されたコンテナ間はIPアドレス
で通信可能bridge
ネットワークに接続されたコンテナ間はコンテナ名
で通信不可(デフォルトのbridge
ネットワークは内蔵DNSサーバ
を持たないため)bridge
ネットワークに接続されたコンテナ間はコンテナ名
で通信可能Docker Compose
は、自動でbridgeネットワークを新規作成するので
service名`[^service名]で通信可能[^service名]:Docker Composeは各コンテナをservice
と呼びます。
Dockerインストール時にデフォルトでネットワーク名がbridge
、host
、null
のネットワークが作成されます。
$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
abf0a3a6242a bridge bridge local <--- このネットワークのネットワークインターフェースがUbuntuはdocker0、Macはbridge0になります
5647050e2ccb host host local
f17799accf48 none null local
上述したとおりUbuntuの場合デフォルトで作成されるbridge
ネットワークのネットワークインターフェースがdoker0
になります(Macはbridge0
)。
Docker のインストールは、自動的に3つのネットワークを作成します。
https://docs.docker.jp/engine/userguide/networking/dockernetworks.html
Docker をインストールした全ての環境には、 docker0 と表示されるブリッジ( bridge )ネットワークが現れます。オプションで docker run --net=<ネットワーク名> を指定しない限り、Docker デーモンはデフォルトでこのネットワークにコンテナを接続します。ホスト上で ifconfig コマンドを使えば、ホストネットワーク上のスタックの一部として、このブリッジを見ることができます。
https://docs.docker.jp/engine/userguide/networking/dockernetworks.html
$ docker inspect {{NETWORK ID}}
# コンテナのIPアドレス
$ docker inspect {{コンテナID or NAME}}
bridge
ネットワークのネットワークインターフェースはdocker0
になりますbridge
ネットワークに接続されますホストは以下のネットワークインターフェースを持つと仮定します。
bridge
ネットワークのネットワークインターフェースIPアドレス[^docker-ip]を使ったコンテナ間通信においてdocker0
に発生するデータをキャプチャしてみます。
[^docker-ip]:サービス名で通信する場合はdocker0
ではなく、docker network create {{network_name}}
で作成したネットワークを設定してコンテナを起動します。
$ docker run -itd --name alpine-sample1 alpine:latest
$ docker run -itd --name sample-sample2 alpine:latest
コンテナのIPアドレスを確認します。
$ sudo docker exec -it alpine-sample1 /bin/sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
...
※ docker inspect alpine-sample1
でも確認できます。
172.17.0.2
です 172.17.0.3
としますコンテナ間はdocker0
で通信していることを確認します^docker0-2。
$ sudo tcpdump -tnl -i docker0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
alpine-sample1
からalpine-sample2
にping
を発行します。
$ docker exec -it alpine /bin/sh
/ # ping -c 1 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.110 ms
予想どおりdocker0
に通信が発生しています。
$ sudo tcpdump -tnl -i docker0 icmp [15/84]
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
.....
IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 12, seq 0, length 64
IP 172.17.0.3 > 172.17.0.2: ICMP echo reply, id 12, seq 0, length 64
外部との通信を確認します。
例としてGoogleが提供するフルサービスリゾルバ8.8.8.8
にping
を発行します。
$ sudo docker exec -it alpine-sample1 /bin/sh
/ # ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=101 time=3.000 ms
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.000/3.000/3.000 ms
予想どおりdocker0
に通信が発生しています。
$ sudo tcpdump -tnl -i docker0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
.....
IP 172.17.0.2 > 8.8.8.8: ICMP echo request, id 27, seq 0, length 64
IP 8.8.8.8 > 172.17.0.2: ICMP echo reply, id 27, seq 0, length 64
加えてホストのデフォルトのネットワークインターフェースeth0
にも通信が発生していることが分かります。
$ 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 > 8.8.8.8: ICMP echo request, id 27, seq 0, length 64
IP 8.8.8.8 > 10.3.0.183: ICMP echo reply, id 27, seq 0, length 64
外部からコンテナにアクセスする際の通信をみます。
例としてhttpd:latest
を稼働しているホストに外部からアクセスした際の通信をみます。
203.0.113.1
192.0.2.1/24
eth0
docker0
172.17.0.4
eth0
203.0.113.150
httpd:latest
はifconfig
がインストールされていないのでapt install net-tools
でインストールします。
$ sudo docker run -d -p 8000:80 --name httpd-sample httpd
クライアントのブラウザで http://203.0.113.1:8000 にアクセスします。
ホストのeth0
の通信をみます。
クライアントとホストはポート8000番で通信しています。
$ sudo tcpdump -tnl -i eth0 tcp port 8000 [19/1972]
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 203.0.113.150.64640 > 192.0.2.1.8000: Flags [S], seq 218777360, win 65535, options [mss 1394,nop,wscale 6,nop,nop,TS val 3364579648 ecr 0,sackOK,eol], length 0
IP 192.0.2.1.8000 > 203.0.113.150.64640: Flags [S.], seq 1645943187, ack 218777361, win 65160, options [mss 1460,sackOK,TS val 2400436806 ecr 3364579648,nop,wscale 6], length 0
IP 203.0.113.150.64639 > 192.0.2.1.8000: Flags [.], ack 1, win 2051, options [nop,nop,TS val 1426504603 ecr 2400436806], length 0
ホストのdocker0
の通信をみます。
コンテナとポート80番で通信しています。
$ sudo tcpdump -tnl -i docker0 tcp port 80 [19/1804]
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 203.0.113.150.64640 > 172.17.0.4.80: Flags [S], seq 218777360, win 65535, options [mss 1394,nop,wscale 6,nop,nop,TS val 3364579648 ecr 0,sackOK,eol], length 0
IP 172.17.0.4.80 > 203.0.113.150.64640: Flags [S.], seq 1645943187, ack 218777361, win 65160, options [mss 1460,sackOK,TS val 2400436806 ecr 3364579648,nop,wscale 6], length 0
IP 203.0.113.150.64639 > 172.17.0.4.80: Flags [.], ack 1, win 2051, options [nop,nop,TS val 1426504603 ecr 2400436806], length 0
コンテナのeth0
の通信をみます。
予想どおりポート80番で通信しています。
# tcpdump -tnl -i eth0 tcp port 80
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
IP 203.0.113.150.64640 > 172.17.0.4.80: Flags [S], seq 218777360, win 65535, options [mss 1394,nop,wscale 6,nop,nop,TS val 3364579648 ecr 0,sackOK,eol], length 0
IP 172.17.0.4.80 > 124.18.121.200.64640: Flags [S.], seq 1645943187, ack 218777361, win 65160, options [mss 1460,sackOK,TS val 2400436806 ecr 3364579648,nop,wscale 6], length 0
IP 124.18.121.200.64639 > 172.17.0.4.80: Flags [.], ack 1, win 2051, options [nop,nop,TS val 1426504603 ecr 2400436806], length 0
簡単ですが外部からのコンテナに対するアクセスついて確認しました。
https://cacoo.com/diagrams/0jEiiI3UonJoOn6D/C8EAD
bridge
ネットワークを作成したときにホストに追加されるブリッジの仮想ネットワークインターフェースbridge
ネットワークにコンテナを追加したときにホストに追加されるブリッジ側のネットワークインターフェースホスト
のネットワークインターフェースとルートテーブルを確認します。
ネットワークインターフェースを確認します。
$ 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
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
valid_lft 2700sec preferred_lft 2700sec
inet6 fe80::4b5:10ff:fe1f:21cd/64 scope link
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
ルートテーブルを確認します。
$ ip route
default via 10.3.0.1 dev eth0 proto dhcp src 10.3.0.183 metric 100
10.3.0.0/24 dev eth0 proto kernel scope link src 10.3.0.183
10.3.0.1 dev eth0 proto dhcp scope link src 10.3.0.183 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
$ 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
birdge
ドライバのsample
ネットワークを作成します。
$ sudo docker network create sample
29faca36a6b48487a16a1071c20dbe0b0b0bab3f6695d5d96324b80a9c3da773
ホスト
には仮想ブリッジが作成されて、仮想ブリッジのネットワークインターフェースが追加されます。ホスト
のネットワークインターフェースを確認します。
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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
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
valid_lft 2360sec preferred_lft 2360sec
inet6 fe80::4b5:10ff:fe1f:21cd/64 scope link
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
sample
を作成したことによってbr-29faca36a6b4
が作成されて、ブリッジのネットワークインターフェースbr-29faca36a6b4
(172.168.0.1
)が追加されました。
(ブリッジとブリッジのネットワークインターフェースは同一名になっています)
ルートテーブルを確認します。
$ ip route
default via 10.3.0.1 dev eth0 proto dhcp src 10.3.0.183 metric 100
10.3.0.0/24 dev eth0 proto kernel scope link src 10.3.0.183
10.3.0.1 dev eth0 proto dhcp scope link src 10.3.0.183 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-29faca36a6b4 proto kernel scope link src 172.18.0.1 linkdown
$ 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
sampleネットワークにコンテナを追加します。 コンテナ名はcontainer1にします。
$ sudo docker run -itd --name container1 --net sample ubuntu:latest
daf864877355b6444832408add4afe7819c2e75446259aec9ca66ed399f692af
ホスト
にコンテナ(container1)とブリッジを接続するvethのブリッジ側ネットワークインターフェース(veth7a0c3b1@if6)が追加されています。
$ 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
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
valid_lft 1949sec preferred_lft 1949sec
inet6 fe80::4b5:10ff:fe1f:21cd/64 scope link
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
5: br-29faca36a6b4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 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
valid_lft forever preferred_lft forever
inet6 fe80::42:c1ff:fe07:547f/64 scope link
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
sampleネットワークを確認します。
$ sudo docker network inspect sample
[
{
"Name": "sample",
"Id": "29faca36a6b48487a16a1071c20dbe0b0b0bab3f6695d5d96324b80a9c3da773",
"Created": "2022-06-08T11:33:26.165225737Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1" <--- ブリッジのIP
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"daf864877355b6444832408add4afe7819c2e75446259aec9ca66ed399f692af": {
"Name": "container1",
"EndpointID": "8233bb298d5fe7ef0d06af692a87c013677bdff42be7c22fbaa382105f3255c6",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
container1が追加されています。
コンテナを追加します。
$ sudo docker run -itd --name container2 --net sample ubuntu:latest
31abe1533cfed576910011ca990445da30dc641e2447ad63663b91175e52ea15
ホスト
にコンテナ(container2)とブリッジを接続するvethのブリッジ側ネットワークインターフェース(veth2a5f404@if8)が追加されています。
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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
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
valid_lft 3439sec preferred_lft 3439sec
inet6 fe80::4b5:10ff:fe1f:21cd/64 scope link
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
5: br-29faca36a6b4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 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
valid_lft forever preferred_lft forever
inet6 fe80::42:c1ff:fe07:547f/64 scope link
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
sampleネットワークにコンテナが追加されています。
$ sudo docker network inspect sample
[
{
"Name": "sample",
"Id": "29faca36a6b48487a16a1071c20dbe0b0b0bab3f6695d5d96324b80a9c3da773",
"Created": "2022-06-08T11:33:26.165225737Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"31abe1533cfed576910011ca990445da30dc641e2447ad63663b91175e52ea15": {
"Name": "container2",
"EndpointID": "63366b86e00fae9705030e42606dd311807cd03330678d73372cb715d6b74d22",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"daf864877355b6444832408add4afe7819c2e75446259aec9ca66ed399f692af": {
"Name": "container1",
"EndpointID": "8233bb298d5fe7ef0d06af692a87c013677bdff42be7c22fbaa382105f3255c6",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
ブリッジbr-29faca36a6b4
$ brctl show br-29faca36a6b4
bridge name bridge id STP enabled interfaces
br-29faca36a6b4 8000.0242c107547f no veth2a5f404
veth7a0c3b1
apt install iproute2
ipコマンドapt install net-tools -y
routeコマンド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
valid_lft forever preferred_lft forever
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
valid_lft forever preferred_lft forever
コンテナのネットワークインターフェースeth0@if7
はブリッジのネットワークインターフェースveth7a0c3b1@if6
とvethで接続。
ルートテーブルを確認。
$ 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
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
コンテナのネットワークインターフェースeth0@if9とブリッジのネットワークインターフェースveth2a5f404@if8が仮想イーサネットで接続。
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
ホストのIPテーブルを見る。 ブリッジの仮想NICからホストの物理NICにIPマスカレードさえることを確認。
$ 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
デフォルトのネットワークを再度確認してみます。
$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
abf0a3a6242a bridge bridge local <--- このネットワークのネットワークインターフェースがUbuntuはdocker0、Macはbridge0
5647050e2ccb host host local
f17799accf48 none null local
$ docker network create {{network_name}}
br-
で始まるネットワーク・インターフェースがホストに作成されますdocker network ls
で確認します例)
$ docker network create sample
$sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
abf0a3a6242a bridge bridge local
5647050e2ccb host host local
f17799accf48 none null local
8fe0215332a8 sample bridge local <--- 新規に作成
ホストでifconfig
を発行してネットワークインターフェースを確認します。
br-8fe0215332a8
が追加されていますbr-8fe0215332a8
のIPアドレスは172.18.0.1です$ ifconfig
br-8fe0215332a8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 // <--- 追加
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
inet6 fe80::42:87ff:fe57:24b2 prefixlen 64 scopeid 0x20<link>
ether 02:42:87:57:24:b2 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5 bytes 526 (526.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:37ff:fe8d:b952 prefixlen 64 scopeid 0x20<link>
ether 02:42:37:8d:b9:52 txqueuelen 0 (Ethernet)
RX packets 1392 bytes 85837 (85.8 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2875 bytes 13382135 (13.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9001
inet 10.3.0.183 netmask 255.255.255.0 broadcast 10.3.0.255
inet6 fe80::4b5:10ff:fe1f:21cd prefixlen 64 scopeid 0x20<link>
ether 06:b5:10:1f:21:cd txqueuelen 1000 (Ethernet)
RX packets 66248 bytes 76218429 (76.2 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 96440 bytes 23585335 (23.5 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
net
オプションで作成したbridge
ネットワークを指定してコンテナを起動します。
$ sudo docker run -itd --name alpine-sample1 --net sample alpine:latest
$ sudo docker run -itd --name alpine-sample2 --net sample alpine:latest
alpine-sample1に入ってネットワークインターフェースのIPアドレスを確認してみます。
docker exec -it alpine-sample1 /bin/sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe12:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1392 (1.3 KiB) TX bytes:656 (656.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
IPアドレスは172.18.0.2です。
同様にalpine-sample2のネットワークインターフェースのIPアドレスは172.18.0.3です。
ネットワークをまとめると以下になります。
br-8fe0215332a8
のIPアドレスは172.18.0.1ではネットワークインターフェースbr-8fe0215332a8
の通信をキャプチャして使用を確認します。
$ sudo tcpdump -tnl -i br-8fe0215332a8 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-8fe0215332a8, link-type EN10MB (Ethernet), capture size 262144 bytes
コンテナ名alpine-sample2
にアクセスします(デフォルトのbridgeネットワークインターフェースdocker0
を使う場合はIPアドレスでしかアクセスできません)。
コンテナ名でアクセスできるのは、bridge
ネットワーク(デフォルトのbridge
ネットワークを除く)が内蔵DNSサーバ
を持っているからです^bridge-net。
デフォルトの「bridge0」という名称のブリッジ・ネットワークでは、この名前解決機能がありません。コンテナ間の通信でサービス・ディスカバリを有効化するには、自分でブリッジ・ネットワークを作成する必用があります。これをDockerではUser Defined Bridge Network(ユーザ定義ブリッジ・ネットワーク)と呼びます。
内蔵DNSサーバを使用してコンテナ名(Docker Composeではservice名)でアクセスする機能をサービス・ディスカバリと呼びます。
$ sudo docker exec -it alpine1 /bin/sh
/ # ping -c 1 alpine-sample2 // <------------------------ コンテナ名でPingを発行
PING alpine2 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.103 ms
--- alpine-sample2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.103/0.103/0.103 ms
sudo tcpdump -tnl -i br-8fe0215332a8 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-8fe0215332a8, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 172.18.0.3 > 172.18.0.2: ICMP echo request, id 14, seq 0, length 64
IP 172.18.0.2 > 172.18.0.3: ICMP echo reply, id 14, seq 0, length 64
新規に作成したbridgeネットワークは内蔵DNS
サーバ利用できます。
内蔵DNS
はDocker デーモンが提供します。
Docker デーモンは内蔵 DNS サーバを動かし、ユーザ定義ネットワーク上でコンテナがサービス・ディスカバリを自動的に行えるようにします。コンテナから名前解決のリクエストがあれば、内部 DNS サーバを第一に使います。リクエストがあっても内部 DNS サーバが名前解決できなければ、外部の DNS サーバにコンテナからのリクエストを転送します。割り当てできるのはコンテナの作成時だけです。内部 DNS サーバが到達可能なのは 127.0.0.11 のみであり、コンテナの resolv.conf に書かれます。ユーザ定義ネットワーク上の内部 DNS サーバに関しては ユーザ定義ネットワーク用の内部 DNS サーバ をご覧ください。
-- https://docs.docker.jp/engine/userguide/networking/dockernetworks.html
上述のalpine-sample1
コンテナにdig
を入れて内蔵DNSサーバを確認します。
$ sudo docker exec -it alpine-sample1 /bin/sh
/ # apt update
/ # apk add --no-cache bind-tools // <---------------------- digをインストール
fetch https://dl-cdn.alpinelinux.org/alpine/v3.15/main/x86_64/APKINDEX.tar.gz
.....
OK: 13 MiB in 29 packages
/ # dig alpine-sample2 // <------------------------ サービス・ディスカバリを見る
; <<>> DiG 9.16.27 <<>> alpine2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35236
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;alpine-sample2. IN A
;; ANSWER SECTION:
alpine-sample2. 600 IN A 172.18.0.2
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11) <---- 内蔵DNSサーバ
;; WHEN: Sat May 14 07:26:26 UTC 2022
;; MSG SIZE rcvd: 48
host
ネットワークは文字通りホストとネットワークを共有します。
そのためネットワークインターフェースもホストのeth0
を使用します(ホストのネットワークインターフェースがeth0
の場合)。
host
ネットワークの特徴は以下のとおりです。
host
ネットワークは1つしか存在できないhost
ネットワークはDockerインストール時に作成されるのでユーザーは作成できない。host
ネットワークを作成しようとするとエラーが発生する$ sudo docker network create -d host sample
Error response from daemon: only one instance of "host" network is allowed
$ sudo docker run -d --name httpd --net host httpd:latest
hostネットワークはホストのネットワークを共有するのでifconfig
もホストと同じです。
ネットワークインターフェースもホストのeth0を使用します。
$ sudo docker exec -it httpd /bin/bash
root@ip-10-3-0-183:/usr/local/apache2# apt install net-tools // ifconfigインストール
....
root@ip-10-3-0-183:/usr/local/apache2# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:37ff:fe8d:b952 prefixlen 64 scopeid 0x20<link>
ether 02:42:37:8d:b9:52 txqueuelen 0 (Ethernet)
RX packets 1392 bytes 85837 (85.8 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2875 bytes 13382135 (13.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9001
inet 10.3.0.183 netmask 255.255.255.0 broadcast 10.3.0.255
inet6 fe80::4b5:10ff:fe1f:21cd prefixlen 64 scopeid 0x20<link>
ether 06:b5:10:1f:21:cd txqueuelen 1000 (Ethernet)
RX packets 87575 bytes 94433872 (94.4 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 105846 bytes 24945855 (24.9 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 574 bytes 61238 (61.2 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 574 bytes 61238 (61.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ブラウザでアクセスするとeth0
に通信が発生していることが確認できます(docker0
には発生しない)。
$ sudo tcpdump -tnl -i eth0 tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 203.0.113.150.51221 > 10.3.0.183.80: Flags [S], seq 251437622, win 65535, options [mss 1394,nop,wscale 6,nop,nop,TS val 1967450493 ecr 0,sackOK,eol], length 0
IP 10.3.0.183.80 > 203.0.113.150.51221: Flags [S.], seq 3651188619, ack 251437623, win 62643, options [mss 8961,sackOK,TS val 14863613 ecr 1967450493,nop,wscale 6], length 0
IP 203.0.113.150.51222 > 10.3.0.183.80: Flags [.], ack 1, win 2051, options [nop,nop,TS val 1589689261 ecr 14863612], length 0
docker0
には通信は発生していません。
sudo tcpdump -tnl -i docker0 tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
// ブラウザでアクセスしても通信は発生しない
/etc/hostname/
に記載された名前。hostname
コマンドで確認できる。同一のユーザー定義bridgeネットワークでは、IPアドレス、サービス名、ホスト名で通信できる。
sudo docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd1d6037c81e httpd "httpd-foreground" 29 minutes ago Up 29 minutes 0.0.0.0:9000->80/tcp, :::9000->80/tcp web-httpd2
b44bfea6fb4d httpd "httpd-foreground" 48 minutes ago Up 48 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp web-httpd
2b4840ca369d nginx "/docker-entrypoint.…" 53 minutes ago Up 53 minutes 0.0.0.0:8000->80/tcp, :::8000->80/tcp web-nginx
Dockerの場合ホスト名はコンテナIDになる。 bd1d6037c81eにexecしてホスト名b44bfea6fb4dの80ポートからHTMLを取得する例。
root@bd1d6037c81e:/usr/local/apache2# curl --head b44bfea6fb4d:80
HTTP/1.1 200 OK
Date: Fri, 22 Jul 2022 23:53:54 GMT
Server: Apache/2.4.53 (Unix)
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes
Content-Length: 45
Content-Type: text/html