目录
1 Bridge 模式
1.1 概述
当 Docker 启动时,会自动在主机上创建一个名为 docker0 的虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。
同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给 docker0 接口。比如典型的 172.17.42.1,掩码为 255.255.0.0。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址。
当创建一个 Docker 容器的时候,同时会创建一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。
接下来测试下上述内容的正确性:
- 查看docker0网桥:brctl show docker0,此时网桥上空空如也,没有挂载任何veth
- 查看宿主机ip,可找到docker0的ip:ip addr
- 分别创建2个容器,网络模式为默认
- 查看容器ip发现:容器ip与docker0的ip在同一网段下
- 此外:docker0下挂载了2个容器分别对应的veth
由此发现:docker0作为桥梁,一方面连接容器与容器,另一方面连接容器与宿主机,实现其通通信。
1.2 网络模式指令
- 查看docker网络模式指令:docker network ls
- 查看某个网络模式的具体信息:docker inspect 网络模式id
1.3 网桥相关指令
- 安装网桥管理工具包:yum install bridge-utils
- 查询网桥docker0的信息:brctl show docker0
- 查看ip信息:ip a
1.4 创建自定义网络
- 创建一个自定义网络(默认bridge模式):docker network create test
- 创建一个容器,并且把该容器连接到目标网络上:docker run -id --name=ng1 --network test nginx:1.16
- 创建容器时,即便不指定网络,也会默认连接到docker0这个bridge类型的网络上
- bridge模式是Docker中的默认网络模式
1.5 同一子网下的容器间通信
这里先直接给出结论
- 如果容器间直接通过ip访问,在创建容器时可以不通过 --network 参数来指定该容器的网络模式
- 如果容器间要通过主机名访问,在创建容器时,必须要自定义网络模式
详细过程如下
- 进入主机名称为my_box的容器中,在该容器中可以使用常用的Linux指令(使用的默认docker0网桥):docker run -it --hostname=my_box busybox sh
- 上面的指令,是想分别创建两个busybox容器,然后ifconfig看一下这两个容器是否在同一个子网下(可相互通信),结果是可以的(如果退出了busybox容器后再想进去的话,exec指令最后要用sh而不是bash!)~
- 这时候问题来了:容器间访问难道要直接通过ip吗?是否可以通过主机名称访问呢?
- 于是,通过在busybox其中一个容器中输入“hostname”,获取到当前容器的主机名后,让另一个容器去ping这个主机名,结果竟然不能访问!
- 这就说明:默认的桥接模式(使用网桥docker0)并不具备DNS解析能力(将主机名解析为目标容器的ip地址)
- 接下来重新创建2个容器并且自定义网桥,看看是否能够通过主机名实现同一子网下容器之间的访问,这下就可以啦,如下图~
- docker run -it --hostname=my_box2 --network=test busybox sh
- docker run -it --hostname=my_box3 --network=test busybox sh
2 Host 模式
- 如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。
- 也就是说:容器不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
- 但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的
- 在默认模式下,创建一个容器(部署redis)需要指定端口映射(宿主机端口到容器端口),然而使用host模式则不需要进行端口映射,因为用的端口就是宿主机端口
- 通过host网络方式启动一个容器部署redis:docker run -id --name=r1 --net=host redis
- 查看宿主机被占用的端口,发现6379端口被redis占用:ss -antp
3 None 模式
- 使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
- 这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
4 Container 模式
- 这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。
- 新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。
- 同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
- 创建容器,网络命名空间与现存的容器共用一个:
docker run -id --name=容器名 --net=container:其他容器id 镜像名字