我们知道docker利用linux内核特性namespace实现了网络的隔离,让每个容器都处于自己的小世界里面,当这个小世界需要与外界(宿主机或其他容器)通信的时候docker的网络就发挥作用了,这篇小作文我们一起来学习一下docker容器网络基础,这里我们会着重学习bridge模式的工作原理。


docker提供了三个开箱即用的网络模式(驱动)bridgehost none

我们通过ls看一下相关信息:

[root@bogon /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f33b32dd8351 bridge bridge local
2c102587be2f host host local
04a61e996030 none null local

一、host与none模式

在host模式下,容器共享主机的网络命名空间,直接将其暴露给外界。同时主机名与宿主机一致。

[root@bogon proc]# docker run -it --name busybox_host --net host busybox
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
link/ether 00:0c:29:45:89:e6 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.123/24 brd 192.168.1.255 scope global noprefixroute ens192
valid_lft forever preferred_lft forever
inet6 fe80::806e:979a:d38f:a85b/64 scope link noprefixroute
valid_lft forever preferred_lft forever / # hostname
localhost

host模式主要用于对网络性能要求高、追求传输效率的服务,但是需要注意的是会占用主机的端口,多个容器工作可能需要处理冲突。

none模式下,不配置网络,并且无法访问外部网络以及其他容器,对于不需要网络访问的容器很有用,比如批处理应用,密码管理等等。

[root@bogon proc]# docker run -it --name busybox_none --net none busybox
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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

二、bridge模式及其工作原理

1.默认和自定义bridge网络

bridge是docker默认网络模式,docker安装后会选择一个私有网段作为bridge的子网,从下面config中可以看到我们的16位掩码的子网是172.17.0.0/16,这样在我们创建容器时默认会将容器网络加入到这个子网中。

[root@bogon proc]# docker inspect bridge
[
{
"Name": "bridge",
"Id": "f33b32dd835100abc5c94855d3676b082ef6f0ebea10847425fbe6187d263823",
"Created": "2021-08-09T21:41:49.031849089-04: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": {}
}
]

上面Containers字段中并为包含容器,现在我们创建一个busybox工具箱容器,通过inspect分别查看bridge容器信息,显然172.17.0.1在子网172.17.0.0/16下。

[root@bogon proc]# docker run -d -t --name busybox busybox
[root@bogon proc]# docker inspect bridge
... "Containers": {
"b6f1e0103c1b44f76cd31fb75a3d9537f3292e5390e4441db2376e7e13d31ed2": {
"Name": "busybox",
"EndpointID": "caac0bd4feedd0ac483fa44155c46e6c07d72e1d6281ca43599d5e72018f8066",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
... [root@bogon proc]# docker inspect b6f
...
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "f33b32dd835100abc5c94855d3676b082ef6f0ebea10847425fbe6187d263823",
"EndpointID": "caac0bd4feedd0ac483fa44155c46e6c07d72e1d6281ca43599d5e72018f8066",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
...

从上面我们可以看到使用默认bridge模式非常简单,当然在生产中我们一般会手动创建一个bridge,然后将容器加入到这个网络,以防不必要的容器被加入到生产子网中。

[root@bogon proc]# docker network create --driver bridge --subnet 172.0.0.0/24 --gateway 172.0.0.1 newbridge
1b1bc5ffe581472c098418ddaafc38fbdc101ef55d840d4be55b882242bca552
[root@bogon proc]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f33b32dd8351 bridge bridge local
2c102587be2f host host local
1b1bc5ffe581 newbridge bridge local
04a61e996030 none null local

--dirver、--subnet、--gateway分别指定我们的驱动、子网和网关

我们已经创建好了一个新的bridge网络,这样我们在创建容器的时候使用--net参数就可以加入到这个网络。

[root@bogon proc]# docker run -d -t --net newbridge --name busybox_newbridge busybox

以上我们大概了解了创建一个bridge网络和使用,但是我们不了解其工作原理,这不太棒。

2.bridge网络工作原理

我们从下面这张图展开bridge网络工作原理

我们安装Docker后守护进程将创建一个linux虚拟以太网桥docker0,它会在连接到其上的所有接口之间转发数据包,默认情况下主机上的所有容器都连接到这个内部桥接器,它会将一个接口(虚拟设备对veth pair)作为容器的eth0接口和主机命名空间中的另一个接口。这样容器就获得了私有 IP 地址分配。同时为了防止本地网络上的 ARP 冲突,Docker 守护进程从分配的 IP 地址上生成一个随机 MAC 地址。这样一来容器就和网桥连接起来了,然后通过iptables NAT规则和主机上eth0网卡交换数据。

veth pair我们可以理解为一条虚拟网络电缆,其两端都有一个虚拟网络接口设备。

接下来我们从实际中来看一看。使用brctl show来查看linux网桥和接口。

[root@bogon proc]# brctl show
bridge name bridge id STP enabled interfaces
br-1b1bc5ffe581 8000.024297a8cc80 no vethe19101d
docker0 8000.02426da67767 no veth53e494e

可以看到我们默认的docker0和手动创建的newbridge对应的br-1b这两个网桥上分别接了vethe19101d和veth53e494e,为了方便下面咋们只关注docker0网桥。

同样我们也可以通过ip addr来查看接口信息,veth53e494e所属的网桥正是docker0

我们进入busybox容器看看,同样的存在接口eth0@if19

/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever

如此一来我们的虚拟设备对veth pair就成了,网桥与容器的通信水到渠成。最后容器怎么通过网桥与外界通信呢?

我们来查看iptables nat规则:

[root@bogon proc]# iptables -t nat -vnL
...
Chain POSTROUTING (policy ACCEPT 184 packets, 14201 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE all -- * !br-1b1bc5ffe581 172.0.0.0/24 0.0.0.0/0
...

POSTROUTING链会将所有来自172.17.0.0/16、172.0.0.0/24的流量伪装为宿主机网卡发出。即容器的流量通过NAT后服务端并没有感知,只知道是源自宿主机网卡的流量,相当于SNAT。

我们在看看DNAT,这里我们启动一个端口映射容器

[root@bogon proc]# docker run -d -p 8888:80 httpd

此时通过tcp/8888端口的流量已经被转发到了172.17.0.3:80,这也是为什么在使用docker是需要开启net.ipv4.ip_forward转发。

Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- br-1b1bc5ffe581 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8888 to:172.17.0.3:80

bridge网络模式大致到这里。容器的实现有太多linux细节,博大精深,关于网络部分水更深,本文只是冰山一角,有兴趣的同志可以通过搜索引擎遨游知识海洋。欢迎关注查看后面关于容器网络驱动Overlay、macvlan的小作文。


我是顶级饮水机管理员,博客iqsing.github.io

您可以随意转载、修改、发布本文章,无需经过本人同意。

NEXT

  • docker容器网络Overlay
  • docker容器网络macvlan

docker容器网络bridge的更多相关文章

  1. Docker容器网络篇

    Docker容器网络篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Docker的网络模型概述 如上图所示,Docker有四种网络模型: 封闭式网络(Closed conta ...

  2. 【转】理解Docker容器网络之Linux Network Namespace

    原文:理解Docker容器网络之Linux Network Namespace 由于2016年年中调换工作的原因,对容器网络的研究中断过一段时间.随着当前项目对Kubernetes应用的深入,我感觉之 ...

  3. Docker容器网络-基础篇

    开源Linux 一个执着于技术的公众号 Docker的技术依赖于Linux内核的虚拟化技术的发展,Docker使用到的网络技术有Network Namespace.Veth设备对.Iptables/N ...

  4. Docker容器网络配置

    Docker容器网络配置 1.Linux内核实现名称空间的创建 1.1 ip netns命令 可以借助ip netns命令来完成对 Network Namespace 的各种操作.ip netns命令 ...

  5. 两台主机间docker容器网络互通

    服务器1: 网络172.30.0.0/16 服务器2: 网络172.31.0.0/16 服务器1和服务器2上的docker容器网络之间是无法互通的,如果需要互通,需要做以下配置: 服务器1上执行: i ...

  6. docker容器网络

    1.我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式: · host模式,使用--net=host指定 · containe ...

  7. docker 容器网络基础

    ======================== docker缺省自带的网络 ======================== host 网络, This enables a container to ...

  8. 5、Docker容器网络

    使用Linux进行IP层网络管理的指     http://linux-ip.net/html/ # yum install iproute http://linux-ip.net/html/tool ...

  9. 12、Docker的网络--bridge

    单机网络 Bridge Network Host Network None Network 多机网络 Overlay Network 12.1 网络命名空间   启动一个容器 docker run - ...

随机推荐

  1. 【spring源码系列】之【Bean的生命周期】

    为源码付出的每一分努力都不会白费. 1. Bean的实例化概述 前一篇分析了BeanDefinition的封装过程,最终将beanName与BeanDefinition以一对一映射关系放到beanDe ...

  2. VLAN的基础介绍与使用方法

    一.VLAN概述与优势 二.VLAN的种类 三.VLAN的范围 四.VLAN的三种接口模式 五.VLAN的实例操作 一.VLAN概述与优势 VLAN(虚拟局域网)通过为子网提供数据链路连接来抽象出局域 ...

  3. 我是怎么写 Git Commit message 的?

    目录 作用 用的什么规范? type scope subject body footer 参考文章 用的什么辅助工具? 作用 编写格式化的 commit message 能够大大提高代码的维护效率. ...

  4. 徒手从零实现 uTools 系列(三)- 屏幕取色和截屏

    前言 为了进一步提高开发工作效率,最近我们基于 electron 开发了一款媲美 uTools 的开源工具箱 rubick.该工具箱不仅仅开源,最重要的是可以使用 uTools 生态内所有开源插件!这 ...

  5. 暑假自学java第六天

    1,方法的覆盖:当子类继承父类,而子类中的方法与父类中方法的名称,返回类型及参数都完全一致时,就称子类中的方法覆盖了父类中的方法,有时也称方法的"重写" [不需要关键字] 2,th ...

  6. 0、springboot

    在线新建springboot项目 https://start.spring.io/ 参考地址 https://github.com/battcn/spring-boot2-learning 博客 ht ...

  7. springCloud--admin监控使用

    Admin监控应用 Spring Boot提供的监控接口,例如:/health./info等等,实际上除了之前提到的信息,还有其他信息业需要监控:当前处于活跃状态的会话数量.当前应用的并发数.延迟以及 ...

  8. charles证书导入系统信任区(Android7.0以上)

    打开charles,跟着下图来,下载好charles的证书 后缀是pem的格式,挺方便的了,burp的证书是der的,还需要再进一步转化成pem,这里就不再多说, 利用openssl来计算出文件名 加 ...

  9. edraw max for mac 安装

    1.下载网址:https://xclient.info/s/edraw-max.html#versions 2.安装断网安装,直接打开 .dmg文件安装 3.按照阅读文件中的第二步,将opt.cell ...

  10. sscanf功能详解(转)

    #include <stdio.h> #include <stdlib.h> #include <string.h> static void sscanf_test ...