目录

  • Docker 系列文章目录
  • 认识默认网桥
  • 查看默认的网桥信息
  • 默认网桥上的容器互相通信
  • 1. 先创建两个容器
  • 2. 观察默认网桥的信息
  • 3. 进入容器中测试互相通信
  • 禁用默认桥接网络
  • 配置默认网桥


认识默认网桥

安装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 命令可以看到此设备

docker 切换网卡后 docker 默认网络_Docker

docker 切换网卡后 docker 默认网络_Docker_02

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

docker 切换网卡后 docker 默认网络_docker_03

从上图中不难看出,刚才我们运行的连个容器被添加到了默认的网桥上,并且分配了具体的地址信息。

官方提示:
连接到默认bridge网络的容器可以通过IP地址相互通信。Docker不支持默认网桥上的自动服务发现。如果你希望容器能够通过容器名称解析的IP地址,你应该使用用户定义的网络代替。您可以使用旧版 docker run --link 选项将两个容器链接在一起,但在大多数情况下不建议这样做。

3. 进入容器中测试互相通信

a. 容器 1 的操作

$ docker exec -it container1 /bin/sh  # 进入容器 1
/ # ip -4 addr        # 查看 IPv4 地址信息
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
51: eth0@if52: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> 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