Docker进阶篇02 — Docker网络

概述

本章,您将学习有关 Docker network 的相关知识。

首先查看 Docker 的架构图,如下所示:

file

绝大多数读者都使用过 Vmware Workstation 的虚拟机,而在该软件中存在三种网络连接方式:

  • Bridged(桥接) - 将虚拟机的网卡与真实机的物理网卡通过一个内置的虚拟交换机(VMnet0)桥接在一起,相当于在虚拟机与物理网络之间架设了一座「桥」。此时,虚拟机的虚拟网卡和真实机的物理网卡都作为独立的端口接入这台虚拟交换机,虚拟机与真实机依靠这台交换机进行二层通信(即通过 MAC 地址识别对方并转发数据)。桥接之后,虚拟机会被当作局域网中的一台独立的主机,拥有与真实机相同的网络访问能力,特点如下:

    • 网络配置 - 虚拟机需要与真实机处于同一网段,虚拟机的网络配置可通过 DHCP 来自动获取,也可以手动配置
    • 通信范围 - 虚拟机可与局域网中的其他设备进行互相通信与访问
    • 桥接时,若真实机存在多块网卡,需要手动选择桥接到哪块网卡上
  • NAT(网络地址转换) - 利用虚拟网卡 Vmnet8 以及自带的虚拟 DHCP 服务为虚拟机提供一个独立的私有网络。在 NAT 这种连接方式下,虚拟机的所有流量将通过 NAT 转换成真实机的 IP 地址,再发送到外部网络,特点如下:

    • 网络配置 - 通过自带的虚拟 DHCP 服务(绑定在 Vmnet8)自动获取相关的网络配置。手动配置时,虚拟机的网关需要指向 NAT 设备的地址(通常是 x.x.x.2)
    • 通信范围 - 虚拟机可以主动访问真实机所处的局域网设备,但这些局域网设备不能主动访问虚拟机。从网络角度来说,此时所有虚拟机的网络都处于一个局域网中,而真实机的局域网此时相当于广域网。
  • Host-only(仅主机) - 移除了 NAT 功能或设备但保留了虚拟 DHCP 服务的连接方式。通过 Vmnet1 虚拟网卡,虚拟机只能与真实机以及使用仅主机的其他虚拟机通信,完全无法访问广域网,特点如下:

    • 网络配置 - 通过自带的虚拟 DHCP 服务(绑定在 Vmnet1)自动获取相关的网络配置,也可以手动配置
    • 通信范围 - 仅限虚拟机与真实机之间、虚拟机与虚拟机之间互相通信

简单来说就是:

  • 想让虚拟机像真实电脑一样直接加入局域网,并能相互访问 → 选 Bridged
  • 只需要虚拟机通过主机上网,不用被外部访问 → 选 NAT
  • 只想搭建一个与外界隔离的内部网络进行通信 → 选 Host-only

Docker 属于进程级的轻量虚拟化,它也有自己的网络。当 Docker 守护进程(Docker daemon)未启动时,会输出这样的错误:

Shell > docker images
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

# 活跃的网络连接信息,网络的连接名称为 ens160,应用在 ens160 这块网卡上
Shell > nmcli connection show
NAME    UUID                                  TYPE      DEVICE
ens160  0c0b3295-26e4-4c09-a861-b0562f69e8dc  ethernet  ens160

# 两块网卡(ens160 以及回环网卡)
Shell > nmcli device show
GENERAL.DEVICE:                         ens160
...
GENERAL.DEVICE:                         lo
...

一旦将 Docker 守护进程启动,可以看到,输出文本中多出了一块名称为 docker0 的虚拟网卡,其连接方式为 桥接,连接名称为 docker0。默认情况下,Docker 为虚拟网卡分配的地址为 172.17.0.1/16(IPv4 中,B 类地址中的私有地址),Docker 通过这个虚拟网卡与宿主机进行通信,当有多个容器实例时,容器实例与容器实例之间的通信也是依靠这块虚拟网卡。

Shell > systemctl start docker.service

Shell > nmcli device show
...
GENERAL.DEVICE:                         docker0
GENERAL.TYPE:                           bridge
GENERAL.HWADDR:                         02:42:7D:9D:F4:6A
GENERAL.MTU:                            1500
GENERAL.STATE:                          100 (connected (externally))
GENERAL.CONNECTION:                     docker0
GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/2
IP4.ADDRESS[1]:                         172.17.0.1/16
IP4.GATEWAY:                            --
IP4.ROUTE[1]:                           dst = 172.17.0.0/16, nh = 0.0.0.0, mt = 0
IP6.GATEWAY:                            --

