一、前言
在上一篇文章中已经介绍了docker数据的备份、恢复与迁移, 下面正式进入到docker网络模式详解以及容器间的网络通信。
当项目大规模使用 Docker 时,容器通信的问题也就产生了。要解决容器通信问题,必须先了解很多关于网络的知识。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker 同样有着很多不完善的地方,网络方面就是 Docker 比较薄弱的部分。因此,我们有必要深入了解 Docker 的网络知识,以满足更高的网络需求。
二、docker网络模式介绍
1、默认网络
在安装完Docker以后,会默认创建三种网络,可以通过docker network ls
命令查看
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
03630b284778 bridge bridge local
cd72d6f40b2e host host local
784bae94991c none null local
在学习 Docker 网络之前,我们有必要先来了解一下这几种网络模式都是什么意思
网络模式 |
简介 |
bridge |
为每一个容器分配、设置 IP 等,并将容器连接到一个docker0 虚拟网桥,默认为该模式。 |
host |
容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。 |
none |
容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,IP 等。 |
container |
新创建的容器不会创建自己的网卡和配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。(不属于默认网络,但在Kubernetes中会使用到 ) |
1.1、bridge网络模式
在该模式中,Docker 守护进程创建了一个虚拟以太网桥 docker0
,新建的容器会自动桥接到这个接口,附加在其上的任何网卡之间都能自动转发数据包。
默认情况下,守护进程会创建一对对等虚拟设备接口 veth pair
,将其中一个接口设置为容器的 eth0
接口(容器的网卡),另一个接口放置在宿主机的命名空间中,以类似 vethxxx
这样的名字命名,从而将宿主机上的所有容器都连接到这个内部网络上。
关于 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,实现容器网络环境的隔离性。
演示案例:
1、运行一个基于busybox
镜像构建的容器 mybox
,并查看容器的ip
地址信息
docker run -it --name=mybox busybox
可以看到mybox
容器有一个lo 本地回环地址
和 一个4: eth0@if5
网卡
2、查看宿主机的ip
地址信息
可以看到宿主机有一个lo 本地回环地址
、一个ens32
网卡 (即:eth0
)、一个docker0
网桥和一个5: vetha1025cd@if4
网卡。
通过以上的比较可以发现,证实了之前所说的:守护进程会创建一对对等的虚拟设备接口 veth pair
,将其中一个接口设置为容器的 eth0
接口(容器的网卡,即上图容器mybox
的4: eth0@if5
网卡),另一个接口放置在宿主机的命名空间中,以类似 vethxxx
这样的名字命名 (即:上图宿主机的5: vetha1025cd@if4
网卡)。
同时,守护进程还会从网桥 docker0
的私有地址空间中分配一个 ip
地址和子网给该容器,并设置 docker0
的 ip
地址为容器的默认网关。也可以安装 yum install -y bridge-utils
以后,通过 brctl show
命令查看网桥信息。
对于每个容器的 IP
地址和 Gateway
信息,我们可以通过 docker inspect 容器名称|ID
进行查看,在 NetworkSettings
节点中可以看到详细信息。
可以看到 Gateway
网关地址为 docker0
的 ip
地址 172.17.0.1
,容器的ip
地址为172.17.0.2
我们还可以通过 docker network inspect bridge
查看所有 bridge
网络模式下的容器,在 Containers
节点中可以看到容器名称。
1.2、host网络模式
host
网络模式需要在创建容器时通过参数 --net host
或者 --network host
指定。
采用 host
网络模式的 Docker Container
,可以直接使用宿主机的 ip
地址与外界进行通信,若宿主机的 eth0
是一个公有 ip
,那么容器也拥有这个公有 ip
。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT
转换。
host
网络模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。
演示案例:
1、运行一个基于busybox
镜像构建的容器 hostbox
,并查看容器的ip地址信息
docker run -it --name=hostbox --net host busybox
可以看到hostbox
容器有一个lo 本地回环地址
、一个ens32
网卡 (即:eth0
) 和 一个docker0
网桥
2、查看宿主机的ip地址信息
可以看到宿主机的ip
地址信息跟上图的hostbox
容器的ip
地址信息是一模一样的
我们还可以通过 docker network inspect host
查看所有 host
网络模式下的容器,在 Containers
节点中可以看到容器名称。
1.3、none网络模式
none
网络模式是指禁用网络功能,只有 lo
地址 (local
的简写),代表 127.0.0.1
,即 localhost
本地回环地址。在创建容器时通过参数 --net none
或者 --network none
指定。
none
网络模式即不为 Docker Container
创建任何的网络环境,容器内部就只能使用 loopback
网络设备,不会再有其他的网络资源。可以说 none
模式为 Docke Container
做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker
开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker
设计理念的开放。
演示案例:
运行一个基于busybox
镜像构建的容器 nonebox
,并查看容器的ip地址信息
docker run -it --name=nonebox --net none busybox
可以看到nonebox
容器有一个lo 本地回环地址
我们还可以通过 docker network inspect none
查看所有 none
网络模式下的容器,在 Containers
节点中可以看到容器名称。
1.4、container网络模式
Container
网络模式是 Docker
中一种较为特别的网络的模式。在创建容器时通过参数 --net container:已运行的容器名称|ID
或者 --network container:已运行的容器名称|ID
指定。
处于这个模式下的 Docker
容器会共享一个网络栈,这样两个容器之间可以使用 localhost
高效快速通信。
Container
网络模式即新创建的容器不会创建自己的网卡,配置自己的 ip
,而是和一个指定的容器共享 ip
、端口范围等。 同样两个容器除了网络方面相同之外,其他的如文件系统、进程列表等还是隔离的。
演示案例:
1、运行一个基于bridge
网络模式的mybox
容器创建container
网络模式的容器 containerbox
,并查看容器的ip
地址信息
//启动原先的mybox容器
docker start mybox
//运行containerbox容器
docker run -it --name=containerbox --net container:mybox busybox
可以看到containerbox
容器有一个lo 本地回环地址
和 一个4: eth0@if5
网卡
2、查看mybox
容器的ip
地址信息
docker exec -it mybox ip addr
可以看到mybox
容器的ip
地址信息跟上图的containerbox
容器的ip
地址信息是一模一样的
3、查看宿主机的ip
地址信息
通过以上测试可以发现,Docker
守护进程只创建了一对对等虚拟设备接口用于连接 mybox
容器和宿主机,而containerbox
容器则直接使用了 mybox
容器的网卡信息。
这个时候如果将mybox
容器停止,会发现containerbox
容器就只剩下 lo 本地回环地址
了
如果mybox
容器重启以后,containerbox
容器也重启一下,就又可以获取到网卡信息了
2、自定义网络
虽然 Docker
提供的默认网络使用比较简单,但是为了保证各容器中应用的安全性,在实际开发中更推荐使用自定义的网络进行容器管理,以及启用容器名称到 ip
地址的自动 DNS
解析。
从 Docker 1.10
版本开始,docker daemon
实现了一个内嵌的 DNS server
,使容器可以直接通过容器名称通信。方法很简单,只要在创建容器时使用 --name
为容器命名即可。
但是使用 Docker DNS
有个限制:只能在 user-defined
网络中使用。也就是说,默认的 bridge
网络是无法使用 DNS
的,所以我们就需要自定义网络。
2.1、创建网络
1、通过 docker network create
命令可以创建自定义网络模式,查看 docker network create
命令使用详情,发现可以通过 -d
或者 --driver
指定网络模式且默认是 bridge
网络模式,命令提示如下:
2、创建一个基于 bridge
网络模式的自定义网络模式 custom_network
,完整命令如下:
docker network create custom_network
或者
docker network create -d bridge custom_network
3、通过 docker network ls
查看本地网络:
4、通过自定义网络模式 custom_network
创建容器:
docker run -di --name=custombox --net custom_network busybox
5、可以通过 docker inspect 容器名称|ID
查看容器的网络信息,在 NetworkSettings
节点中可以看到详细信息
docker inspect custombox
2.2、连接网络
1、通过 docker network connect 网络名称 容器名称
为容器连接新的网络模式,这里我们为mybox
容器添加custom_network
网络
docker network connect custom_network mybox
2、通过 docker inspect 容器名称|ID
查看容器的网络信息,可以看到mybox
容器多增加了custom_network
网络
docker inspect mybox
2.3、断开网络
1、通过 docker network disconnect 网络名称 容器名称
命令断开网络
docker network disconnect custom_network mybox
2、通过 docker inspect 容器名称|ID
再次查看容器的网络信息,发现只剩下默认的 bridge
网络了
docker inspect mybox
2.4、移除网络
可以通过 docker network rm 网络名称
命令移除自定义
的网络,网络移除成功则会返回自定义的网络名称
docker network rm custom_network
提示
:如果某个自定义网络模式被创建的容器使用了,则该网络模式无法被删除。
3、容器间的网络通信
接下来我们通过所学的知识实现容器间的网络通信。首先明确一点,容器之间要想互相通信,必须要有属于同一个网络的网卡。
1、我们先创建两个基于默认的 bridge
网络模式的容器
docker run -di --name=box busybox
docker run -di --name=otherbox busybox
2、通过 docker network inspect bridge
查看两容器的具体 ip
信息
可以看到容器box
的ip地址为172.17.0.3
,容器otherbox
的ip
地址为172.17.0.4
3、然后测试两容器间是否可以进行网络通信
//容器box ping 容器otherbox
docker exec -it box ping -c3 172.17.0.4
//容器otherbox ping 容器box
docker exec -it otherbox ping -c3 172.17.0.3
经过测试,从结果得知两个属于同一个网络的容器是可以互相进行网络通信的,但是由于容器经常会被删除和创建,其IP 地址经常会发生变化,是不固定的。那容器内所有通信的 IP 地址也需要进行更改,那么能否使用固定的容器名称进行网络通信呢?我们接着继续测试
经过测试,从结果得知使用容器名称进行网络通信是不行的,那怎么实现这个功能呢?
前面说过,从 Docker 1.10
版本开始,docker daemon
实现了一个内嵌的 DNS server
,使容器可以直接通过容器名称通信。方法很简单,只要在创建容器时使用 --name
为容器命名即可。
但是使用 Docker DNS
有个限制:只能在 user-defined
网络中使用。也就是说,默认的 bridge
网络是无法使用 DNS
的,所以我们就需要自定义网络。
4、我们先基于 bridge
网络模式创建自定义网络 custom_network
,然后创建两个基于custom_network
自定义网络模式的容器
5、通过 docker network inspect custom_network
查看两容器的具体 ip
信息
6、然后测试两容器间是否可以通过网络名称进行网络通信,分别使用具体 ip
和容器名称进行网络通信
//通过容器ip地址,容器custombox1 ping 容器custombox2
docker exec -it custombox1 ping -c3 172.19.0.3
//通过容器名称,容器custombox1 ping 容器custombox2
docker exec -it custombox1 ping -c3 custombox2
经过测试,从结果得知两个属于同一个自定义网络的容器是可以进行网络通信的,并且可以使用容器名称进行网络通信。
那如果此时我希望 bridge
网络下的容器也可以和 custom_network
网络下的容器进行网络又该如何操作?其实答案也非常简单:给 bridge
网络下的容器再添加一个新的 custom_network
网络即可。
//为容器box添加custom_network网络
docker network connect custom_network box
//容器custombox1 ping 容器box
docker exec -it custombox1 ping -c3 box
//容器box ping 容器custombox1
docker exec -it box ping -c3 custombox1
Docker入门到实践系列文章列表:
Docker入门到实践 (一) docker简介与安装
Docker入门到实践 (二) docker常用命令讲解
Docker入门到实践 (三) Dockerfile解析与镜像制作
Docker入门到实践 (四) docker容器数据卷与数据卷容器
Docker入门到实践 (五) docker数据的备份、恢复与迁移
Docker入门到实践 (六) docker网络模式详解以及容器间的网络通信
Docker入门到实践 (七) docker常用软件的安装
Docker入门到实践 (八) 本地镜像推送到阿里云 和 下载镜像到本地
Docker入门到实践 (九) docker可视化界面portainer的安装与使用
Docker入门到实践 (十) IDEA集成Docker构建容器镜像,部署项目
Docker入门到实践 (十一) docker私有仓库的搭建与配置
Docker入门到实践 (十二) docker compose简介与安装
Docker入门到实践 (十三) docker compose配置文件与常用命令讲解
Docker入门到实践 (十四) docker企业级容器镜像仓库HarBor的搭建与配置