Docker 网络-默认网桥

基于 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=选项另行指定,否则Docker守护程序默认情况下将容器连接到此网络。这就将所有容器和本地主机都放到同一个物理网络。

在宿主机上执行 ip addr show 命令可以看到此设备

docker0 网桥

网桥网络模型

在每创建一个容器时,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

你可能感兴趣的:(Docker 网络-默认网桥)