在实际的生产环境下,管理好 Docker 的网络对于容器实例之间的互联通信(不管是一台机器上容器实例之间的通信,还是跨物理机器的容器实例之间的通信)会特别有用。

Dokcer 网络相关的命令

主要使用 docker network 这个命令,用法为 docker network COMMAND,其中 COMMAND 可以是以下的其中一个:

  • connect
  • create
  • disconnect
  • inspect
  • ls
  • prune
  • rm

通过 docker network ls 命令列出网络基本信息,默认情况下会创建三个网络模式:

Shell > docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
1a2216001528   bridge    bridge    local
462413705a03   host      host      local
f61762ba2839   none      null      local

您可以通过 docker network inspect 查阅更加详细的信息,比如:

Shell > docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "1a2216001528921321dc617390e9838fccac32b79af2d2f2f590b1f262013f9d",
        "Created": "2026-06-04T11:08:41.655520279+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,
        "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 网络中的网络模式

有五种网络模式,分别是:

  • bridge(常用) - 默认的桥接模式。该模式会通过 docker0 这个虚拟网卡为每一个容器实例分配并设置 IP 相关信息。在该网络模式下,容器实例之间可以相互通信,多适用于单宿主机多容器实例的情况。
  • host(常用) - 不使用 docker0 这个虚拟网卡,而是与宿主机共用一个网络命名空间,即直接使用宿主机的网络栈,这也意味着容器实例可以使用宿主机上的网络代理、路由、防火墙等功能。该模式的网络性能最好(不需要再做任何网络转换就能与外界通信),但容器实例的网络隔离很差(容器实例容易受到宿主机和其他容器实例的攻击;被使用的端口不能再使用)。
  • none - 处于该网络模式下的容器实例有独立的网络命名空间,但并没有对其进行网络配置;如果不对网络进行配置,则仅有一个 lo 回环网卡。它适用于容器实例不需要与外部进行任何网络通信的情况,实际上这种网络模式几乎不会被使用。
  • container - 新创建的容器实例不会创建专属于自己的 IP 配置信息和网卡,而是和一个已经存在的容器实例共用网络命名空间(共享 IP 和 端口范围等)。
  • 自定义网络模式

Q:如何使用网络模式?

docker run 之后的任意位置使用 --network 选项即可:

  • 针对 bridge 的用法 —— 不键入 --network--network bridge
  • 针对 host 的用法 —— --network host
  • 针对 none 的用法 —— --network none
  • 针对 container 的用法 —— --network container:容器实例名称--network container:容器实例ID
  • 针对自定义网络模式的用法 —— --network 自定义的网络名称--network 自定义的网络ID

容器实例的 IP 变动规则

拿 fedora:latest 这个镜像为例来说明,容器实例采用 bridge 网络模式。

Shell > docker pull fedora:latest

# 创建第一个容器实例,可以看到它的 IP 地址为 172.17.0.2/16
Shell > docker run -it --name="f1" fedora:latest /bin/bash
[root@29611f722111 /]#
<ctrl + p + q>

Shell > docker inspect f1 | tail -n 20
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:02",
                    "NetworkID": "1a2216001528921321dc617390e9838fccac32b79af2d2f2f590b1f262013f9d",
                    "EndpointID": "2d5f74cdeb04db762b317c49b722caa4f2641fc3e093388dc0663be2078eb2a8",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }
        }
    }
]

# 创建第二个容器实例,可以看到它的 IP 地址为 172.17.0.3/16
Shell > docker run -it --name="f2" fedora:latest /bin/bash
[root@6f9da0019546 /]#
<ctrl + p + q>

Shell > docker inspect f2 | tail -n 20
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:03",
                    "NetworkID": "1a2216001528921321dc617390e9838fccac32b79af2d2f2f590b1f262013f9d",
                    "EndpointID": "da9ddecdf530db2514d21dafdb64f0233ce8c9f68be935d15381000447845ab6",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }
        }
    }
]
# 当将 f2 这个容器实例停止且删除之后,创建 f3 这个容器实例,它的 IP 地址为 172.17.0.3/16
Shell > docker stop f2 && docker rm f2

Shell > docker run -it --name="f3" fedora:latest /bin/bash
[root@8e662375c8be /]#
<ctrl + p + q>

