Docker容器网络通信机制

导读:本篇文章讲解 Docker容器网络通信机制,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

本文从本人博客搬运,原文格式更加美观,可以移步原文阅读:Docker容器网络通信机制

原理

Docker启动时,会自动在主机上创建一个docker虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机,它会在挂载到它的网口之间进行转发。同时,Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker 接口。比如典型的 172.17.0.1,掩码为 255.255.0.0此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址

我们可以通过命令来查看docker虚拟网桥的信息

docker network ls  # 查看docker的网络列表
docker inspect 网络名称  # 查看某个网络的详细信息

Docker容器网络通信机制

也可以通过查看容器详细信息,得到其连接哪个网络

Docker容器网络通信机制

当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在宿主机本地并被挂载到 docker 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,宿主机可以跟容器通信,容器之间也可以通过docker网桥相互通信。Docker就创建了在宿主机和所有容器之间一个虚拟共享网络

Docker容器网络通信机制

  • 安装docker时创建的默认docker网桥,用docker network ls查看其名称是bridge,如果在宿主机上用ifconfig查看,实际上是对应了docker0虚拟网卡

Docker容器网络通信机制

  • 我们启动的所有容器,如果不做特殊的网络指定,默认都是连接到docker网桥上。每启动一个容器,都会在宿主机上创建一个veth开头的虚拟网卡,用来进行容器与宿主机、容器与容器间的通信。容器通过DHCP获取一个与docker0同网段的IP地址

Docker容器网络通信机制

  • 我们启动的所有容器,默认都是连接到docker网桥上,但是这不是一个好的实践。假设我们有多个应用,每个应用启动了自己独有的MySQLRedistomcat等容器,那么默认情况下所有容器都连接到同一个网桥,此时应用1的tomcat发送给应用1自己的mysql的数据,应用2和应用3的所有容器也都能收到,这增加了不必要的网络流量压力:

Docker容器网络通信机制

所以最佳的方式是:以应用为单位划分网络,同个应用对应的容器连接到1个网络,不同应用之间的容器做到网络隔离

Docker容器网络通信机制

docker默认的网络除了bridge外,还有hostnone

  • host:如果指定容器网络为host,那么表示容器与宿主机共享网络,即容器的ip与宿主机相同。这样做的好处是访问宿主机就相当于访问容器,提升网络性能,不需要宿主机转发给容器。坏处是容器与宿主机共享端口,不能冲突。我们可以在启动容器时通过--network host指定为host网络

    docker run -d --network host --name redis redis:5.0.8
    

    当指定网络为host之后,进入容器可以发现容器拥有与宿主机相同的ip配置

    image-20210930202740199

    而默认bridge模式的容器只有自己的ip

    Docker容器网络通信机制

    host模式可以用于所有应用和中间件部署在同一台机器的情况下,应用在容器中连接中间件只需指定ip为localhost即可,因为此时localhost就是代表了宿主机

  • none:如果指定容器的网络为none,那么将无法通过网络访问容器,容器只有一个本地回环地址。如果禁止容器联网,为了安全可以采用这种方式

网络相关命令

1.查看网络

docker network ls  # 查看docker的网络列表
docker inspect 网络名称  # 查看某个网络的详细信息

2.创建网络

docker network create 网络名称

Docker容器网络通信机制

每创建一个网络,宿主机上都会生成类似于docker0的虚拟网卡,作为该网络容器之间通信的桥梁

Docker容器网络通信机制

3.启动容器时指定网络

docker run -d -p 6380:6379 --name redis01 --network 网络名称 redis:5.0.8

Docker容器网络通信机制

可以发现,我们创建的网络baobao,默认网段是172.18.0.1,与默认docker172.17.0.1刚好区分开

启动容器指定网络时,必须保证网络已经存在

4.容器间的网络通信

连接到同一个网络的容器可以互相通信,容器启动时docker网络会为其分配ip,我们可以利用ip与其他容器通信

首先我们启动2个redis容器,指定一个自定义网络

docker run -d -p 6380:6379 --name redis01 --network baobao redis:5.0.8
docker run -d -p 6381:6379 --name redis02 --network baobao redis:5.0.8

Docker容器网络通信机制

然后通过查看网络的详细信息可以知道网络下所有容器的ip

Docker容器网络通信机制

然后我们进入到redis01的内部,尝试ping redis02的ip。没有ping命令可以先用下列命令安装

apt-get update
apt install iputils-ping

Docker容器网络通信机制

虽然用ip可以完成容器间通信,但是如果容器ip发生变化,通信将会失败。从Docker 1.10版本开始,docker daemon实现了一个内嵌的DNS server,使容器可以直接通过容器名通信。使用默认的bridge网络,不能通过DNS server实现通过容器名通信,但是使用自定义bridge网络可以做到通过容器名互相通信。所以在自定义网络的情况下,更推荐的方式是用容器名称进行通信。我们尝试在redis01中ping redis02的容器名称

Docker容器网络通信机制

注意:

  • 采用容器名称互相通信的方式,必须在创建容器时指定自定义网络才会生效。如果容器连接到默认的docker0网络是无法用容器名通信的
  • 如果没有给容器指定自定义网络,那么会连接到默认的docker0网段,此时可以用ip进行容器互联,但是这个ip是通过DHCP动态分配的,所以这种情况下更推荐直接用宿主机ip+容器映射端口进行容器间通信
  • 如果指定了自定义网络,那么推荐用容器名称进行通信

5.将容器连接到另一个网络

假如我们要将网络1的某个容器同时挂到网络2下,可以使用下列命令

docker network connect 网络名称 容器名称

执行完成后该容器与网络2就连通了,可以与网络2下的所有容器通信。其原理很简单,就是docker会给该容器再分配一个网络2网段的ip,相当于容器有2个ip,一个是网络1网段的,另一个是网络2网段的

如果想让容器与网络再断开连接,可以用下列命令

docker network disconnect 网络名称 容器名称

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/2667.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!