共计 3274 个字符,预计需要花费 9 分钟才能阅读完成。
一. 为什么要理解 docker 网络
当你开始大规模应用 Docker 时,你会发现须要理解很多对于网络的常识。Docker 作为目前最火的轻量级容器技术,有很多令人称道的性能,如 Docker 的镜像治理。然而,Docker 同样有着很多不欠缺的中央,网络方面就是 Docker 比拟单薄的局部。因而,咱们有必要深刻理解 Docker 的网络常识,以满足更高的网络需要。本文首先介绍了 Docker 本身的 4 种网络工作形式,而后介绍一些自定义网络模式。
二.docker 网络理论
Docker 应用 Linux 桥接(参考《Linux 虚构网络技术》),在宿主机虚构一个 Docker 容器网桥 (docker0),Docker 启动一个容器时会依据 Docker 网桥的网段调配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就可能通过容器的 Container-IP 间接通信。
Docker 网桥是宿主机虚构进去的,并不是实在存在的网络设备,内部网络是无奈寻址到的,这也意味着内部网络无奈通过间接 Container-IP 拜访到容器。如果容器心愿内部拜访可能拜访到,能够通过映射容器端口到宿主主机(端口映射),即 docker run 创立容器时候通过 -p 或 -P 参数来启用,拜访容器的时候就通过 [宿主机 IP]:[容器端口] 拜访容器。
当你装置 Docker 时,它会主动创立三个网络。你能够应用以下 docker network ls 命令列出这些网络:
# docker network ls
NETWORK ID NAME DRIVER SCOPE
857db65319fa bridge bridge local
c16cf8722909 host host local
d39a88b56801 none null local
三.docker 的四类网络模式
网络模式 | 配置 | 阐明 |
---|---|---|
bridge 模式 | –net=bridge | (默认为该模式)此模式会为每一个容器调配、设置 IP 等,并将容器连贯到一个 docker0 虚构网桥,通过 docker0 网桥以及 Iptables nat 表配置与宿主机通信。 |
host 模式 | –net=host | 容器和宿主机共享 Network namespace。 |
container 模式 | –net=container:NAME_or_ID | 容器和另外一个容器共享 Network namespace。kubernetes 中的 pod 就是多个容器共享一个 Network namespace。 |
none 模式 | –net=none | 该模式敞开了容器的网络性能。 |
3.1 bridge 模式
当 Docker 过程启动时,会在主机上创立一个名为 docker0 的虚构网桥,此主机上启动的 Docker 容器会连贯到这个虚构网桥上。虚构网桥的工作形式和物理交换机相似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从 docker0 子网中调配一个 IP 给容器应用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创立一对虚构网卡 veth pair 设施,Docker 将 veth pair 设施的一端放在新创建的容器中,并命名为 eth0(容器的网卡),另一端放在主机中,以 vethxxx 这样相似的名字命名,并将这个网络设备退出到 docker0 网桥中。能够通过 brctl show 命令查看。
bridge 模式是 docker 的默认网络模式,不写 –net 参数,就是 bridge 模式。应用 docker run - p 时,docker 理论是在 iptables 做了 DNAT 规定,实现端口转发性能。能够应用 iptables -t nat -vnL 查看。
bridge 模式如下图所示:
3.2 host 模式
如果启动容器的时候应用 host 模式,那么这个容器将不会取得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚构出本人的网卡,配置本人的 IP 等,而是应用宿主机的 IP 和端口。然而,容器的其余方面,如文件系统、过程列表等还是和宿主机隔离的。
应用 host 模式的容器能够间接应用宿主机的 IP 地址与外界通信,容器外部的服务端口也能够应用宿主机的端口,不须要进行 NAT,host 最大的劣势就是网络性能比拟好,然而 docker host 上曾经应用的端口就不能再用了,网络的隔离性不好。
Host 模式如下图所示:
3.3 container 模式
这个模式指定新创建的容器和曾经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创立本人的网卡,配置本人的 IP,而是和一个指定的容器共享 IP、端口范畴等。同样,两个容器除了网络方面,其余的如文件系统、过程列表等还是隔离的。两个容器的过程能够通过 lo 网卡设施通信。
Container 模式示意图:
3.4 none 模式
应用 none 模式,Docker 容器领有本人的 Network Namespace,然而,并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。须要咱们本人为 Docker 容器增加网卡、配置 IP 等。
这种网络模式下容器只有 lo 回环网络,没有其余网卡。none 模式能够在容器创立时通过 –network=none 来指定。这种类型的网络没有方法联网,关闭的网络能很好的保障容器的安全性。
None 模式示意图:
四.bridge 模式下容器的通信
4.1 防火墙开启状态
在 bridge 模式下,连在同一网桥上的容器能够互相通信(若出于平安思考,也能够禁止它们之间通信,办法是在 DOCKER_OPTS 变量中设置–icc=false,这样只有应用–link 能力使两个容器通信)。
容器也能够与内部通信,咱们看一下主机上的 Iptable 规定,能够看到这么一条
这条规定会将源地址为 172.17.0.0/16 的包(也就是从 Docker 容器产生的包),并且不是从 docker0 网卡收回的,进行源地址转换,转换成主机网卡的地址。这么说可能不太好了解,举一个例子阐明一下。假如主机有一块网卡为 eth0,IP 地址为 192.168.21.10/24,网关为 192.168.21.255。从主机上一个 IP 为 172.17.0.1/16 的容器中 ping 百度(www.baidu.com)。IP 包首先从容器发往本人的默认网关 docker0,包达到 docker0 后,也就达到了主机上。而后会查问主机的路由表,发现包应该从主机的 eth0 发往主机的网关 192.168.21.255/24。接着包会转发给 eth0,并从 eth0 收回去(主机的 ip_forward 转发应该曾经关上)。这时候,下面的 Iptable 规定就会起作用,对包做 SNAT 转换,将源地址换为 eth0 的地址。这样,在外界看来,这个包就是从 192.168.21.10 上收回来的,Docker 容器对外是不可见的。
那么,里面的机器是如何拜访 Docker 容器的服务呢?咱们首先用上面命令创立一个含有 web 利用的容器,将容器的 80 端口映射到主机的 80 端口。
docker run -itd --name=nginx_bridge --net=bridge -p 80:80 nginx
而后查看 Iptable 规定的变动,发现多了这样一条规定:
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
此条规定就是对主机 eth0 收到的目标端口为 80 的 tcp 流量进行 DNAT 转换,将流量发往 172.17.0.2:80,也就是咱们下面创立的 Docker 容器。所以,外界只需拜访 192.168.21.10:80 就能够拜访到容器中的服务。
4.2 防火墙敞开状态
如果 docker 网络应用了 bridge 模式,也不须要防火墙,那间接关掉 FirewallD 服务就能够了。能够解决诸多因为防火墙网络问题导致的 docker 容器端口不通的问题。
- docker 网络官网文档:https://docs.docker.com/engin…