Shell > docker inspect f3 | tail -n 20
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:03",
                    "NetworkID": "1a2216001528921321dc617390e9838fccac32b79af2d2f2f590b1f262013f9d",
                    "EndpointID": "ecaca934941fc870302d2d993828c23644b21d978e6de3b764c51f5b419a665d",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }
        }
    }
]
# 当将 f1 容器停止后,可以看到,新创建的容器实例重新占用了 172.17.0.2/16 这个 IP 地址。
Shell > docker stop f1

Shell > docker run -it --name="f4" fedora:latest /bin/bash
[root@cfa4c953dedf /]#
<ctrl + p + q>

Shell > docker inspect f4 | tail -n 20
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:02",
                    "NetworkID": "1a2216001528921321dc617390e9838fccac32b79af2d2f2f590b1f262013f9d",
                    "EndpointID": "50aa33eb5c1ee19150204fa1278bc07cb0a0982323507c19782cbfc27357f883",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }
        }
    }
]

通过上面的例子可以得出结论,容器实例的 IP 地址会动态发生变化,其变化规则为:

  • 当 IP 地址未被占用时,以 1 为步长自动递增
  • 当前一个或多个容器实例处于未活跃的状态时(比如删除和停止),下一个新创建的容器实例的 IP 地址会继续使用原先的 IP 地址

因为容器实例的 IP 地址会动态变化,因此在调用相关容器实例时要特别注意——在调用容器实例时,不要将 IP 地址固定。也因为这种 IP 地址变化的特性,Docker 的网络管理就显得非常重要。

Shell > docker stop f1 f2 f3 f4 && docker rm f1 f2 f3 f4

Bridge

如下图所示:

file

  1. Docker 守护进程启动之后,会自动创建一个被称为 docker0 的虚拟网卡(类似于有多个接口的交换机,每个接口都被称为 veth)。
  2. 每个容器实例内部都有一块网卡,每个接口被称为 eth0
  3. docker0 是每个容器实例的默认网关
  4. docker0 上面的每个 veth 会匹配对应容器实例的内部 eth0

以 tomcat:latest 这个镜像来说明具体的说明:

Shell > docker pull tomcat:latest

Shell > docker run -d --name="t1" tomcat:latest
b99024c494461b62bbf563aa78f98172b1436126a4d63697d0fffa1c7e19573d

Shell > docker run -d --name="t2" tomcat:latest
6cf02a70f6a602582638f0afc5a5a13a8213162f9148f6c0f84252dbb503b732

Shell > 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:b3:41:fd brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.100.20/24 brd 192.168.100.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 240e:36a:836c:2500:20c:29ff:feb3:41fd/64 scope global dynamic noprefixroute
       valid_lft 225175sec preferred_lft 138775sec
    inet6 fe80::20c:29ff:feb3:41fd/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:7d:9d:f4:6a 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
    inet6 fe80::42:7dff:fe9d:f46a/64 scope link
       valid_lft forever preferred_lft forever
14: veth08afb28@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether ea:36:96:7e:8d:80 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::e836:96ff:fe7e:8d80/64 scope link
       valid_lft forever preferred_lft forever
16: vethbe13829@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 4a:83:43:83:b2:12 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::4883:43ff:fe83:b212/64 scope link
       valid_lft forever preferred_lft forever

如上面的例子,我们创建了两个容器实例,此时的网卡又多出了两块——veth08afb28(网卡的接口索引为 14,"@" 后面的 if13 表示对应容器实例的网卡接口索引为 13) 和 vethbe13829(网卡的接口索引为 16,"@" 后面的 if15 表示对应于容器实例的网卡接口索引为 15)

进入到 t1 容器实例的内部:

Shell > docker exec -it t1 /bin/bash

root@b99024c49446:/usr/local/tomcat# apt-get update && apt-get -y install iproute2
root@b99024c49446:/usr/local/tomcat# 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
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

可以看到,容器 t1 的内部网卡为 eth0 。此时,宿主机上接口索引为 14 的网卡与容器实例上接口索引为 13 的网卡对应上。

提示
ip a 命令的输出中,冒号左边的数字被称为接口索引(interface index),此数字是唯一的,用来标识接口。
Shell > docker stop t1 t2 && docker rm t1 t2

Host

前面提到,使用该网络模式的容器实例会与宿主机共用一个网络命名空间(Network Namespace),该模式的网络性能最好(不需要再做任何网络转换就能与外界通信),但容器实例的网络隔离很差(容器实例容易受到宿主机和其他容器实例的攻击;被使用的端口不能再使用)。

同样的,以 tomcat:latest 这个镜像为例来说明:

