Docker:Docker Network容器之间及容器与外部世界的通信桥梁

Docker:Docker Network容器之间及容器与外部世界的通信桥梁

一.docker网络架构及常见网络类型

Docker 容器网络是为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、 IP 协议栈、端口套接字、 IP路由表、防火墙等等与网络相关的模块。Docker 为实现容器网络,主要采用的架构由三部分组成: CNM、 Libnetwork 和驱动。
CNM

Docker 网络架构采用的设计规范是 CNM(Container Network Model)。 CNM 中规定了 Docker 网络的基础组成要素: Sandbox、 Endpoint、 Network。

  • Sandbox:提供了容器的虚拟网络栈,也即端口、套接字、 IP 路由表、防火墙、DNS 配置等内容。主要用于隔离容器网络与宿主机网络,形成了完全独立的容器网络环境。
  • Network: Docker 内部的虚拟子网,使得网络内的参与者能够进行通讯。
  • Endpoint:就是虚拟网络的接口,就像普通网络接口一样, Endpoint 的主要职责是负责创建连接。 Endpoint 类似于常见的网络适配器,那也就意味着一个 Endpoint 只能接入某一个网络, 当容器需要接入到多个网络,就需要多个 Endpoint。

如上图所示,容器 B 有两个 Endpoint 并且分别接入 Networkd A 和 Network B。那么容器 A 和容器 B 之间是可以实现通信的,因为都接入了 NetworkA。但是容器 A 和容器 C 不可以通过容器 B 的两个 Endpoint 通信。
Libnetwork

Libnetwork 是 CNM 的一个标准实现。 Libnetwork 是开源库,采用 Go 语言编写(跨平台的),也是 Docker 所使用的库, Docker 网络架构的核心代码都在这个库中。Libnetwork 实现了 CNM 中定义的全部三个组件,此外它还实现了本地服务发现、基于 Ingress 的容器负载均衡,以及网络控制层和管理层等功能。
驱动

驱动主要负责实现数据层相关内容,例如网络的连通性和隔离性是由驱动来处理的。驱动通过实现特定网络类型的方式扩展了 Docker 网络栈,例如桥接网络和覆盖网络。

Docker 内置了若干驱动,通常被称作原生驱动或者本地驱动。例如 Bridge Driver、Host Driver、 Overlay Driver、 MacVLan Driver、 IPVLan Driver、 None Driver 等等。每个驱动负责创建其上所有网络资源的创建和管理。
docker中的网络类型

  1. bridge 网络
    bridge 驱动会在 Docker 管理的主机上创建一个 Linux 网桥。默认情况下,网桥上的容器可以相互通信。也可以通过 bridge 驱动程序配置,实现对外部容器的访问。Docker 容器的默认网络驱动.当我们需要多个容器在同一个 Docker 主机上通信时,桥接网络是最佳选择。
  2. host 网络
    对于独立容器,移除容器和 Docker 主机之间的网络隔离,并直接使用主机的网络。当网络堆栈不应该与 Docker 主机隔离,但是希望容器的其他资源被隔离时,主机网络是最佳选择。
  3. container 网络
    这个模式指定新创建的容器和引进存在的一个容器共享一个网络 ,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 ip,而是和一个指定的容器共享 ip,端口等,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信
  4. none 网络
    Docker 容器拥有自己的 Network Namespace,但是,并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、 IP、路由等信息。容器完全网络隔离。
  5. overlay 网络
    借助 Docker 集群模块 Docker Swarm 搭建的跨 Docker Daemon 网络。将多个Docker 守护进程连接在一起,使集群服务能够相互通信。当我们需要运行在不同Docker 主机上的容器进行通信时,或者当多个应用程序使用集群服务协同工作时,覆盖网络是最佳选择。

另外,在 Docker 安装时,会自动安装一块 Docker 网卡称为 docker0,它是一个网桥设备,主要用于 Docker 各容器及宿主机的网络通信。

