我们在使用docker run创建Docker容器时,可以用–net选项指定容器的网络模式;Docker网络有四种模式:

  • 桥模式:–net=bridge
  • 主机模式:–net=host
  • 容器模式:–net=container_name|id
  • 无网络模式:–net=none

Docker 网络实现

相关知识

Docker网络实现基础:

基本原理

设备要实现网络通信,至少需要一个网络接口(物理接口 or 虚拟接口)来收发数据包;如果是不同子网间通信则需要路由机制。

Docker默认采用虚拟网络接口:在本地主机和容器中分别创建一个虚拟接口(veth),使主机和容器彼此联通(该接口对为:veth pair)

容器网络模型

容器网络模型由三部分组成:

  • Sandbox: 保存容器的网络配置,一个Sandbox内可保存多个Endpoint
  • Endpoint: 可以通过Network可以和其他的Endpoint进行通信,每个Endpoint都只在一个网络内
  • Network: 由多个可相互通信的Endpoint组成,不同的网络间相互隔离

基于这个网络模型,同一个网络内的所有容器都可以互相访问;如果需要隔离,创建新的网络即可。

Docker的覆盖网络是怎么工作的

创建网络参数

docker run --net 可指定Docker启用的 网络模式

Docker创建容器时网络模块配置:

  1. 创建一对虚拟接口,分别连接到本地主机和容器
  2. 本地主机接口桥接到docker0(默认)或指定的网桥,并分配一个唯一的名字(如:veth17a2548)
  3. 容器端接口连接到新容器,并重命名为eth0, eth0接口只在容器的命名空间可见
  4. 从网桥(step-2指定)可用地址段查找空闲ip分配给eth0, 并配置默认路由到桥接网卡veth17a2548

Docker 网络模式

bridge网络模式

bridge模式是Docker的默认网络设置

  • 该模式下,Docker守护进程会创建一个虚拟以太网桥docker0,任何附加在网桥docker0上的网卡间都能自动转发数据包。默认情况下,Docker守护进程会创建一对对等接口,将其中一个接口设置为容器的eth0接口,另一个接口放置在宿主机的命名空间中,从而将宿主机上的所有容器都连接到这个内部网络。同时,守护进程还会从网桥的私有地址空间中分配一个ip地址和子网给该容器。

  • birdge网络模式图:

birdge网络模式

注:由于bridge是默认模式,可省略–net,直接启动

host网络模式

host模式会禁用Docker容器的网络隔离。

该模式下容器共享宿主机的网络命名空间,直接会暴露在公共网络中,因此要通过端口映射(port mapping)来进行协调。

  • host网络模式图:

host网络模式

注:当时用host网络模式时,容器实际上继承了宿主机的ip地址。该模式比bridge更快,因为没有路由开销,但他将容器直接暴露在公网中,存有安全隐患。

container网络模式

container模式会重用另一个容器的网络命名空间。

该模式指定新创建的容器和已经存在的某个容器共享同一个network namespace,而不是和宿主机共享。新建的容器不会创建自己的网卡,配置自己的ip,而是和指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他比如文件系统、进程列表等还是隔离的。

  • container网络模式图:

container网络模式

  • 实例
1
2
docker run --it --name centos_netshare centos_net bash ifconfig
docker run --it --name centos_netshare_host1 --net=container:centos_netshare centos_net bash ifconfig

注:

  • 两个容器进程可以通过lo网卡设备通信
  • 由于两个容器共享一个network namespace, 因此需要注意端口冲突情况,否则第二个容器将无法被启动

none网络模式

none模式将容器放置在自己的网络栈中,但是不进行任何配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,需要我们自己添加网卡、配置IP。

该模式会关闭容器的网络功能,适用于一下两种情况:

  1. 容器不需要网络(例如只需要写磁盘卷的批处理任务)
  2. 自定义网络

See Also

Thanks to the authors 🙂