Shell > docker run -d -p 8080:8080 --network host --name="tomcat-host" tomcat:latest
WARNING: Published ports are discarded when using host network mode
290e0a75c7a032e882ae3fbd3876b3f7d914128a93b8061ad2ec295714335516

当容器实例使用这种网络模式时,如果使用 -p 选项指定端口映射,则回车之后会输出警告信息(容器实例直接使用宿主机的 IP 和端口号,-p 选项失去了作用且没有任何意义)

Shell > docker inspect tomcat-host | tail -n 21
            "Networks": {
                "host": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "",
                    "NetworkID": "462413705a038a93da3bcd7c3b3f8ace37895b2f9312419d17829b002c6ae338",
                    "EndpointID": "868c807fcc30d862245cbecf9bd1d19de94cd0106b574c3c293af8f7f302297a",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }
        }
    }
]
# 查阅宿主机的网络信息
Shell > 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:b3:41:fd brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.100.20/24 brd 192.168.100.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 240e:36a:836c:2500:20c:29ff:feb3:41fd/64 scope global dynamic noprefixroute
       valid_lft 224144sec preferred_lft 137744sec
    inet6 fe80::20c:29ff:feb3:41fd/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:7d:9d:f4:6a 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
    inet6 fe80::42:7dff:fe9d:f46a/64 scope link
       valid_lft forever preferred_lft forever

# 进入到 tomcat-host 这个容器实例
## 可以看到,容器实例的网卡信息与宿主机的网卡信息几乎一致。
Shell > docker exec -it tomcat-host bash
root@HOME01:/usr/local/tomcat# apt-get update && apt-get -y install iproute2

root@HOME01:/usr/local/tomcat# 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:b3:41:fd brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.100.20/24 brd 192.168.100.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 240e:36a:836c:2500:20c:29ff:feb3:41fd/64 scope global dynamic noprefixroute
       valid_lft 223967sec preferred_lft 137567sec
    inet6 fe80::20c:29ff:feb3:41fd/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:7d:9d:f4:6a 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
    inet6 fe80::42:7dff:fe9d:f46a/64 scope link
       valid_lft forever preferred_lft forever
Shell > docker stop tomcat-host && docker rm tomcat-host

None

直接键入命令查看:

Shell > docker run -d --name="tomcat-none" --network none tomcat:latest
1bc3d9f2f9d593684f3bc00b8331510a4e9d4c32c218568f644613e241816caf

Shell > docker inspect tomcat-none | tail -n 21
            "Networks": {
                "none": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "",
                    "NetworkID": "f61762ba2839b1eda3f58c86b056e5d16f4c8429ea448c75e902f344130a5f7f",
                    "EndpointID": "beac014089d2b748e9121d54703c6ec85f5cca9bc63401a1e531561286dcf02b",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }
        }
    }
]
Shell > docker stop tomcat-none && docker rm tomcat-none

Container

这里以 nginx:latest 的镜像来进行演示与说明。

警告
当容器实例使用 container 网络模式时,不能使用 -p 选项,否则你要看到类似这样的错误输出——"docker: Error response from daemon: conflicting options: port publishing and the container type network mode."
另外请注意!当容器实例借用另外一个容器实例的网络时,这个另外的容器实例 **必须** 处于活跃状态。

创建 nginx 容器实例,不指定端口,默认对外暴露 80/TCP 端口:

Shell > docker pull nginx:latest

Shell > docker run -d --name="nginx-source" --network bridge nginx:latest
840e5839603bb17a6be3d0045b6fa6c01b3b699921bff17a2af3127ddca767f2

Shell > 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:b3:41:fd brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.100.20/24 brd 192.168.100.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 240e:36a:836c:2500:20c:29ff:feb3:41fd/64 scope global dynamic noprefixroute
       valid_lft 223642sec preferred_lft 137242sec
    inet6 fe80::20c:29ff:feb3:41fd/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:7d:9d:f4:6a 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
    inet6 fe80::42:7dff:fe9d:f46a/64 scope link
       valid_lft forever preferred_lft forever
18: veth2540ffe@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether aa:98:42:c6:1b:94 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::a898:42ff:fec6:1b94/64 scope link
       valid_lft forever preferred_lft forever

Shell > docker inspect nginx-source | grep -i "exposed" -C 3
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Tty": false,

创建 tomcat 容器实例,借用 nginx-source 容器实例的网络:

Shell > docker run -d --name="tomcat-container" --network container:nginx-source tomcat:latest
2e1cd58025b3e95f14121e127a0deb4a74c28a10f3111ee61c877c8f4fe1c7d9