二.docker网络管理命令

2.1docker网络常用命令清单

命令 参数示例 功能描述
docker network create --driver bridge --subnet 192.168.0.0/16 mynet 创建新网络,可指定驱动、子网等
docker network connect mynet mycontainer 将运行中的容器连接到指定网络
docker network disconnect mynet mycontainer 将容器从指定网络断开连接
docker network ls / list -f "driver=bridge" 列出所有网络,支持过滤器
docker network prune --force 删除所有未被使用的网络
docker network inspect mynet 显示网络的详细信息,包括连接容器、IP配置等
docker network rm / remove mynet1 mynet2 删除一个或多个网络

2.2docker网络命令认识与使用

docker network create

docker network create
功能

创建自定义网络
语法

bash 复制代码
docker network create [OPTIONS] NETWORK

关键参数

  • -d, --driver: 网络驱动
  • --gateway: 网关地址当使用docker network create命令创建网络时,如果不显示指定网关地址Docker会自动从子网中分配一个网关地址。默认情况下,Docker会使用子网中的第一个可用IP地址作为网关地址。例如,如果创建的网络子网为192.168.0.0/16,那么网关地址通常会被设置为192.168.0.1。
  • --subnet: 表示网段的 CIDR 格式的子网
  • --ipv6: 启用 ipv6

这里我们先来回顾下私网IP。如果一个组织内部组建局域网,IP 地址只用于局域网内的通信,而不直接连到 Internet 上,理论上使用任意的 IP 地址都可以,但是 RFC 1918 规定了用于组建局域网的私有 IP 地址。

再回顾下之前学习过的子网掩码的概念:

子网掩码从左到右的1是连续的,也就是说不可能出现不连续的情况(比如10111111 11111111 11111111 0000000)。怎么理解上图呢,我们将一个IP地址与子网掩码按位与运算,拿第一个为例,按位与的结果即为当前IP地址对应的网络号,而子网掩码此时后8位是0,也就是说当前IP地址能容纳的最大主机数为2^8次方台,也就是256台。

实际上为254台,因为140.252.20.0 IP地址与网络号相同的地址被称为网络地址(Network Address),标识整个子网本身,不可分配给主机使用。而140.252.20.255为子网掩码无效部分全为1的地址 → 广播地址(Broadcast Address),用于向子网内所有主机发送广播数据包,不可分配给主机。

如果想要更加详细的回顾,可以参考我之前写过的一篇文章:
从网络层与数据链路层核心协议浅析 NAT、代理服务与内网穿透机制

上面的内容也是从我之前写的这篇文章中摘取的。

驱动我们一般是不会动它的,如果想要深入了解的读者可以自行搜索研究。这里我们创建一个自定义的bridge网络:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker network create --subnet=192.168.0.0/16 mynet1
[sudo] password for knd:                                            
ac351cea4dad2defd09a993fb4d41459cb4195f12272a8d3b8edd788eef14005
knd@NightCode:~/dockertest$ sudo docker inspect mynet1
...
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "IPRange": "",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
...

可以看到,此网络的默认网关地址是192.168.0.1。而--subnet后面跟的是一个CIDR 格式的子网。如果我们显示指定了--gateway那上面Gateway显示的网关地址就是我们自己指定的ip地址。

docker network inspect

docker network inspect
功能

查看网络详情
语法

bash 复制代码
docker network inspect [OPTIONS] NETWORK [NETWORK...]

关键参数

  • -f,--format:指定格式

