Docker 网络模式详解及容器间网络通讯

  当项目大规模使用 Docker 时,容器通讯的问题也就产生了。要解决容器通讯问题,必须先了解不少关于网络的知识。Docker 做为目前最火的轻量级容器技术,有不少使人称道的功能,如 Docker 的镜像管理。然而,Docker 一样有着不少不完善的地方,网络方面就是 Docker 比较薄弱的部分。所以,咱们有必要深刻了解 Docker 的网络知识,以知足更高的网络需求。docker

  

默认网络

  

  安装 Docker 之后,会默认建立三种网络,能够经过 docker network ls 查看。shell

[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
688d1970f72e        bridge              bridge              local
885da101da7d        host                host                local
f4f1b3cf1b7f        none                null                local

  

  在学习 Docker 网络以前,咱们有必要先来了解一下这几种网络模式都是什么意思。安全

网络模式 简介
bridge 为每个容器分配、设置 IP 等,并将容器链接到一个 docker0 虚拟网桥,默认为该模式。
host 容器将不会虚拟出本身的网卡,配置本身的 IP 等,而是使用宿主机的 IP 和端口。
none 容器有独立的 Network namespace,但并无对其进行任何网络设置,如分配 veth pair 和网桥链接,IP 等。
container 新建立的容器不会建立本身的网卡和配置本身的 IP,而是和一个指定的容器共享 IP、端口范围等。

  

bridge 网络模式

  

  在该模式中,Docker 守护进程建立了一个虚拟以太网桥 docker0,新建的容器会自动桥接到这个接口,附加在其上的任何网卡之间都能自动转发数据包。网络

  默认状况下,守护进程会建立一对对等虚拟设备接口 veth pair,将其中一个接口设置为容器的 eth0 接口(容器的网卡),另外一个接口放置在宿主机的命名空间中,以相似 vethxxx 这样的名字命名,从而将宿主机上的全部容器都链接到这个内部网络上。oop

  好比我运行一个基于 busybox 镜像构建的容器 bbox01,查看 ip addr学习

busybox 被称为嵌入式 Linux 的瑞士军刀,整合了不少小的 unix 下的通用功能到一个小的可执行文件中。测试

  而后宿主机经过 ip addr 查看信息以下:spa

  经过以上的比较能够发现,证明了以前所说的:守护进程会建立一对对等虚拟设备接口 veth pair,将其中一个接口设置为容器的 eth0 接口(容器的网卡),另外一个接口放置在宿主机的命名空间中,以相似 vethxxx 这样的名字命名。设计

  同时,守护进程还会从网桥 docker0 的私有地址空间中分配一个 IP 地址和子网给该容器,并设置 docker0 的 IP 地址为容器的默认网关。也能够安装 yum install -y bridge-utils 之后,经过 brctl show 命令查看网桥信息。3d

  对于每一个容器的 IP 地址和 Gateway 信息,咱们能够经过 docker inspect 容器名称|ID 进行查看,在 NetworkSettings 节点中能够看到详细信息。

  咱们能够经过 docker network inspect bridge 查看全部 bridge 网络模式下的容器,在 Containers 节点中能够看到容器名称。

  关于 bridge 网络模式的使用,只须要在建立容器时经过参数 --net bridge 或者 --network bridge 指定便可,固然这也是建立容器默认使用的网络模式,也就是说这个参数是能够省略的。

  

Bridge 桥接模式的实现步骤主要以下:

  • Docker Daemon 利用 veth pair 技术,在宿主机上建立一对对等虚拟网络接口设备,假设为 veth0 和 veth1。而 veth pair 技术的特性能够保证不管哪个 veth 接收到网络报文,都会将报文传输给另外一方。
  • Docker Daemon 将 veth0 附加到 Docker Daemon 建立的 docker0 网桥上。保证宿主机的网络报文能够发往 veth0;
  • Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被更名为 eth0。如此一来,宿主机的网络报文若发往 veth0,则当即会被 Container 的 eth0 接收,实现宿主机到 Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。

  

host 网络模式

  

  • host 网络模式须要在建立容器时经过参数 --net host 或者 --network host 指定;
  • 采用 host 网络模式的 Docker Container,能够直接使用宿主机的 IP 地址与外界进行通讯,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可使用宿主机的端口,无需额外进行 NAT 转换;
  • host 网络模式可让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通讯,可是容器的网络缺乏隔离性。

  

  好比我基于 host 网络模式建立了一个基于 busybox 镜像构建的容器 bbox02,查看 ip addr

  而后宿主机经过 ip addr 查看信息以下:

  对,你没有看错,返回信息如出一辙,我也能够确定我没有截错图,不信接着往下看。咱们能够经过 docker network inspect host 查看全部 host 网络模式下的容器,在 Containers 节点中能够看到容器名称。

  

none 网络模式

  

  • none 网络模式是指禁用网络功能,只有 lo 接口 local 的简写,表明 127.0.0.1,即 localhost 本地环回接口。在建立容器时经过参数 --net none 或者 --network none 指定;
  • none 网络模式即不为 Docker Container 建立任何的网络环境,容器内部就只能使用 loopback 网络设备,不会再有其余的网络资源。能够说 none 模式为 Docke Container 作了极少的网络设定,可是俗话说得好“少便是多”,在没有网络配置的状况下,做为 Docker 开发者,才能在这基础作其余无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。

  

  好比我基于 none 网络模式建立了一个基于 busybox 镜像构建的容器 bbox03,查看 ip addr

  咱们能够经过 docker network inspect none 查看全部 none 网络模式下的容器,在 Containers 节点中能够看到容器名称。

  

container 网络模式

  

  • Container 网络模式是 Docker 中一种较为特别的网络的模式。在建立容器时经过参数 --net container:已运行的容器名称|ID 或者 --network container:已运行的容器名称|ID 指定;
  • 处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可使用 localhost 高效快速通讯。

  Container 网络模式即新建立的容器不会建立本身的网卡,配置本身的 IP,而是和一个指定的容器共享 IP、端口范围等。一样两个容器除了网络方面相同以外,其余的如文件系统、进程列表等仍是隔离的。

  

  好比我基于容器 bbox01 建立了 container 网络模式的容器 bbox04,查看 ip addr

  容器 bbox01ip addr 信息以下:

  宿主机的 ip addr 信息以下:

  经过以上测试能够发现,Docker 守护进程只建立了一对对等虚拟设备接口用于链接 bbox01 容器和宿主机,而 bbox04 容器则直接使用了 bbox01 容器的网卡信息。

  这个时候若是将 bbox01 容器中止,会发现 bbox04 容器就只剩下 lo 接口了。

  而后 bbox01 容器重启之后,bbox04 容器也重启一下,就又能够获取到网卡信息了。

  

link

  

  docker run --link 能够用来连接两个容器,使得源容器(被连接的容器)和接收容器(主动去连接的容器)之间能够互相通讯,而且接收容器能够获取源容器的一些数据,如源容器的环境变量。

  这种方式官方已不推荐使用,而且在将来版本可能会被移除,因此这里不做为重点讲解,感兴趣可自行了解。

  官网警告信息:https://docs.docker.com/network/links/

  

自定义网络

  

  虽然 Docker 提供的默认网络使用比较简单,可是为了保证各容器中应用的安全性,在实际开发中更推荐使用自定义的网络进行容器管理,以及启用容器名称到 IP 地址的自动 DNS 解析。

  从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器能够直接经过容器名称通讯。方法很简单,只要在建立容器时使用 --name 为容器命名便可。

  可是使用 Docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是没法使用 DNS 的,因此咱们就须要自定义网络。

  

建立网络

  

  经过 docker network create 命令能够建立自定义网络模式,命令提示以下:

  

  进一步查看 docker network create 命令使用详情,发现能够经过 --driver 指定网络模式且默认是 bridge 网络模式,提示以下:

  

  建立一个基于 bridge 网络模式的自定义网络模式 custom_network,完整命令以下:

docker network create custom_network

  

  经过 docker network ls 查看网络模式:

[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b3634bbd8943        bridge              bridge              local
062082493d3a        custom_network      bridge              local
885da101da7d        host                host                local
f4f1b3cf1b7f        none                null                local

  

  经过自定义网络模式 custom_network 建立容器:

docker run -di --name bbox05 --net custom_network busybox

  

  经过 docker inspect 容器名称|ID 查看容器的网络信息,在 NetworkSettings 节点中能够看到详细信息。

  

链接网络

  

  经过 docker network connect 网络名称 容器名称 为容器链接新的网络模式。

docker network connect bridge bbox05

  经过 docker inspect 容器名称|ID 再次查看容器的网络信息,多增长了默认的 bridge

  

断开网络

  

  经过 docker network disconnect 网络名称 容器名称 命令断开网络。

docker network disconnect custom_network bbox05

  经过 docker inspect 容器名称|ID 再次查看容器的网络信息,发现只剩下默认的 bridge

  

移除网络

  

  能够经过 docker network rm 网络名称 命令移除自定义网络模式,网络模式移除成功会返回网络模式名称。

docker network rm custom_network

注意:若是经过某个自定义网络模式建立了容器,则该网络模式没法删除。

  

容器间网络通讯

  

  接下来咱们经过所学的知识实现容器间的网络通讯。首先明确一点,容器之间要互相通讯,必需要有属于同一个网络的网卡。

  咱们先建立两个基于默认的 bridge 网络模式的容器。

docker run -di --name default_bbox01 busybox
docker run -di --name default_bbox02 busybox

  

  经过 docker network inspect bridge 查看两容器的具体 IP 信息。

  

  而后测试两容器间是否能够进行网络通讯。

  

  通过测试,从结果得知两个属于同一个网络的容器是能够进行网络通讯的,可是 IP 地址多是不固定的,有被更改的状况发生,那容器内全部通讯的 IP 地址也须要进行更改,可否使用容器名称进行网络通讯?继续测试。

  

  通过测试,从结果得知使用容器进行网络通讯是不行的,那怎么实现这个功能呢?

  从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器能够直接经过容器名称通讯。方法很简单,只要在建立容器时使用 --name 为容器命名便可。

  可是使用 Docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是没法使用 DNS 的,因此咱们就须要自定义网络。

  咱们先基于 bridge 网络模式建立自定义网络 custom_network,而后建立两个基于自定义网络模式的容器。

docker run -di --name custom_bbox01 --net custom_network busybox
docker run -di --name custom_bbox02 --net custom_network busybox

  

  经过 docker network inspect custom_network 查看两容器的具体 IP 信息。

  

  而后测试两容器间是否能够进行网络通讯,分别使用具体 IP 和容器名称进行网络通讯。

  

  通过测试,从结果得知两个属于同一个自定义网络的容器是能够进行网络通讯的,而且可使用容器名称进行网络通讯。

  那若是此时我但愿 bridge 网络下的容器能够和 custom_network 网络下的容器进行网络又该如何操做?其实答案也很是简单:让 bridge 网络下的容器链接至新的 custom_network 网络便可。

docker network connect custom_network default_bbox01

学完容器网络通讯,你们就能够练习使用多个容器完成常见应用集群的部署了。后面就该学习 Docker 进阶部分的内容 Docker Compose 和 Docker Swarm。

本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议

你们能够经过 分类 查看更多关于 Docker 的文章。

  

🤗 您的点赞转发是对我最大的支持。

📢 扫码关注 哈喽沃德先生「文档 + 视频」每篇文章都配有专门视频讲解,学习更轻松噢 ~

相关文章
相关标签/搜索