【Docker】(六)使用network完成容器间的网络通信

1.前言

本系列文章记录了从0开始学习Docker的过程,Docker系列历史文章:

(一)基本概念与安装使用
(二)如何使用Docker发布一个SpringBoot服务
(三)使用registry远程镜像仓库管理镜像
(四)使用volume持久化Docker容器中的Redis数据
(五)使用bind mounts修改Docker容器中的Nginx配置

在前边介绍了,得益于使用dockerfile创建镜像文件,registry仓库管理镜像文件,我们可以仅通过docker run这个简单的指令,就能创建容器并启动一个服务,减少了繁琐的安装部署流程。容器之所以能够这么强大,除了上述的镜像文件管理以外,还得意于Dockernetwork机制。

可以想象一下,我们可以将已经创建好的容器看作一个轻量级的OS,如果没有网络通信,这个容器就被变成一个孤岛,没有什么存在的意义。所以在容器与宿主机之间、容器与容器之间,通过network建立了网络通信。

network机制中,提供了容器间的网络通信API,这个API封装了对操作系统网络的操作,我们在使用Docker的时候可以不用在意操作系统层面的网络实现细节。

接下来会介绍如何使用这些API,并以Nginx反向代理为例讲述自定义的network存在的意义。

2.network的驱动类型

Docker中的network实际上是使用的插件机制,即提供核心接口,让不同的插件去实现细节,我们一般将这种实现细节的插件叫做驱动。由用户根据需要选择不同的驱动处理不同的业务场景。

Docker官方提供了几个默认的驱动,下面是不同驱动使用场景:

  • bridge:用在单机多容器需要互相通信的场景,是docker的默认网络驱动。
  • overlay:用于多机多容器的网络通信场景,更多的使用在docker swarm中。
  • host:也是用在单机场景,与bridge的区别在于,host会直接使用宿主机的ip和端口。
  • ipvlan:用于用户需要自行操作ip的场景。
  • macvlan:用于用户需要自行操作mac地址的场景。
  • none:禁用网络,自己玩。

一般来说常用的就是bridgeoverlay驱动,如果上述默认的驱动类型还不满足要求的话,也可以在Docker Hub上找自定义的驱动【自定义网络驱动地址】

3.网络驱动的使用

3.1.bridge模式

使用docker network指令可以管理网络驱动【network指令文档地址】,在docker安装完毕之后,会创建几个默认的网络驱动,如下:

docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
18baf7cfd864   bridge    bridge    local
06fe786c0c48   host      host      local
6844c7218d3f   none      null      local

我们在输入docker run运行容器,如果不显示的指定驱动,则会使用默认的bridge,但是我们在实际使用时,一般不会选择默认的驱动,而是自行创建一个。

docker network create -d bridge my-bridge

这里的-d是指定驱动类型,默认就是bridge,如果想创建一个bridge类型的驱动的话,指令可以简化为:

docker network create my-bridge

此时再查看network列表,就能看到刚刚创建的驱动了。

docker network ls

NETWORK ID     NAME        DRIVER    SCOPE
18baf7cfd864   bridge      bridge    local
06fe786c0c48   host        host      local
8e449b8833ab   my-bridge   bridge    local
6844c7218d3f   none        null      local

为什么要使用自定义的bridge而不使用默认的呢?

自定义bridge有以下的几点优势:

  • 提供了DNS服务
    可以将容器名映射到容器的ip和端口,使用容器名进行网络访问。
  • 可以更好的做到容器隔离
    可以将一组应用放到同一个bridge中,另一组应用放到另一个bridge中,两组应用互不影响。
  • 可以动态的添加和移除网络驱动
    在容器运行的时候,可以通过docker network connect/disconnect指令,连接或移除某一个自定义的网络驱动,这种方式是不需要重启容器的。如果使用默认的bridge则需要重新创建容器。

接下来,以nginx做服务的反向代理的示例,来感受一下自定义network的优势。

