docker网络
- docker网络概念
- host模式
- bridge
- none
- joined-container
- 容器之间的通讯方式
- 自定义网络
- 不同网段的容器网络连通
docker网络概念
docker的网络模式
这里我们先讨论docker的单主机网络模式,它包括以下4类:
host
bridge
none
joined-container
host模式
docker不会为容器创建独有的network namespace;
使用宿主机的默认网络命名空间,共享一个网络栈;
表现为容器内和宿主机的IP一致;
这种模式用于网络性能较高的场景,但安全隔离性相对差一些。
bridge
桥接模式,有点类型VM-NAT,dockerd进程启动时会创建一个docker0网桥,容器内的数据通过这个网卡设备与宿主机进行数据传输。
docker会为容器创建独有的network namespace,也会为这个命名空间配置好虚拟网卡,路由,DNS,IP地址与iptables规则(也就是sandbox的内容)。
none
none模式可以说是桥接模式的一种特例,docker会为容器创建独有的network namespace ,但不会为这个命名空间准备虚拟网卡,IP地址,路由等,需要用户自己配置。
joined-container
容器共享模式,这种模式是host模式的一种延伸,一组容器共享一个network namespace;
对外表现为他们有共同的IP地址,共享一个网络栈;
kubernetes的pod就是使用的这一模式。
关于跨主机的docker网络通信,包含overlay、macvaln,又包含calico、flannel、weave等方案,不过跨主机的docker网络管理更多的是交给kubernetes或swarm等编排工具去实现了。
容器之间的通讯方式
新建的两个容器之间是可以互通的,他们之间通过bridge docker0进行通信,docker0为他们分别组了一对
我么启动一个tomcat1来查看下它的IP
docker run -d -P --name tomcat01 tomcat #启动tomcat01
docker exec -it tomcat01 ip addr #查tomcat01的ip
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#返回主机ping tomcat01
ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.216 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.044 ms
#通过上面的情况,我么可以看出宿主机是可以ping通自己所建的容器的
原理:
1.我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0
2.桥接模式,使用的技术是evth-pair技术!
3.启动的容器,也会得到一张对应的网卡
再启动一个tomcat02会发现每启动一个容器,下面的网卡ye会多一个。
此时:我们会发现启动容器带来的网卡都是一对一对的
因为evth-pair就是一堆的虚拟设备接口,它们都是成对出现,例如7对应6,5对应4;正因为有了这个特性,evth-pair才充当了一个桥梁的作用,连接各种虚拟网络设备的Openstac,Docker容器之间的连接是用的OVS连接,都是使用evth-pair。
那两个容器之间是否能ping通呢?
这我们测试下tomcat01是否可以ping通tomcat02!
docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.074 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.048 ms
通过实验证明,tomcat02是可以ping通tomcat01的
原理图:
结论,tomcat01和tomcat02是共用一个路由器,docker0.
所以,所有的容器不指定网络的情况下,都是docker0路由的,docker会给容器分配一个默认的可用IP来实现通讯。
#如果不加参数,启动容器默认走bridge(桥接模式)
我们直接启动的命令
docker run -d -P --name tomcat01 tomcat
和
docker run -d -P --name tomcat01 --net bridge tomcat
其实是一样的,默认有–net bridge 这个参数
刚刚我们通过IP地址是可以进行容器间的通讯的,假如项目不重启,数据库ip换掉了,我们希望可以处理这个问题,那我们直接使用容器的名字是否还可以ping通呢?
测试
[root@docker ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
[root@docker ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
#这时候通过名字是无法ping通
为了解决这个问题,docker为我们准备了自定义网络。
自定义网络
创建自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
bb3aac34755d bridge bridge local
faa06498f8b8 host host local
0a4bca199bba mynet bridge local
674f1e2caf4c none null local
查看网络信息
docker network inspect mynet
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
通过自定义网络创建容器
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
然后再次查看自定义网络的信息
docker network inspect mynet
就能够看到创建容器的网络地址
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
"Name": "tomcat-net-01",
"EndpointID": "7edc84759c8da4153ed85ff62637645b31c2374
0dd4b9ce6785ca8990a98a653", "MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"fc3ffae295eb76822d6b8682aba2547ad7ee3510508c4f883d9003c8b
701dc7a": { "Name": "tomcat-net-02",
"EndpointID": "84f94c697a60ad62ba1c505b4eb4c2d41ae6332
58bb8ea66fc917935bbbeac89", "MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
测试两个容器间的通讯:
首先通过ip地址
[root@docker ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.167 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.052 ms
然后通过容器名
[root@docker ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.568 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.044 ms
我们的自定义网络docker已经帮我们维护好了对应的关系,因此这种自定义网络的方式是推荐使用的
好处是能够隔离两个集群之间的网络,保证安全
不同网段的容器网络连通
拓扑图:
首先测试docker0的网段和我们自定义mynet能否连通
测试能否ping通
docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
#不同网段肯定是没法连通的
#因此我们需要使用connect连通网络
docker network connect mynet tomcat01
docker network inspect mynet #查看mynet的信息
"Name": "tomcat01",
"EndpointID": "4594a63296a94af2384d6fe7d6caa74436d80bf
6101915a391e2f8e8a4f50473", "MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
#这里发现tomcat01已经加入到mynet网络了
#再次进行测试:
docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.107 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.051 ms
#将tomcat02也加入到mynet网络
docker network connect mynet tomcat02
#测试tomcat02和tomcat-net2-01是否能连通
docker exec -it tomcat02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.052 ms
#测试tomcat02和tomcat-net2-02是否能连通
docker exec -it tomcat02 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.049 ms
通过测试,我们发现,不同网段的容器加入到同一个网络下是可以实现直接通讯的。
不同主机之间容器互联的拓扑图:
因为该架构消耗内存较大,平时用的很少,这里就不做演示!