# 并没有产生新的虚拟网卡设备
Shell > 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:b3:41:fd brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.100.20/24 brd 192.168.100.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 240e:36a:836c:2500:20c:29ff:feb3:41fd/64 scope global dynamic noprefixroute
       valid_lft 223415sec preferred_lft 137015sec
    inet6 fe80::20c:29ff:feb3:41fd/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:7d:9d:f4:6a 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
    inet6 fe80::42:7dff:fe9d:f46a/64 scope link
       valid_lft forever preferred_lft forever
18: veth2540ffe@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether aa:98:42:c6:1b:94 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::a898:42ff:fec6:1b94/64 scope link
       valid_lft forever preferred_lft forever

# 如您所见,第二个容器实例在网络方面的信息几乎没有
Shell > docker inspect tomcat-container | tail -n 22
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "",
            "SandboxKey": "",
            "Ports": {},
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "",
            "Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "MacAddress": "",
            "Networks": {}
        }
    }
]

# 对外暴露 8080/TCP 端口
Shell > docker inspect tomcat-container | grep -i "exposed" -C 3
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "8080/tcp": {}
            },
            "Tty": false,

# 进入到容器实例 tomcat-container 的内部
Shell > docker exec -it tomcat-container /bin/bash

root@840e5839603b:/usr/local/tomcat# apt-get update && apt-get -y install iproute2
## 查看容器实例的网络信息
root@840e5839603b:/usr/local/tomcat# 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
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

如果将第一个容器实例停止,则第二个容器实例的网络会输出这样的文本信息(这也验证了前面的警告信息——"容器实例借用另外一个容器实例的网络时,这个另外的容器实例 必须 处于活跃状态"):

Shell > docker stop nginx-source

Shell > docker exec -it tomcat-container /bin/bash
root@840e5839603b:/usr/local/tomcat# 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
Shell > docker stop nginx-source tomcat-container && docker rm nginx-source tomcat-container

自定义网络

有时,我们希望所有容器实例的网络按照实际的需求合理规划且相互之间完成通信;前面演示过 Docker 容器实例内部的 IP 地址会动态变化,这导致容器实例之间通过固定的 IP 地址进行通信就会很麻烦。基于前面的两点,我们就需要自定义网络。有了自定义网络之后,相互 ping 不再需要 IP 地址,而是通过 容器实例的名称(因为自定义网络本身已经维护好了容器实例名称与 IP 之间的对照关系),来看下面的演示:

# 创建自定义网络
Shell > docker network create my-network -d bridge
a443674bef1ade5ee8ad071ed7458c6738703f04b2658a9ea652b25604ccfde0

Shell > docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
1a2216001528   bridge       bridge    local
462413705a03   host         host      local
a443674bef1a   my-network   bridge    local
f61762ba2839   none         null      local

# 创建第一个容器实例
Shell > docker run -d --name="tomcat-1" --network my-network tomcat:latest
fdc4c1262c9d5379819ee5aa4d0bf37ea542104ed7b041df9f92257bb061fa37

# 创建第二个容器实例
Shell > docker run -d --name="tomcat-2" --network my-network tomcat:latest
6213c8d7777f24af385e5f34e25c40444af253485d76cd864181311c386f2df2

# 进入到第一个容器实例的内部,ping 第二个容器实例
Shell > docer exec -it tomcat-1 /bin/bash
root@fdc4c1262c9d:/usr/local/tomcat# apt-get update && apt-get -y install iputils-ping
root@fdc4c1262c9d:/usr/local/tomcat# ping tomcat-2 -c 5
PING tomcat-2 (172.19.0.3) 56(84) bytes of data.
64 bytes from tomcat-2.my-network (172.19.0.3): icmp_seq=1 ttl=64 time=0.075 ms
64 bytes from tomcat-2.my-network (172.19.0.3): icmp_seq=2 ttl=64 time=0.093 ms
64 bytes from tomcat-2.my-network (172.19.0.3): icmp_seq=3 ttl=64 time=0.191 ms
64 bytes from tomcat-2.my-network (172.19.0.3): icmp_seq=4 ttl=64 time=0.125 ms
64 bytes from tomcat-2.my-network (172.19.0.3): icmp_seq=5 ttl=64 time=0.132 ms

--- tomcat-2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4088ms
rtt min/avg/max/mdev = 0.075/0.123/0.191/0.039 ms

笔记
自定义网络在 Docker 集群环境中非常重要!

删除:

Shell > docker stop tomcat-1 tomcat-2 && docker rm tomcat-1 tomcat-2 && docker network rm my-network
Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