在上一篇《使用bind mounts修改Docker容器中的Nginx配置》 中,已经详细的讲述了如何创建nginx容器,并将配置文件挂接到宿主机中,不知道如何在Docker中使用nginx的同学,可以看一下这篇Nginx配置部分,非常简单。在这个例子中,配置了两个SpringBoot的服务,配置如下:

upstream hello-boot {
    server 192.168.200.101:8080;
    server 192.168.200.101:8081;
}

server {
    listen       80;
    listen  [::]:80;
    server_name  192.168.200.101;

    location /hello {
        proxy_pass http://hello-boot;
    }
    
    access_log  /var/log/nginx/hello-boot.access.log  main;
}

配置中的ip地址192.168.200.101是宿主机所在的ip,两个SpringBoot服务所在的容器,映射了宿主机的端口80808081,此时我们访问nginx时,就可以将请求转发到任意一个服务中。

这种方式虽然可以正常使用,但是占用了宿主机的端口,并且还可能存在端口冲突的问题,所以最好是在upstream中配置容器的ip而不是宿主机的ip,而容器间需要网络通信的话,需要将所有的容器都连接到同一个网络驱动中,现在将Nginx和两个SpringBoot的服务都连接到my-bridge
上面提到了,自定义的bridge可以动态的连接或断开连接,所以可以直接使用connect指令,不需要重新创建容器。

docker network connect my-bridge my-nginx
docker network connect my-bridge hello-1
docker network connect my-bridge hello-2

然后使用inspect指令查看容器的网络情况。

docker network inspect my-bridge

在这里插入图片描述
可以看到my-bridge为各个容器分配的ip地址,我们将hello-1hello-2的ip填充到nginx的配置文件中:

upstream hello-boot {
	server 172.18.0.3:8080;
	server 172.18.0.4:8080;
}

这样就不会占用宿主机的端口了,但又引入了新的问题,这里的ip是由my-bridge动态分配的,在hello-1hello-2重新发布时,有可能会被其他的应用占用ip,导致访问异常。
上面我们提到了,自定义的bridge自带了DNS服务,所以我们可以使用容器名代替ip地址,最终的配置文件修改如下:

upstream hello-boot {
	server hello-1:8080;
	server hello-2:8080;
}

server {
    listen       80;
    listen  [::]:80;
    server_name  192.168.200.101;

    access_log  /var/log/nginx/hello-boot.access.log  main;

	location /hello {
		proxy_pass http://hello-boot;
	}
}

重新加载Nginx并尝试访问:

docker exec -it my-nginx nginx -s reload
curl http://192.168.200.101/hello/sayHello?name=挥之以墨

sayHello方法只做了一个返回,输入了name是什么就返回什么,此时会打印出:

hello 挥之以墨

3.2. host模式

host模式创建的容器,不能指定映射的端口,会使用镜像中已经指定好的端口,例如创建一个host模式的nginx。

docker run -d --network=host --name nginx-host nginx

此时,将会占用宿主机的80端口,尝试访问下:
在这里插入图片描述

4.结语

本篇主要讲述了bridge类型的网络驱动是如何使用的,自定义的bridge相对于默认的bridge的优势所在,即:

  • 自带DNS服务
  • 可以动态的连接容器或断开容器而不需要重启
  • 可以有效的隔离不同的应用组

而对于host类型的网络驱动来说,由于或占用主机的端口,而且不能动态指定端口,很容易端口冲突,我们一般不选择这种使用方式。

overlay类型的驱动,主要是用在多机多容器的网络通信场景,由于管理比较复杂,一般是配合多机容器编排机制 Docker Swarm来使用的,在后续的博客中会继续讲述。

下一篇会讲Docker的单机容器编排技术,Docker Compose。


如果觉得本文对你有所帮助,可以帮忙点点赞哦!你的支持是我更新最大的动力!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挥之以墨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值