这里的format还是遵循go语言的输入的格式的,所以想要深入了解其他格式的输出方式的读者可以自行在官方文档中进行查询认识。我们这里看下它以json输出时的样子:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker inspect -f json  mynet1
[{"Name":"mynet1","Id":"ac351cea4dad2defd09a993fb4d41459cb4195f12272a8d3b8edd788eef14005","Created":"2025-12-30T15:50:03.007831105+08:00","Scope":"local","Driver":"bridge","EnableIPv4":true,"EnableIPv6":false,"IPAM":{"Driver":"default","Options":{},"Config":[{"Subnet":"192.168.0.0/16","IPRange":"","Gateway":"192.168.0.1"}]},"Internal":false,"Attachable":false,"Ingress":false,"ConfigFrom":{"Network":""},"ConfigOnly":false,"Options":{},"Labels":{},"Containers":{},"Status":{"IPAM":{"Subnets":{"192.168.0.0/16":{"IPsInUse":3,"DynamicIPsAvailable":65533}}}}}]

docker network connect

docker network connect
功能

将容器连接到网络。可以按名称或 ID 连接容器。 一旦连接,容器可以与同一网络中的其他容器通信。
语法

bash 复制代码
docker network connect [OPTIONS] NETWORK CONTAINER

关键参数

  • --ip: 指定 IP 地址
  • --ip6: 指定 IPv6 地址

