基于 Docker18.09.0
认识默认网桥
安装Docker时,它会自动创建三个网络。您可以使用以下docker network ls命令列出这些网络:
$ docker network ls
NETWORK ID NAME DRIVER
7fca4eb8c647 bridge bridge
9f904ee27bf5 none null
cf03ee007fb4 host host
这三个网络都内置在 Docker 中。运行容器时,可以使用该
--network
标志指定容器应连接到的网络。
上面的 bridge
是 Docker 服务启动时默认创建的 docker0
网桥(其上有一个 docker0
内部接口),它在内核层连通了其他的物理或虚拟网卡。
除非您使用该docker run --network=
在宿主机上执行 ip addr show
命令可以看到此设备
在每创建一个容器时,Docker 都会为此容器创建一对儿网络接口,比如上图中的
eth0
就是容器 Test1 的一端的 网口。
当我们不指定具体的网络去创建一个容器的时候,Docker 会同时把这两个接口放在docker0
的网络名称空间中。就相当于,为此容器做了一条网线,网线的一端连接到docker0
这个网桥上,另一端连接到这个容器的eth0
这个接口上。
只要是连接到docker0
这个网桥上的任何容器都可以通过彼此的 ip 地址互相通信。
查看默认的网桥信息
可以在宿主机上执行 docker network inspect bridge
来查看默认网桥的源数据信息。
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "8a5f470ffe774f4f96a712642ed361fbeb0d8e66018e1d629ab44cfdf3e42a05",
"Created": "2018-12-09T03:03:21.385313598Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {}, # 目前没有任何容器加入到此网络中,所以是空的
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
默认网桥上的容器互相通信
刚才提到了,默认情况下 Docker 会将主机上所有容器连接到此网桥上,他们默认情况下就是可以互相通信的。
但是只能使用彼此的 IP 通信,不可以使用容器名。
下面我们就来实操验证一下。
1. 先创建两个容器
# shark @ SharkAir in ~ [10:51:48]
$ docker run -itd --name=container1 busybox
b0ca6cc19650cfdaa572c9e656a64a5a041b0825e4f68416e9b36dfdbeca3dc8
# shark @ SharkAir in ~ [10:52:47]
$ docker run -itd --name=container2 busybox
df5375eaeb17ea49f6dbbf87b7dd5fb6bda42b33eaa4708a4e2cb9c67ae63145
2. 观察默认网桥的信息
在宿主机上执行命令 docker network inspect bridge
从上图中不难看出,刚才我们运行的连个容器被添加到了默认的网桥上,并且分配了具体的地址信息。
官方提示:
连接到默认bridge
网络的容器可以通过IP地址相互通信。Docker不支持默认网桥上的自动服务发现
。如果你希望容器能够通过容器名称解析的IP地址,你应该使用用户定义的网络代替。您可以使用旧版docker run --link
选项将两个容器链接在一起,但在大多数情况下不建议这样做。
3. 进入容器中测试互相通信
a. 容器 1 的操作
$ docker exec -it container1 /bin/sh # 进入容器 1
/ # ip -4 addr # 查看 IPv4 地址信息
1: lo: mtu 65536 qdisc noqueue qlen 1
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
51: eth0@if52: mtu 1500 qdisc noqueue
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # cat /etc/hosts # 查看本地 DNS 解析文件
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 b0ca6cc19650 # 可以看出只有 ip 和 容器 ID 的对应关系
/ # ping -w2 b0ca6cc19650 # 尝试 ping 另外一个容器的 ID
PING b0ca6cc19650 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.847 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.113 ms
--- b0ca6cc19650 ping statistics ---
3 packets transmitted, 2 packets received, 33% packet loss
round-trip min/avg/max = 0.113/0.480/0.847 ms
/ # ping -w2 172.17.0.2 # 尝试 ping 另外一个容器的 IP
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.574 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.155 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.155/0.364/0.574 ms
/ # exit # 退出这个容器
b. 容器 2 的简单操作
$ docker exec -it container2 /bin/sh
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 df5375eaeb17
/ # ping -w1 df5375eaeb17
PING df5375eaeb17 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.122 ms
--- df5375eaeb17 ping statistics ---
2 packets transmitted, 1 packets received, 50% packet loss
round-trip min/avg/max = 0.122/0.122/0.122 ms
/ # exit
值得注意的是: 默认网桥的
hosts文件中只有 IP 到容器 ID 之间的对应关系,所以是无法通过容器名称进行互相通信的。
禁用默认桥接网络
如果您不希望创建默认桥接网络,请将以下内容添加到该daemon.json
文件中。这仅适用于Docker守护程序在Linux主机上运行的情况。
"bridge": "none",
"iptables": "false"
重新启动Docker以使更改生效。
这属于高级操作,大部分情况下你都不需要禁用它。
配置默认网桥
Docker 默认指定了 docker0
接口 的 IP 地址和子网掩码,可以在 Docker
服务启动时改变它:
-
--bip=CIDR
IP 地址加掩码格式,例如 192.168.1.5/24 -
--mtu=BYTES
覆盖默认的 Docker mtu 配置
由于目前 Docker 网桥是 Linux 网桥,用户也可以使用 brctl show
来查看网桥和端口连接信息。
brctl
命令需要安装 bridge-utils
[root@docker ~]# yum install bridge-utils
[root@docker ~]# brctl show
bridge name bridge id STP enabled interfaces
br-592bf266d1de 8000.0242d53c8ae4 no veth1357758
vetha2ea524
br-8f91b60157b9 8000.02421002c747 no
docker0 8000.0242b23bc676 no vethcc2dfbe
vethe52debb