目录
1、前言
2、基本原理
3、Docker网络配置
3.1、查看网络配置
3.2、4种网络模式
3.3、bridge模式
3.3.1、使用bridge网络
3.3.2、自定义bridge网络
3.4、host模式
3.5、container模式
3.6、none模式
4、小结
1、前言
前面我们介绍了Docker容器的相关内容,Docker 的容器运行在宿主机的虚拟机上。这些虚拟机彼此独立,彼此之间没有任何接口,即容器彼此之间是逻辑隔离的。那么,如何实现容器的相互通信?这个就是我们今天要讲的内容。
2、基本原理
Docker 容器中的网络接口默认都是虚拟接口。虚拟接口的最大优势是转发效率极高。这是因为,Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,即发送接口缓存中的数据包会被直接复制到接收接口的缓存中,而无须通过外部的物理网络设备进行交换。
Docker 的网络很好地利用了 Linux 虚拟网络技术,在宿主机的物理网卡和容器内分别创建-个虚拟接口(veth),并让它们通过宿主机的 docker0 网桥进行连接,我们把这样的一对 veth 叫作 veth pair。
3、Docker网络配置
3.1、查看网络配置
我们可以通过以下命令查看Docker的网络配置信息。
docker network
通过以下命令可以查看Docker的几种网络通信模式。
docker network ls
可以看到有3中模式:bridge,host,none。而默认情况下为bridge。
我们随便启一个docker容器,容器名称为myapp,且不指定任何网络模式:
docker run -d -p 18080:8899 myapp
启动成功后,我们查看网络Bridge的详情:
docker network inspect bridge
可以看到Container里面包含了我们的myapp容器,这说明我们刚启动的myapp容器默认使用的就是bridge网络模式。
而默认的子网地址是“172.17.0.0/16”。容器IP为172.17.0.2,是属于bridge网络的子网络。
3.2、4种网络模式
Docker一共提供了4种网络通信模式: bridge、container、host 和 none。通过上述的docker network ls看到的bridge,host,none以外,还有container模式。
模式 | 是否支持多主机 | 纵向通信机制 | 横向通信机制 |
bridge | 否 | 绑定宿主机端口 | 通过 Linux 桥接进行通信 |
container | 否 | 绑定宿主机端口 | 通过 Linux 连接进行通信 |
host | 是 | 通过宿主机网络进行通信 | 通过宿主机网络进行通信 |
none | 否 | 无法通信 | 只能通过 Linux 连接进行通信 |
由于 Docker 容器彼此之间是逻隔离的,所以,在安装 Docker 时会在容器中创建隔离的网络环境。在隔离的网络模式环境中,运行在宿主机上的各个容器具有完全独立的网络栈,并且Docker 容器的网络环境与宿主机相互隔离。通过使用 Docker 的不同网络模式,可以使 Docker容器共享宿主机的网络命名空间,也可以实现 Docker 容器间的相互访问。
3.3、bridge模式
前面提到了bridge模式是 Docker 默认的网络通信模式,也是开发者最常用的模式。在 bridge 模式下,Docker引擎会创建独立的网络命名空间。这样就可以保证运行在每一个命名空间中的容器具有独立的网卡等网络资源。
利用 bridge 模式,可以非常方便地实现容器与容器之间、容器与宿主机之间的网络隔离。通过使用宿主机上的 docker0 网桥,可以实现 Docker 容器与宿主机(乃至外部网络)的网络通信。
简单实验一下:
3.3.1、使用bridge网络
创建一个busybox镜像的容器。
BusyBox 是一个集成了三百多个最常用Linux命令和工具的软件。BusyBox 包含了一些简单的工具,例如ls、cat和echo等等,还包含了一些更大、更复杂的工具,例grep、find、mount以及telnet。
docker run -it busybox /bin/sh
使用ifconfig查看网络信息:
可以看到容器的内网ip为172.17.0.3。
3.3.2、自定义bridge网络
默认情况下,docker引擎会自动创建一个bridge网络。但是通常生产环境种,我们都会自定义一个bridge网络,当然docker也是支持我们自定义的。
1)创建一个自定义的bridge网络。
创建一个名为mybridge的网络模式,网关ip为172.19.0.1,子网IP范围是172.19.0.0/24。
docker network create -d bridge --ip-range=172.19.0.0/24 --gateway=172.19.0.1 --subnet=172.19.0.0/24 mybridge
- -d:指定网络通信模式,默认是bridge。
- --ip-range:子网IP地址范围。
- --gateway:网关的IP地址。
- --subnet:子网的IP地址。
- mybridge:自定义bridge网络名称
2)查看Docker网络。
docker network ls
可以看到多了一个mybridge的网络通信模式。
3)使用mybridge创建容器。
docker run -it --network=mybridge --ip=172.19.0.33 busybox
- --ip:指定容器的IP地址。
- --network:使用的网络通信模式,这里指定刚创建的mybridge。
4)查看容器IP。
5)删除自定义网络。
docker network rm mybridge
3.4、host模式
host模式,容器与宿主机共享同一个网络命名空间,容器的IP 地址与宿主机的IP地址相同。如果宿主机具有公网的IP 地址,则容器也拥有这个公网的IP地址。即这时容器可以直使用宿主机的IP地址与外界进行通信,且容器内服务的端口也可以直接使用宿主机的端口,无须行任何的转换。
由于在 host 模式下不再需要宿主机的转发,因此其性能得到了极大的提高。
1)使用host模式创建容器。
docker run -it --net=host busybox /bin/sh
2)使用ifconfig看下网络信息。
容器内:
宿主机:
我们可以看到容器和宿主机的网络配置一摸一样,这就表示容器与宿主机共享了同一个网络命名空间。
如果使用host模式,我们在创建容器的时候就不需要-p 映射端口了,如果有映射端口,创建的时候会有警告提示。因为这个时候的IP和端口都是与宿主机共享的。
使用host模式的时候存在以下两个问题:
- 由于容器使用了宿主机的网络环境,因此网络环境的隔离性功能被减弱,从而造成宿主机和容器争用网络资源。容器本身也不再拥有所有的网络资源,而是与宿主机共享网络资源。
- 宿主机和容器使用了相同的 IP 地址,这不利于网络的配置和管理。
3.5、container模式
在 container 模式下,容器之间会共享网络环境。即一个容器会使用另一个容器的网络命名空间。因此,在这种模式下,容器之间可以通过 localhost 或者 127.0.0.1 进行相互间的访问,从而提高了传输的效率。
container 模式节约了网络资源,但是运行在这种模式下的容器不存在网络隔离。Container 网络的隔离性处于 bridge 网络与 host 网络之间。
container 模式在一些特殊场景中非常有用。例如:在 Kubernetes 中创建 Pod 时,会首先创建 Pod的基础容器;而 Pod 中的其他容器则采用 container 模式与基础容器进行通信。Pod中的各个容器采用localhost 或者 127.0.0. 进行通信,从而将 Pod 中的所有容器形成一个逻辑整体。
1)创建一个容器A,使用默认网络模式。
docker run -it busybox /bin/sh
查看网络信息:
2)创建一个容器B,使用container模式,并指向刚创建的容器A。
查看容器A的containerId为:0783212a7f4c。
开启容器B。
docker run -it --net=container:0783212a7f4c busybox /bin/sh
查看ifconfig:
可以看到容器A和B的IP信息相同,表示容器A和容器B使用了相同的网络命名空间。
因为容器B创建的时候,使用了container模式,这样容器B就不用创建自己的网络命名空间,而直接使用容器A的。
3.6、none模式
none模式下容器具有独立的网络命名空间,但不包含任何的网络配置,只能通过localhost或127.0.0.1访问容器。
docker run -it --net=none busybox /bin/sh
一般来说none模式用于一些对安全性要求高但是不需要联网的情况下。让自己的网络处于一个封闭的空间,可以排除外界其他网络的干扰。
4、小结
一般来讲,生产中用到最多的还是bridge模式,container和host模式也有自己相应的使用场景,可以根据实际情况选择。了解几种不同的网络通信模式,可以帮助我们更容易学习后续关于不同容器或者容器和宿主机间通信。一起学习吧~