这里我们使用busybox镜像运行容器进行示例,默认情况下,如果我们不指定network,它默认连接的是docker运行时默认就有的一个名为bridge的自定义网络。

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run -itd --name b1 busybox
32beea9f3125cf6f162b0dcb00aab47d9f94efe10214e4086887fc87281d173c
knd@NightCode:~/dockertest$ sudo docker exec -it b1 sh
/ # ifconfig
...
eth0      Link encap:Ethernet  HWaddr B2:5B:FC:35:1B:D6  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:9 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:806 (806.0 B)  TX bytes:126 (126.0 B)
...
/ # exit
knd@NightCode:~/dockertest$ sudo docker inspect bridge
...
        "Containers": {
            "32beea9f3125cf6f162b0dcb00aab47d9f94efe10214e4086887fc87281d173c": {
                "Name": "b1",
                "EndpointID": "af558f3598501bafed71afdaecd4d6edaf36291b06f20dddab68006bd5d480f3",
                "MacAddress": "b2:5b:fc:35:1b:d6",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
...

如果我们指定了自定义网络,那么初始时便不会连接默认的bridge网络:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run -itd --network mynet1 --name b2 busybox
7ec808101acae70b4c3c0dc2173a5c0ebb37ac016e7fd5771c282fcf21aba9e2
knd@NightCode:~/dockertest$ sudo docker exec -it b2 sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 22:44:2E:63:25:0D  
          inet addr:192.168.0.2  Bcast:192.168.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1182 (1.1 KiB)  TX bytes:126 (126.0 B)
...

/ # exit
knd@NightCode:~/dockertest$ sudo docker inspect mynet1
...
        "Containers": {
            "7ec808101acae70b4c3c0dc2173a5c0ebb37ac016e7fd5771c282fcf21aba9e2": {
                "Name": "b2",
                "EndpointID": "5e896ddf69d3ffd98314677aee38762e6f9e22a66b21cf6118f9f57de68a9a33",
                "MacAddress": "22:44:2e:63:25:0d",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
...

如果刚开始我们并没有指定,后面又使用connect进行了连接,那么ifconfig就会看到两个自定义网络,一个docker默认就有的bridge,还有一个我们自己的自定义网络:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker network connect --ip 192.168.0.3 mynet1 b1
knd@NightCode:~/dockertest$ sudo docker exec -it b1 ifconfig
eth0      Link encap:Ethernet  HWaddr 6E:AB:E3:A8:1D:04  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1016 (1016.0 B)  TX bytes:126 (126.0 B)

eth1      Link encap:Ethernet  HWaddr C2:26:8E:46:2D:AB  
          inet addr:192.168.0.3  Bcast:192.168.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:656 (656.0 B)  TX bytes:126 (126.0 B)
...

docker network disconnect

docker network disconnect
功能

断开网络
语法

bash 复制代码
docker network disconnect [OPTIONS] NETWORK CONTAINER

关键参数

  • -f:强制退出

这里我们让上面连接了自定义网络的b1容器退出我们刚开始创建的自定义网络:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker network disconnect mynet1 b1
knd@NightCode:~/dockertest$ sudo docker exec -it b1 ifconfig
eth0      Link encap:Ethernet  HWaddr 6E:AB:E3:A8:1D:04  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1086 (1.0 KiB)  TX bytes:126 (126.0 B)
...

docker network prune

docker network prune
功能

删除不使用 的网络
语法

bash 复制代码
docker network prune [OPTIONS]

关键参数

  • -f, --force : 不提示

不再演示

docker network rm

docker network rm
功能

删除 1 个或者多个网络
语法

bash 复制代码
docker network rm NETWORK [NETWORK...]

关键参数

  • -f:强制退出

不再演示

docker network ls

docker network ls
功能

列出网络
语法

bash 复制代码
docker network ls [OPTIONS]

别名

bash 复制代码
docker network list

关键参数

  • -f, --filter:指定过滤条件
  • --format:指定格式
  • --no-trunc:不截断
  • -q, --quiet :仅仅显示 id

这些命令都和我们之前用过的差不太多,我们这里就不再过多演示了。

三.docker网络详细认识

3.1docker bridge

Docker Bridge 网络采用内置的 bridge 驱动, bridge 驱动底层采用的是 Linux 内核中Linux bridge 技术。就网络而言, bridge 网络是在网络段之间转发流量的链路层设备,而网桥可以是在主机内核中运行的硬件设备或软件设备;就 Docker 而言,桥接网络使用软件网桥 docker0,它允许连接到同一网桥网络的容器进行通信,同时提供与未连接到该网桥网络容器的隔离。

Docker Container 的 bridge 桥接模式可以参考下图:

默认情况下,创建的容器在没有使用--network 参数指定要加入的 docker 网络时,默认都是加入 Docker 默认的单机桥接网络,即我们之前看到的 name 为 bridge 的网络。

默认的 bridge 网络会被映射到内核中为 docker0 的网桥上。

Docker 默认的 bridge 网络和 Linux 内核中的 docker0 网桥是一一对应的关系。bridge 是 Docker 对网络的命名,而 docker0 是内核中网桥的名字。

我们之前学习的网络通信如果是两台主机可以直接通过连接网线的两端进行通信。那多台主机通信怎么处理呢?这就需要新增路由器/交换机,把多台主机连接到路由器/交换机上, 通过路由器/交换机来达到交换数据, 即通信的目的。

其实容器之间的通信也和上面主机通信的方式如出一辙, 之前我们提到了安装 Docker的时候会默认 docker0 这个网桥软件设备, 这个 docker0 设备可以类比成上图的交换机/路由器设备,当我们创建好容器之后, 如果不手动指定网络模式,默认会使用bridge 网络, 器会自动连接到 docker0 这个网桥设备, 然后通过这个网桥来进行容器间的通信。

使用ping命令验证容器之间的网络联通性

我们可以使用ping命令验证下两个容器之间是否真的能够进行通信,我们让b1重新连接上我们最开时自定义的网络:

bash 复制代码
 knd@NightCode:~/dockertest$ sudo docker network connect --ip 192.168.0.254 mynet1 b1
knd@NightCode:~/dockertest$ sudo docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
7ec808101aca   busybox   "sh"      14 minutes ago   Up 14 minutes             b2
32beea9f3125   busybox   "sh"      19 minutes ago   Up 11 minutes             b1
knd@NightCode:~/dockertest$ sudo docker exec -it b1 sh
/ # ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: seq=0 ttl=64 time=0.096 ms
64 bytes from 192.168.0.2: seq=1 ttl=64 time=0.070 ms
64 bytes from 192.168.0.2: seq=2 ttl=64 time=0.071 ms
64 bytes from 192.168.0.2: seq=3 ttl=64 time=0.071 ms
^C
--- 192.168.0.2 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.077/0.096 ms
/ # exit
knd@NightCode:~/dockertest$ sudo docker exec -it b2 sh
/ # ping 192.168.0.254
PING 192.168.0.254 (192.168.0.254): 56 data bytes
64 bytes from 192.168.0.254: seq=0 ttl=64 time=0.060 ms
64 bytes from 192.168.0.254: seq=1 ttl=64 time=0.078 ms
64 bytes from 192.168.0.254: seq=2 ttl=64 time=0.061 ms
64 bytes from 192.168.0.254: seq=3 ttl=64 time=0.064 ms
^C
--- 192.168.0.254 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.060/0.065/0.078 ms
/ # exit
knd@NightCode:~/dockertest$ 

可以看到两个容器之间是可以正常通信的。

DNS解析

Docker 自定义桥接网络是支持通过 Docker DNS 服务进行域名解析的, 也就是说我们可以直接使用容器名 进行通信,因为 DNS 服务可以解析容器名到 IP 地址的映射, 但是默认的 bridge 网络是不支持 DNS 的。

我们先来验证下默认的bridge是否支持DNS解析,这里我们新启一个b3容器并不指定其自定义网络让他和b1进行通信:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker exec -it b3 sh
/ # ping b1
ping: bad address 'b1'

可以看到二者之间是无法通过容器名称直接访问彼此的。我们在来看下已经连接到同一个自定义bridge网络的b1与b2:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker exec -it b1 sh
/ # ping b2
PING b2 (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: seq=0 ttl=64 time=0.054 ms
64 bytes from 192.168.0.2: seq=1 ttl=64 time=0.072 ms
^C
--- b2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.054/0.063/0.072 ms
/ # exit
knd@NightCode:~/dockertest$ sudo docker exec -it b2 sh
/ # ping b1
PING b1 (192.168.0.254): 56 data bytes
64 bytes from 192.168.0.254: seq=0 ttl=64 time=0.049 ms
64 bytes from 192.168.0.254: seq=1 ttl=64 time=0.066 ms
^C
--- b1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.049/0.057/0.066 ms
/ # exit

能够看到自定义的bridge网络是能够正常通过容器名称访问彼此的。

端口暴露与转发

这其实就是我们之前访问nginx容器中使用过的技术。
暴露方式

端口暴露有 2 种方式,在启动容器的时候添加端口参数,一种-P 暴露所有端口,一种是-p,暴露指定端口
-P

将指定的容器端口映射至主机所有地址的一个动态端口, "动态端口"指随机端口,具体的映射结果可使用 docker port 命令查看
-p :

将容器端口映射至指定的主机端口
端口转发

连接 bridge 网络的容器只能与连接在当前网络中的容器进行通信。如果一个容器想要对外提供一些网络服务的话,需要进行端口转发才可以实现。

端口转发将 Docker 容器的端口映射到宿主机的端口上,那么任何发送到宿主机该端口的流量,都会被转发到容器的端口中。如下图所示,两个容器内部均开放 80 端口,它们分别映射到宿主机的 8088 和 8089 端口, 即表示任何发送到 8088 端口的流量都会转发到 Container 1 容器的 80 端口, 发送到 8089 端口的流程都会转发到Container 2 容器的 80 端口。

这里我们就不做演示了,毕竟前面已经整过不少次了。

3.2docker host网络

说直白点,就是我容器干脆不进行网络环境隔离了,你主机的网络就是我的。我们在来看下概念:

Docker 容器运行默认都会分配独立的 Network Namespace 隔离子系统, 但是如果基于 host 网络模式,容器将不会获得一个独立的 Network Namespace,而是和宿主机共用同一个 Network ,Namespace,容器将不会虚拟出自己的网卡, IP 等,而是直接使用宿主机的 IP 和端口。

连接到 host 网络的容器共享宿主机的网络栈,容器的网络配置与宿主机完全一样。我们可以通过 --network=host 指定使用 host 网络。

我们可以看下一个使用host网络的nginx容器是怎么样的:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run -d --name nginx --network=host nginx:1.29.4
87e9cf384f1185a5d1b9e3b893986b0814aed505c579fd1fd0c195625677fb82

可以看到我这里并没有暴露任何端口,我们直接使用浏览器访问我们自己云服务器的ip地址试试:

可以看到直接就访问成功了。我们在起一个使用主机网络的busybox容器来看下主机的ifconfig与容器ifconfig的区别:

bash 复制代码
knd@NightCode:~/dockertest$ ifconfig
br-ac351cea4dad: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.1  netmask 255.255.0.0  broadcast 192.168.255.255
        inet6 fe80::e00a:a3ff:feb6:6b59  prefixlen 64  scopeid 0x20<link>
        ether e2:0a:a3:b6:6b:59  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
...
knd@NightCode:~/dockertest$ sudo docker exec -it b4 ifconfig
br-ac351cea4dad Link encap:Ethernet  HWaddr E2:0A:A3:B6:6B:59  
          inet addr:192.168.0.1  Bcast:192.168.255.255  Mask:255.255.0.0
          inet6 addr: fe80::e00a:a3ff:feb6:6b59/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:10 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:280 (280.0 B)  TX bytes:526 (526.0 B)
...

答案是没有区别。

3.3docker container网络

跟host类似,就等于直接把其他容器的网络抢过来使用了。

Docker Container 的 other container 网络模式是 Docker 中一种较为特别的网络的模式。之所以称为"other container 模式",是因为这个模式下的 Docker Container,会使用其他容器的网络环境。之所以称为"特别",是因为这个模式下容器的网络隔离性会处于 bridge 桥接模式与 host 模式之间。 Docker Container 共享其他容器的网络环境,则至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。

Docker Container 的 other container 网络模式可以参考下图:

Docker Container 的 other container 网络模式实现逻辑如下:

  1. 查找 other container(即需要被共享网络环境的容器)的网络 namespace;
  2. 将新创建的 Docker Container(也是需要共享其他网络的容器)的 namespace,使用 other container 的 namespace

我们这里新启一个容器,让他绑定一个自定义bridge网络,然后再启一个容器让他绑定前面启动的容器的网络:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run -itd --network=mynet1 --name b1 busybox
c63778c47bb819488d1b28a2ed49ce13f1788953c209039533fa167c7ff8ba52
knd@NightCode:~/dockertest$ sudo docker run -itd --network=container:b1 --name b2 busybox
5f06215233c5c5b0e4ea33e2ec66de968f87f51b50fc5beeda2ac8c62fcecd7e
knd@NightCode:~/dockertest$ sudo docker exec -it b1 ifconfig
eth0      Link encap:Ethernet  HWaddr FA:3B:AB:25:E6:5A  
          inet addr:192.168.0.2  Bcast:192.168.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:10 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:876 (876.0 B)  TX bytes:126 (126.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

knd@NightCode:~/dockertest$ sudo docker exec -it b2 ifconfig
eth0      Link encap:Ethernet  HWaddr FA:3B:AB:25:E6:5A  
          inet addr:192.168.0.2  Bcast:192.168.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:11 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:946 (946.0 B)  TX bytes:126 (126.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

可以看到这两个容器的网络信息是一样的。如果我们把b1给停止了呢?

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker stop b1
b1
knd@NightCode:~/dockertest$ sudo docker exec -it b2 ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

b2容器就无法连接到自定义网络了,那此时我们再把b1容器重新启动呢?

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker start b1
b1
knd@NightCode:~/dockertest$ sudo docker exec -it b2 ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

还是没有,那我们把b2容器重新启动下看看:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker restart b2
b2
knd@NightCode:~/dockertest$ sudo docker exec -it b2 ifconfig
eth0      Link encap:Ethernet  HWaddr 1E:7C:04:66:2F:95  
          inet addr:192.168.0.2  Bcast:192.168.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:11 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:946 (946.0 B)  TX bytes:126 (126.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

怎么说呢,可以这么理解。如果我们家中的路由器本来是开着的,你的设备也连接到了路由器,但是路由器突然关闭了。那么我们的设备自然就连接不上网络了。此时我们重启路由器,但是我们的设备并没有设置没有网络时自动连接此路由器,那此时我们的设备还是没有网的。就必须我们手动重新连接下路由器才能使我们的设备重新有网。

3.4docker none网络

人如其名,就是我的容器不开放任何与外界通信的渠道。ifconfig只能查询到本地环回地址的信息。
使用场景:

  • 针对一些对安全性要求比较高并且不需要联网的应用, 可以使用 none 网络, 比如生成随机密码, 避免生成密码被第三方获取。
  • 一些第三方的应用可能需要 docker 帮忙创建一个没有网络的容器, 网络由第三方自己来配置。
    在运行容器的时候,可以通过--network=none 参数来指定容器使用 none 网络。
bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run -itd --network=none --name b3 busybox
29d8945f577d34c08fb0f30fc539d36bc603650c62d60e9a731d23e30da9c278
knd@NightCode:~/dockertest$ sudo docker exec -it b3 ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

可以看到这个busybox容器只有一个本地环回地址,是无法与其他容器更不用说宿主机甚至互联网进行通信了。

3.5docker overlay网络

Overlay 网络是 Docker 用来把不同主机上的容器连到同一个虚拟网络上的方案 。它在现有物理(或云)网络之上构建一层"覆盖"网络(通常通过 VXLAN 来封装流量),使得同一个 overlay 网络内的容器无论运行在哪台主机上都能像在同一局域网内一样互相通信。对用户来说,这意味着容器可以用私有 IP 和内置 DNS 名称互相发现和访问,网络隔离与命名空间由 Docker 管理,应用可以跨主机扩展而无需手动配置路由或 VPN。

在实际使用上,overlay 常与 Docker Swarm(或其它编排器)配合:创建 overlay 网络后,部署服务时把服务加入该网络,Swarm 会负责服务发现、内建负载均衡以及(可选的)流量加密。优点是部署简单、支持多主机扩容且能隔离租户;需要注意的地方有性能开销与 MTU 限制(封装会增加包长)、以及防火墙/路由需要允许 VXLAN 相关端口(例如 UDP 4789)。示例命令:docker network create -d overlay --attachable mynet,然后在 Swarm 服务或独立容器中使用 --network mynet 将其连接到该 overlay 网络。

这里暂时还不好进行解释,我们放到后面再来详细认识下这个网络类型。

相关推荐
无限大.2 小时前
为什么“容器化“技术很重要?——从虚拟机到 Docker
运维·docker·容器
幺零九零零2 小时前
Docker底层-OverlayFS
运维·docker·容器
goodlook01232 小时前
监控平台搭建-监控指标展示-Grafana篇(五)
java·算法·docker·grafana·prometheus
java_logo2 小时前
Apache Flink Docker 容器化部署指南
docker·flink·apache·apache flink·apache flink部署·flink部署文档·flink部署教程
深耕AI2 小时前
【Docker Desktop for Windows】 两个 volumes 目录的区别
windows·docker·容器
深耕AI2 小时前
【手搓 Docker 卷 volumes】从 `docker volume create` 到落盘位置的最后1公里
运维·docker·容器
鸠摩智首席音效师2 小时前
如何在 Linux 中使用 fallocate 命令 ?
linux·运维·服务器
雨大王5122 小时前
如何选择汽车制造数字化服务商?关键指标与实战案例解析
大数据·运维·人工智能
QT 小鲜肉2 小时前
【Linux命令大全】001.文件管理之split命令(实操篇)
linux·运维·服务器·网络·笔记