docker入门-Docker的网络

1. 网络基础知识回顾

  • 什么是IP、子网掩码、网关、DNS、端口号?

    详细的解答可以跳转到参考1

  • Internet如何工作?

    详细的解答可以跳转到参考2

  • 当你在浏览器输入一个网址并敲回车,这个过程后面发生了什么?

    详细的解答可以跳转到参考3或者我的另一篇博客

2. 网络常用命令

  • IP地址的查看:

    Windows:ipconfig

    Linux:ifconfig或者ip addr

    在显示的内容中,比较重要的是eth0docker0的信息

  • 网络连通性测试:

    测试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 nginxdocker 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.2172.18.0.3。但是在查询web1容器的IP地址时由于没有安装ip命令,可以使用docker container inspect web1查看容器具体信息,得到IP地址为172.18.0.4
  • 在本机中分别ping容器的IP地址:ping 172.18.0.2ping 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. 参考

  1. https://zhuanlan.zhihu.com/p/65226634
  2. https://www.homenethowto.com/advanced-topics/traffic-example-the-full-picture/
  3. https://www.hp.com/us-en/shop/tech-takes/how-does-the-internet-work
  4. http://www.ruanyifeng.com/blog/2019/09/curl-reference.html
  5. https://dockertips.readthedocs.io/en/latest/single-host-network.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值