自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求。而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信。因此,这里我们帮助一些只知其意不知其理小伙伴,对容器的通信原理进行简单的分析,帮助大家更好地使用docker。

1.1 Docker默认网络管理

        在进行Docker安装时,Docker就会自动创建三种网络。客户端可以通过网络管理指令进行查看,具体操作指令如下。

$ docker network ls

上述指令用于列举Docker中的所有网络,执行后的效果如图所示。

docker network 容器互通 docker容器之间的通信_网络管理

        Docker中默认的三种网络分别为bridge、host和none,其中名为bridge的网络就是默认的bridge驱动网络,也是容器创建时默认的网络管理方式,配置后可以与宿主机通信从而实现与互联网通信功能,而host和none属于无网络,容器添加到这两个网络时不能与外界网络通信。

        下面通过一个示例来演示默认的bridge网络管理方式,其执行过程如下。

(1)创建并启动容器。在终端窗口中执行如下指令。

$ docker run -itd --name=networktest ubuntu

        上述指令在后台启动了一个镜像名称为ubuntu的容器,并为启动后的容器命名为networktest。

(2)使用网络查看指令查看网络详情,具体操作指令如下。

$ docker network inspect bridge

        上述指令用于核查名称为bridge的网络详情,需要指明网络名称或者网络ID,执行上述指令后,如图所示。

docker network 容器互通 docker容器之间的通信_docker 容器之间通信_02

        执行上述指令后就会显示出bridge网络的所有详细信息,其中就包括了使用默认的bridge网络管理方式启动的名称为networktest的容器。

        需要注意的是,这里介绍的三种网络bridge、host和none都是在非集群环境下Docker提供的默认网络,而在Docker Swarm集群环境下,除了这三种默认网络外,Docker还提供了docker_gwbridge和ingress两种默认网络。

1.2 自定义网络介绍

        虽然Docker提供的默认网络的使用比较简单,但是为了保证各容器中应用的安全性,在实际开发中更推荐使用自定义的网络进行容器管理。

        在Docker中,可以自定义bridge网络、overlay网络,也可以创建network plugin(网络插件)或者远程网络以实现容器网络的完全定制和控制。接下来将分别针对这几种自定义网络进行讲解。

1. Bridge networks(桥接网络)

        为了保证容器的安全性,我们可以使用基于bridge的驱动创建新的bridge网络,这种基于bridge驱动的自定义网络可以较好的实现容器隔离。

需要说明的是,这种用户自定义的基于bridge驱动的网络对于单主机的小型网络环境管理是一个不错的选择,但是对于大型的网络环境管理(如集群)就需要考虑使用自定义overlay集群网络。

2. Overlay network in swarm mode(Swarm集群中的覆盖网络)

在Docker Swarm集群环境下可以创建基于overlay驱动的自定义网络。为了保证安全性,Swarm集群使自定义的overlay网络只适用于需要服务的群集中的节点,而不会对外部其他服务或者Docker主机开放。

3. Custom network plugins(定制网络插件)

如果前面几种自定义网络都无法满足需求时,就可以使用Docker提供的插件来自定义网络驱动插件。自定义网络插件会在Docker进程所在主机上作为另一个运行的进程。

        自定义网络驱动插件与其他插件遵循相同的限制和安装规则,所有插件都使用Docker提供的插件API,并且有一个包含安装、启动、停止和激活的生命周期。由于自定义网络插件使用较少,所以读者只需了解即可。

1.3 自定义bridge驱动网络

1. 创建自定义网络

在Docker主机上可以使用docker network create指令来创建网络,具体操作指令如下。

$ docker network create --driver bridge isolated_nw

        执行上述指令可以创建一个基于bridge驱动的名称为isolated_nw的网络。其中--driver(可简写为-d)用于指定网络驱动类型,isolated_nw就是新创建的网络名称。需要说明的是,--driver bridge可以省略,省略时Docker会默认使用基于bridge驱动来创建新的网络。

创建完网络后,可以使用docker network ls指令查看创建的网络是否成功,效果如图所示。

docker network 容器互通 docker容器之间的通信_网络管理_03

        除docker network ls指令外,还可以使用docker network inspect指令查看新建网络的详细信息。

2. 使用自定义网络启动容器

        自定义网络创建成功后,就可以使用该网络启动一个容器,具体指令如下。

$ docker run --network=isolated_nw -itd --name=nwtest busybox

        执行上述指令后,会创建一个名为nwtest的容器,指令中的--network参数指定了该容器的网络连接为自定义的isolated_nw。

        通过docker inspect nwtest指令可以查看启动后的容器详情,来核查其网络管理方式,效果如图所示。

docker network 容器互通 docker容器之间的通信_网络管理_04

        从图可以看出,名为nwtest的容器使用的就是自定义的isolated_nw网络进行容器网络管理的。

3. 为容器添加网络管理

        名为nwtest的容器使用的只有自定义的isolated_nw一种网络管理方式,我们还可以继续为该容器添加其他网络管理方式,具体操作指令如下。

$ docker network connect bridge nwtest

        执行上述指令后,会为容器nwtest另添加一种默认的bridge网络管理方式。再次使用docker inspect nwtest指令查看该容器网络详情,效果如图所示。

docker network 容器互通 docker容器之间的通信_自定义_05

4. 断开容器网络连接

容器既可以连接网络,也可以断开网络。这里以断开nwtest容器的自定义网络isolated_nw为例进行演示,断开网络连接的指令如下。

$ docker network disconnect isolated_nw nwtest

        断开网络连接的指令与连接网络的指令类似,在使用时也需要指定网络名称和容器名称。

5. 移除自定义网络

当不再需要某个网络时,可以将该网络移除,但在移除网络之前,一定要先将所有与该网络连接的容器断开。移除自定义网络的指令如下。

$ docker network rm isolated_nw

1.4 容器间通信

        Docker中的不同容器之间需要通过网络来进行通信,那么各个容器之间具体是如何实现通信的呢?接下来,本小节将以非集群环境下的容器通信为例,对Docker容器之间的通信进行讲解。

以下图进行说明,container1使用的是默认的bridge网络管理,container3使用的是自定义的isolated_nw网络管理,而container2使用的是默认的bridge网络管理和自定义的isolated_nw网络管理。这3个容器具体的网络管理关系,可以通过图进行说明。

docker network 容器互通 docker容器之间的通信_自定义_06

        从图可以看出,container1和container2在同一个默认的bridge网络管理下,这两个容器可以相互通信;而container2又和container3在同一个自定义的isolated_nw网络管理下,这两个容器也可以相互通信;但是container1和container3属于不同的网络环境,所以这两个容器无法进行通信。

        总结:不同容器之间想要相互通信必须在同一个网络环境下;使用默认bridge网络管理的容器可以使用容器IP进行通信,但无法使用容器名称进行通信;而使用自定义网络管理的容器则同时可以使用容器IP和容器名称进行通信。

    开发中,强烈建议使用已定义网络管理容器,然后容器直接使用容器名称进行通讯。