现实生活中我们的web程序总是需要去访问redis、nginx、db等其他服务,为了应用隔离,我们不会把web程序和中间件部署在同一个容器中,因此就需要用到了容器间的通信。

tips:Docker中容器的name和id可以替换,下文中均使用name

需要学习的几个Docker命令

  • docker inspect 容器id/镜像id 获取容器/镜像的元数据信息
  • docker network ls 列出Docker的网络服务
  • docker network create -d bridge 网桥名 创建网桥
  • docker network connect 网桥名 容器id/容器name 将容器和网桥绑定

虚拟IP通信

Docker容器创建时会自动分配虚拟IP,虚拟IP无法从外部直接访问,但是在Docker环境中是互通的。

启动一个centos容器模拟web服务

docker run -d --name web -it centos bash

因为centos容器启动时会自动退出,因此需要使用-it结合bash使其阻塞

启动一个centos容器模拟mysql服务

docker run -d --name mysql -it centos bash

两个容器启动后,使用命令查看mysql容器的IP地址

docker  inspect mysql

docker network设置与宿主机一样 docker与宿主机通信_linux

如图,在元数据的 Networks>IPAddress中可以看到mysql服务的虚拟ip(172.17.0.3)

进入web容器中尝试访问mysql

docker exec -it web bash

ping 172.17.0.3

docker network设置与宿主机一样 docker与宿主机通信_容器_02


可以看到网络通畅,重复上述步骤在mysql容器中ping web服务器的虚拟ip得到相同的结果。

由于容器创建成本较低,使用IP通信在新建或重启容器后需要修改配置信息(或设置为IP),因此不建议使用IP进行容器间的通信

容器间单向通信

除了使用虚拟IP通信,我们还可以使用容器间的单向通信技术,需要在容器启动时指定link对象,并使用name进行通信

启动一个centos容器web-link模拟web服务,并link到mysql容器

docker run -d --name web-link --link mysql -it centos bash

进入web-link容器中尝试访问mysql容器,发现web-link已经能正常访问到mysql容器了!

docker network设置与宿主机一样 docker与宿主机通信_linux_03


此时查看服务器的host文件

docker network设置与宿主机一样 docker与宿主机通信_mysql_04


发现Docker已经帮我们配置了mysql的IP使用同样方法进入mysql容器,并尝试访问web-link容器,提示unKnown

docker network设置与宿主机一样 docker与宿主机通信_linux_05


由此可见,link可以实现容器间通信且为单向通信。

问:如果我在两个容器中都配置了单向通信,是不是就能实现双向通信了呢?
博主在Docker版本 20.10.17默认配置情况下是不可以的,感兴趣的可以自己测试

基于Bridge实现容器双向通信

在Docker中连接同一Bridge的容器是互联互通的,因此可以使用自定义网桥来实现特定容器间的互联互通。

查看系统网络配置

docker network ls

docker network设置与宿主机一样 docker与宿主机通信_linux_06


可以看到一个名为bridge的网桥,该网桥为Docker默认网桥,承担起容器与外界的通信的桥梁。

由上文可知此时centos1和centos2容器之间无法使用名称进行通信,接下来我们将创建一个自己的网桥来实现容器间的双向通信。

创建两个centos容器

docker run -d --name centos1 -it centos /bin/bash
docker run -d --name centos2 -it centos /bin/bash

创建一个自己的网桥

docker network create -d  bridge my-bridge
  • create 创建一个网络配置
  • -d 指定类型

将容器与网桥进行绑定

docker network connect my-bridge centos1
docker network connect my-bridge centos2

此时可以看到容器的源数据(docker inspect centos1)中已经有了相关的网桥信息

docker network设置与宿主机一样 docker与宿主机通信_linux_07

测试centos1容器与容器centos2是否互通

docker network设置与宿主机一样 docker与宿主机通信_linux_08

docker network设置与宿主机一样 docker与宿主机通信_docker_09

可以看到我们使用网桥成功将两个容器网络连接起来了!