Docker 教程

Docker 容器网络分析

下面将通过具体的示例来分析 Dokcer 中的 bridge、host 和 none 网络模式。

bridge 模式分析

01af2c2c28852add4add06eb8c375e37_1726128540929-d72570f5-87d8-4a0a-b615-6bdf6d61c501_x-oss-process=image%2Fformat%2Cwebp.png

Docker 运行容器时默认使用 bridge 模式。下面将分析 Docker 的 bridge 模式:

(1)使用 ifconfig 命令查看宿主机的网络接口信息,如下:

root@hxvm:~# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:c7:7b:2a:35  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.27.114.197  netmask 255.255.240.0  broadcast 172.27.127.255
        inet6 fe80::3c5f:557c:2b76:dca8  prefixlen 64  scopeid 0x20<link>
        ether 00:15:5d:ff:0a:00  txqueuelen 1000  (Ethernet)
        RX packets 411  bytes 82130 (82.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 464  bytes 75215 (75.2 KB)
        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 184  bytes 18181 (18.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 184  bytes 18181 (18.1 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

上述输出信息中,有三个网络接口信息,其中 docker0 网络接口是成功安装 Docker 服务后自动安装的网络桥接口。

(2)使用命令启动一个名为 centos 的容器,并在容器内部使用 ip link show 命令查看网络接口信息,如下:

root@hxvm:~# docker run -it --name centos centos /bin/bash

// 容器的网络接口信息
[root@185467f8550c /]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0

上述输出信息中,多了一个 eth0@if9 网络接口。

(3)再次返回宿主机,宿主机执行命令查看宿主机网络接口信息,如下:

hx@hxvm:~$ ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:c7ff:fe7b:2a35  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c7:7b:2a:35  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 34  bytes 4677 (4.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.27.114.197  netmask 255.255.240.0  broadcast 172.27.127.255
        inet6 fe80::3c5f:557c:2b76:dca8  prefixlen 64  scopeid 0x20<link>
        ether 00:15:5d:ff:0a:00  txqueuelen 1000  (Ethernet)
        RX packets 64435  bytes 88621497 (88.6 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 34189  bytes 3144873 (3.1 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 272  bytes 29064 (29.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 272  bytes 29064 (29.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethd42395d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::445c:25ff:feab:12e2  prefixlen 64  scopeid 0x20<link>
        ether 46:5c:25:ab:12:e2  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 25  bytes 3032 (3.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

上述输出信息中,多了一个名为 vethd42395d 的网络接口信息。

到这里为止,我们找到了三个网络接口,分别如下:

  • docker0   是一个网桥(bridge)设备。它创建了一个虚拟的网络环境,用于连接 Docker 容器。当 Docker 容器启动时,它们可以连接到这个 docker0 网桥,从而在这个虚拟网络中实现相互通信。

  • eth0@if9   是容器内部的一个虚拟网络设备,只是将名称改为了 eth0。注意:eth0@if9 名称表示eth0 接口与另一个接口(编号为 if9)存在某种关联。在 Linux 网络设备命名中,这种形式可能出现在虚拟网络设备或者网络设备的特殊连接关系中。

  • vethd42395d   当使用 docker run 运行容器时,由 Docker 自动创建的虚拟网络接口。

继续在宿主机上执行命令,查看宿主机网络接口列表信息,如下:

hx@hxvm:~$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:15:5d:ff:0a:00 brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
    link/ether 02:42:c7:7b:2a:35 brd ff:ff:ff:ff:ff:ff
9: vethd42395d@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
    link/ether 46:5c:25:ab:12:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0

上述输出信息中,最左边的序号(1、2、3、9)是网络接口索引编号,这个编号是 Linux 系统内核分配给每个网络接口的一个唯一标识符,用于在系统内部识别和管理网络接口。

根据上面的信息,加上 eth0@if9 接口名称,是不是可以猜测 eth0@if9vethd42395d@if8 是一对虚拟网络设备,如下图:

32ea0bcb2d7d946c7e34c8748ebe2c21_1726130514117-14653381-1a5b-48ca-a1af-39da5c7bb354_x-oss-process=image%2Fformat%2Cwebp.png

到这里,我们已经知道 Docker 如何使用 bridge 网络模式,以及相关的网络接口。

下面还有一些命令,可以进一步查看网络信息:

(1)使用命令查看指定容器的网络信息,例如,查看名为 centos 容器的详细信息:

root@hxvm:~# docker inspect centos
[
    {
        "Id": "185467f8550c40ed59757228414d26475725e99f48597a448663406d2ca2efe2",
        "Created": "2024-09-12T05:49:37.579501352Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 3053,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2024-09-12T05:49:37.767389387Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        //...
        "Name": "/centos", // 容器名称
        //...容器网络设置信息
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "36019ba05665ad501c902e0e78359485ef67ee82d1c17d3f85bbb0788afc5f17",
            "SandboxKey": "/var/run/docker/netns/36019ba05665",
            "Ports": {},
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "17b055fda792997461f1521b388bc81775a21f111dfb9c10268ea19174b87a2e",
            "Gateway": "172.17.0.1", // 网关地址
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2", // IP地址
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02", // MAC地址
            "Networks": {
                // 桥接模式
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null,
                    "NetworkID": "1da6aa9ec785d8cdfb1e4288168f9dec039adb2809203a757fe25e4ef10e5f94",
                    "EndpointID": "17b055fda792997461f1521b388bc81775a21f111dfb9c10268ea19174b87a2e",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DNSNames": null
                }
            }
        }
    }
]

(2)使用 命令查看 Docker 中名为 bridge 的网络模式的详细信息:

// 查看 docker 网络模式列表
root@hxvm:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
1da6aa9ec785   bridge    bridge    local
23f832eeba6e   host      host      local
f83cddfed9c2   none      null      local

// 查看指定网络模式的详细信息
root@hxvm:~# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "1da6aa9ec785d8cdfb1e4288168f9dec039adb2809203a757fe25e4ef10e5f94",
        "Created": "2024-09-12T13:32:56.8984669+08:00",
        "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,
        // 该网络模式下面的容器信息,当前仅挂载了名为centos容器
        "Containers": {
            "185467f8550c40ed59757228414d26475725e99f48597a448663406d2ca2efe2": {
                "Name": "centos",
                "EndpointID": "17b055fda792997461f1521b388bc81775a21f111dfb9c10268ea19174b87a2e",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "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",
            // 这个 bridge 的名称,是不是很熟悉,docker0
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

(3)使用 brctl show 命令查看 Linux 系统中查的网桥(bridge)信息,系统默认没有安装 brctl 命令,需要手动安装:

a、使用 apt install bridge-utils 安装 brctl 命令

root@hxvm:~# apt install bridge-utils
Reading package lists... Done
Building dependency tree... Done
...
Unpacking bridge-utils (1.7-1ubuntu3) ...
Setting up bridge-utils (1.7-1ubuntu3) ...
Processing triggers for man-db (2.10.2-1) ...

b、查看网桥信息

root@hxvm:~# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242c77b2a35       no              vethd42395d

其中:

  • bridge name  - 网桥在系统中的名称,如上述示例中的 docker0。用户可以根据需求自定义网桥名称,它用于在网络配置和管理中标识特定的网桥设备。

  • bridge id  - 网桥标识,一个唯一的标识符,用于在网络中区分不同的网桥。它由两部分组成,前面的8000 是一个固定的十六进制数,表示这是一个以太网网桥;后面的 0242c77b2a35 是网桥的 MAC 地址或者是基于 MAC 地址计算得到的值。这个标识在网络的链路层通信和一些网络管理操作(如生成树协议相关操作,如果启用了 STP)中可能会被用到。

  • STP enabled -  是否启用了生成树协议(Spanning Tree Protocol,STP)。STP 用于防止网络中的环路,确保网络的稳定性。如果显示为 yes,表示网桥启用了 STP;如果为 no,则表示未启用。

  • interfaces -  连接的接口,列出了连接到该网桥的网络接口。上面示例中,vethd42395d 连接到了 docker0 网桥。

(4)使用命令显示 Linux 网桥(bridge)的转发数据库(Forwarding Database,FDB)中的条目信息。网桥的转发数据库主要存储了 MAC 地址与网桥端口(连接到网桥的网络接口)之间的映射关系。例如:

root@hxvm:~# bridge fdb show
...
02:42:c7:7b:2a:35 dev docker0 vlan 1 master docker0 permanent
02:42:c7:7b:2a:35 dev docker0 master docker0 permanent
46:5c:25:ab:12:e2 dev vethd42395d vlan 1 master docker0 permanent
46:5c:25:ab:12:e2 dev vethd42395d master docker0 permanent
...

分析“02:42:c7:7b:2a:35 dev docker0 master docker0 permanent”:

  • 02:42:c7:7b:2a:35  是一个 MAC 地址。

  • dev docker0  表明这个 MAC 地址所属的设备是 docker0。

  • master docker0  表示这个 MAC 地址对应的设备(即docker0本身)是 docker0 的主设备。这看起来有点像一种自引用的关系,实际上这可能表示这个 MAC 地址是docker0设备在自身的网络管理和数据转发逻辑中的一个重要标识。例如,在docker0进行数据转发时,它可能会根据这个 MAC 地址以及其他相关信息来处理发往自身或者从自身发出的数据帧。

  • permanent  表示这种关联是永久性的。这意味着在正常的网络运行过程中,这个 MAC 地址与docker0设备的这种关系是相对固定的,不会轻易被修改或删除。这种永久性有助于网络的稳定运行,并且在网络管理和故障排查时,可以依据这种固定的关系来确定网络设备的状态和功能。

host 模式分析

使用 docker run 命令启动 centos 容器,并且通过 --network 选项指定网络模式为 host,如下:

(1)启动一个容器:

root@hxvm:~# docker run -it --name my_centos --network host centos /bin/bash

(2)进入容器内部,在容器内部使用 ip link show 命令查看网络接口信息:

[root@hxvm /]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:15:5d:ff:0a:00 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
    link/ether 02:42:c7:7b:2a:35 brd ff:ff:ff:ff:ff:ff

(3)最后,返回宿主机执行 ip link show 命令查看宿主机的网络接口信息:

root@hxvm:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:15:5d:ff:0a:00 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
    link/ether 02:42:c7:7b:2a:35 brd ff:ff:ff:ff:ff:ff

从上述输出的信息可知,在容器内部和宿主机执行 ip link show 命令的输出信息一致,这可以证明二者采用了同一个网络栈。

none 模式分析

使用 docker run 命令启动 centos 容器,并且通过 --network 选项指定网络模式为 none,如下:

root@hxvm:~# docker run -it --name my_centos --network none centos /bin/bash
[root@cf2394999ad2 /]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

上面命令中,在容器内部使用 ip link show 命令查看 Linux 系统中的网络接口信息。这些信息包括网络接口的名称、状态、MAC 地址、最大传输单元(MTU)等。

从输出可知,仅有一个名为 lo 的回路接口,也就意味着当前容器没有网卡,不能访问任何网络。

紧接着,我们在宿主机上运行 ip link show 命令查看网络接口信息,如下:

root@hxvm:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:15:5d:ff:0a:00 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
    link/ether 02:42:c7:7b:2a:35 brd ff:ff:ff:ff:ff:ff

从输出可知,宿主机中没有创建新的网络接口(其中,lo 是回路网络接口,eth0 是物理以太网卡,docker0 是 Docker 创建的网桥)。

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号