1. 网络基础知识回顾
2. 网络常用命令
IP地址的查看:
Windows:
ipconfig
Linux:
ifconfig
或者ip addr
在显示的内容中,比较重要的是
eth0
和docker0
的信息网络连通性测试:
测试IP的可达性:
Ping ip地址
测试端口连通信:
telnet www.baidu.com 80
路径探测跟踪:
Linux:
tracepath www.baidu.com
Windows:
TRACE.EXE www.baidu.com
请求Web服务:
使用
curl www.baidu.com
会返回相应的页面内容,具体的操作可以查看参考4
3. Docker Bridge网络
3.1 问题:
进行如下操作:
- 在Linux主机中创建三个容器:使用
docker container run -d --name web1 nginx
和docker container run -d --rm --name box1/box2 busybox /bin/sh -c "while true; do sleep 3600; done"
,/bin/sh -c "while true; do sleep 3600; done"
表示使用shell脚本执行无限循环,每次循环就sleep(即两个容器都不会退出):
- 查询三个容器的IP地址:
docker container exec -it box1/box2 sh
进入交互式shell然后使用ip a
分别查看容器的IP地址,分别为172.18.0.2
和172.18.0.3
。但是在查询web1容器的IP地址时由于没有安装ip
命令,可以使用docker container inspect web1
查看容器具体信息,得到IP地址为172.18.0.4
- 在本机中分别ping容器的IP地址:
ping 172.18.0.2
和ping 172.18.0.3
,发现是可以ping通的- 在容器中去ping百度网址,发现同样可以ping通:
- 在busy1容器中去ping web1容器,发现同样可以ping通,并且使用
wget 172.18.0.4:80
是可以访问nginx的index.html:
- 在本机中ping web1容器的IP地址,发现可以ping通,但是在另一台主机去ping web1容器是无法ping通的:
- 在本机中使用
docker container run -d -p 80:80 --name web2 nginx
将nginx的80端口转发到本机的80端口。此时再使用另一台主机去ping本机的80端口是可以ping通的(两台主机之前是可以ping通的)引出下面5个问题:
问题1:容器为什么能获取到IP地址?
问题2:为什么在宿主机可以ping通容器的IP地址?
问题3:为什么在容器中可以ping通外网?
问题4:为什么宿主机中的不同容器可以互相ping通?
问题5:容器的端口转发怎么实现?
3.2 容器间的通信之bridge模式
假设有两台电脑需要相互通信,可以在两台电脑间连接一条网线,并且手动配置IP地址:
假设在局域网中有多台电脑需要相互通信(这里只考虑有线连接),在每台电脑间连接一条网线显然不合理,此时需要使用到交换机(路由器),然后给每台电脑分配IP地址(不需要手动配置,而是使用DHCP自动分配),并且每台电脑有一个网关,都会设置为该交换机的IP地址。每台电脑再和交换机连一条线即可:
容器间的通信和上面主机间的通信是一样的,这种模式被称为bridge模式:
可以使用
docker network ls
查看:
使用
docker network inspect 8db
可以查看bridge模式的详细信息,其中有一条信息"Subnet": "172.18.0.0/16"
,表示每创建一个容器时,就会从这个网段中分配一个IP地址给容器。除此之外还能查看到docker默认的bridge为docker0:
在容器内部有eho0接口,在docker0中有veth接口,将两个接口进行连接,这样容器间就可以通信:
3.3 容器对外通信之bridge模式
容器要实现对外通信首先要确保宿主机能连通外网
在宿主机中使用
ip route
可以查看路由:
如果是容器间的通信,则会使用到docker0的
172.18.0.0/16
作为路由,将该网段下的一个容器数据转发到另一个容器;如果是容器对外的通信,则需要使用宿主机的默认路由172.17.0.1
才能将流量转发到外网。此时box1容器(IP地址为172.18.0.2
)要ping百度,就需要经过默认路由172.17.0.1
,所以需要使用到NAT将docker0的172.18.0.0
转换为172.17.0.1
可以使用
iptables --list -t nat
命令去查看转发规则tips:
- NAT可以不仅可以进行公网IP地址和私网IP地址的转换,还可以进行私网IP地址和私网IP地址之间的转换。上面
172.18.0.0
转换为172.17.0.1
就是私网间的转换
4. 创建和使用自定义bridge
默认情况下,我们使用的都是docker0这个bridge,实际上是可以自定义bridge的:
docker network create -d bridge mybridge
:指定docker driver
为bridge(docker的driver有多种),且名字为mybridge:
- 使用
docker network inspect mybridge
可以查看到网段地址为172.20.0.0
:
- 使用
docker container run -d --rm --name box3 --network mybridge busybox /bin/sh -c "while true; do sleep 3600; done"
创建一个容器,且使用的bridge为mybridge。可以使用docker container inspect box1
查看信息:
- 一个容器也可以连接到多个bridge上,使用
docker network connect bridge box3
可以让box3容器连接再连接到bridge:
- 使用
docker container exec -it box3 sh
查看容器的IP地址也会出现eth0和eth1:
- 使用
docker container disconnect bridge box3
则可以断开该容器和bridge的连接- 整体的效果图如下:
默认的docker0和自定义的mybridge有什么区别?
- 创建容器box3和box4且连接network为
mybridge
,创建容器box5和box6且连接network为bridge
- 进入box3容器中使用
ping box4
是可以ping通的,但是进入box5容器中使用ping box6
是无法ping通的:
出现上述情况是因为默认的docker0并不提供DNS这个功能,所以建议创建自定义的bridge
5.容器的端口转发
在上图中,如果nginx容器要访问host2,则需要将
172.17.0.2
经过NAT转换为192.168.200.10
即可完成该操作。但是如果host2要访问nginx容器则不行,因为它不知道该容器的IP地址。那么要如何实现这个操作?因为host2是可以直接访问host1的8080端口(假设host1的8080端口已经开放),所以只将nginx的80端口映射到host1的8080端口。一旦host2传入的数据访问到host1的8080端口,host1就把数据转发到
172.17.0.2:80
完成上述操作使用
docker container run -d --rm -p 8080:80 --name web nginx
。然后使用iptables -t nat -nvxL
可以查看到增加了规则tcp dpt:8080 to:172.18.0.2:80
(DNAT表示基于目标地址的网络转换):
tips:
- 在dockerfile文件中会出现
EXPOSE xx端口
,这条命令的作用只是让用户知道该镜像暴露了哪些端口可以进行端口映射,不加该命令也是可以在创建容器时使用端口转发的
6. Docker host网络
- 创建两个容器box1和box2,一个network为默认的bridge,另一个为host网络。分别进入这两个容器查看其IP地址,可以看到box2容器的IP地址和宿主机的一致(即共享同一个网络):
- 创建两个nginx容器web1和web2,一个network为默认的bridge,另一个为host网络。在查看container信息时,web2是没有显示端口信息的:
并且
curl 127.0.0.1
是可以直接访问到nginx的(相当于在本地开启了nginx服务),此时再去创建一个network为host网络的nginx服务是会自动退出的,因为80端口已经在被web2使用。tips:
- 除了bridge和host网络模式外,还有none模式,容器使用该模式创建则没有建立网络通信,需要自己配置
7. 网络命名空间
- Linux的Namespace(命名空间)技术是一种隔离技术,常用的Namespace有 user namespace, process namespace, network namespace等
- 在Docker容器中,不同的容器通过Network namespace进行了隔离,也就是不同的容器有各自的IP地址,路由表等,互不影响。
8. 参考
- https://zhuanlan.zhihu.com/p/65226634
- https://www.homenethowto.com/advanced-topics/traffic-example-the-full-picture/
- https://www.hp.com/us-en/shop/tech-takes/how-does-the-internet-work
- http://www.ruanyifeng.com/blog/2019/09/curl-reference.html
- https://dockertips.readthedocs.io/en/latest/single-host-network.html