概述

我们可以将服务发布到Docker中,然后发布Docker到各个环境,比如开发、测试、生产环境,不再需要像以前那么麻烦,需要一个个的环境进行配置,经常会为了环境之间的差异,花费大量的时间去排查问题,所以使用 Docker提高了我们的研发交付的效率。但是在使用Docker的时候,我们可能会碰到一个场景,那就是服务A需要访问服务B,如果这两个服务都是部署在Docker中,问题就变为我们就需要能够让这两个docker容器进行通信,为了要让这两个Docker容器进行通信,我们就需要将这两个docker都加入到同一个网络中,这个网络可以是虚拟的网络,也可以是实际的物理网络,具体如何操作详情见下文。

利用物理网络进行通信的介绍

如果要通过实际的物理网络进行通信,那么我在启动docker的时候,会有如下的写法:

docker run -d --name serviceA -p 80:8080 serviceA

这就将serviceA在docker内服务的8080端口映射到宿主机器的80端口上,这样服务A和服务B之间就可以通过宿主机的网络进行通信,服务B以如下的方式启动:

docker run -d --name serviceB -p 81:8080 serviceB

那么我们在服务A中需要访问服务B,就可以利用服务B在物理机器的IP和端口进行通信。

利用虚拟网络的方式进行通信

除了物理网络通信的方式外,Docker还提供了一个种通过虚拟网络进行通信的方式,首先我们通过如下的命令,创建一个虚拟的docker网络,

docker create network demo

然后再通过如下的命令,检查一下demo这个网络的定义信息:

[sshuser@SY-SUZ-SRV73 ~]$ docker network inspect demo

    {
        "Name": "demo",
        "Id": "017b50fa475dafa62ca0cfe4675cc38201be16d19da52f308226952f1c57b5bb",
        "Created": "2019-05-22T11:57:02.010906134+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.21.0.0/16",
                    "Gateway": "172.21.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
        },
        "Options": {},
        "Labels": {}
    }
]

可以观察到containers节点都为空,下面我们将要把serviceA和serviceB都加入的上面创建的demo网络中 。

docker run -d --name serviceA --net=ci -p 80:8080 serviceA
docker run -d --nam serviceB --net=ci -p 8081:8081 serviceB

上面的命令中的–net用来指定前面创建的虚拟网络的唯一ID。这样我们就可以在serviceA或者serviceB中互相以服务名字来访问对方。

总结

以物理网络的方式访问,服务双方通信会经过物理网卡,而通过虚拟网络的方式通信,不会经过物理网卡,所有的通信数据都在在操作系统的内存中进行交互,所以虚拟网络的通信效率肯定会比物理网络的效率高很多。而且在服务依赖的时候,我们以服务名作为依赖,比用物理的IP地址和端口的依赖形式的可读性高。