跳到主要内容
  1. 所有文章/
  2. Docker学习笔记/

Docker07容器网络

·📄 2163 字·🍵 5 分钟

Docker0 #

[root@izwz91mv6i3x6k12jjqh60z ~]# ip addr

#本机回环地址 127.0.0.1/8
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

#阿里云内网地址  172.17.7.116/16
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:3e:0e:35:6a brd ff:ff:ff:ff:ff:ff
    inet 172.17.7.116/18 brd 172.17.63.255 scope global dynamic eth0
       valid_lft 313667957sec preferred_lft 313667957sec

#docker0地址 172.18.0.1/16
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:88:ea:49:a4 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0
       valid_lft forever preferred_lft forever

Docker是如何处理容器网络访问的? #

我们每启动一个容器,Docker 就会给容器自动分配一个 IP,只要安装了 Docker ,就会有一个网卡 Docker0 桥接模式,使用的技术是 evth-pairt 技术。

#启动一个容器
[root@izwz91mv6i3x6k12jjqh60z ~]# docker run -d -P --name tomcat01 tomcat
2d9f156c40335f1c105e47e60b751b3e3a094808fbdeeca65856ac26291966b9

#查看网络,发现得到一个 eth0@if91 的Ip地址  (90---91)
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
90: eth0@if91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
       
#测试主机是否能Ping通
[root@izwz91mv6i3x6k12jjqh60z ~]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.061 ms
^C
--- 172.18.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.061/0.067/0.078/0.007 ms

#再次测试ip addr,发现多了一对网卡( (91---90))
[root@izwz91mv6i3x6k12jjqh60z ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:3e:0e:35:6a brd ff:ff:ff:ff:ff:ff
    inet 172.17.7.116/18 brd 172.17.63.255 scope global dynamic eth0
       valid_lft 313667249sec preferred_lft 313667249sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:88:ea:49:a4 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0
       valid_lft forever preferred_lft forever
91: veth57aecab@if90: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP 
    link/ether ae:a3:d9:3e:9f:7e brd ff:ff:ff:ff:ff:ff link-netnsid 0

总结:我们发现这个容器带来的网卡都是一对对的。evth-pair 就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一段彼此相连。正因为这个特性,evth-pair 充当一个桥梁,连接着各种虚拟网络设备。OpebStac,Docker容器之间的连接,OVS的连接都是使用的这个技术。

#再开启一个容器
[root@izwz91mv6i3x6k12jjqh60z ~]# docker run -d -P --name tomcat02 tomcat
d45372d1407871511b6089434b41d48c18dcc0972571114f47800be5a76eda1c

#查看容器tomcat01 ip地址
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
90: eth0@if91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever

#查看容器tomcat02 ip地址
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec tomcat02 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
92: eth0@if93: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
#查看容器tomcat02 能否 ping 通 tomcat01
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec tomcat02 ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.106 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.073 ms
64 bytes from 172.18.0.2: icmp_seq=4 ttl=64 time=0.073 ms
64 bytes from 172.18.0.2: icmp_seq=5 ttl=64 time=0.071 ms
64 bytes from 172.18.0.2: icmp_seq=6 ttl=64 time=0.072 ms
64 bytes from 172.18.0.2: icmp_seq=7 ttl=64 time=0.072 ms
64 bytes from 172.18.0.2: icmp_seq=8 ttl=64 time=0.075 ms
64 bytes from 172.18.0.2: icmp_seq=9 ttl=64 time=0.070 ms
64 bytes from 172.18.0.2: icmp_seq=10 ttl=64 time=0.070 ms
64 bytes from 172.18.0.2: icmp_seq=11 ttl=64 time=0.072 ms

容器网络访问原理 #

结论:tomcat01tomcat02共用一个路由器,Docker0。所有容器在不指定网络的情况下,都是由 Docker0 路由给容器分配一个默认的可用 IP。Docker中所有的网络接口都是虚拟的。(在内网中转发效率很高),只要容器删除,对应的网桥就没了。

–link技术 #

问题:假设我们编写了一个微服务,database.url=ip ,怎么在项目不重启的情况下,当数据库的 IP 换掉时,如果只使用 IP访问连接容器是不可以的,可以用容器名字访问连接容器?

[root@izwz91mv6i3x6k12jjqh60z ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED       STATUS       PORTS                                         NAMES
d45372d14078   tomcat    "catalina.sh run"   9 hours ago   Up 9 hours   0.0.0.0:49156->8080/tcp, :::49156->8080/tcp   tomcat02
2d9f156c4033   tomcat    "catalina.sh run"   9 hours ago   Up 9 hours   0.0.0.0:49155->8080/tcp, :::49155->8080/tcp   tomcat01

#正常情况下是不能直接用容器名字 ping
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known

#使用  --link 之后测试可以使用名字 ping
[root@izwz91mv6i3x6k12jjqh60z ~]# docker run -d -P --name  tomcat03 --link tomcat02 tomcat
29bb33b11f8ef774df9871f48acf3223e3b91f60ea0f8e1bd2a4f1307fd3da54
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.116 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=4 ttl=64 time=0.074 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=5 ttl=64 time=0.074 ms
^C
--- tomcat02 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 5ms
rtt min/avg/max/mdev = 0.073/0.082/0.116/0.017 ms

#发现这只能正向 ping 通,不能反向
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

查看网络配置信息:

[root@izwz91mv6i3x6k12jjqh60z ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
d71469651905   bridge    bridge    local
4210c11fb888   host      host      local
15f30a8dc35d   none      null      local
[root@izwz91mv6i3x6k12jjqh60z ~]# docker network inspect bridge

image-20210518081532255.png

–link原理 #

查看 host 配置,发现 --link 的本质就是增加了一个 172.18.0.3 tomcat02 d45372d14078 网络配置。

[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1  localhost
::1  localhost ip6-localhost ip6-loopback
fe00::0  ip6-localnet
ff00::0  ip6-mcastprefix
ff02::1  ip6-allnodes
ff02::2  ip6-allrouters
172.18.0.3  tomcat02 d45372d14078
172.18.0.4  29bb33b11f8e

总结:Docker已经不建议使用 --link ,为了解决不支持容器名访问连接的问题,我们可以使用 自定义网络

自定义网络 #

查看所有的 Docker 网络

image-20210518082217281.png

网络模式

  • bridge:桥接 docker(默认,我们自定义的也是使用这个模式)
  • null:不配置网络
  • host:和宿主机共享网络
  • container:容器网络连通

自定义一个网络

#我们直接使用  docker run -d -P --name tomcat01 tomcat
#实际上相当于  docker run -d -P --name tomcat01 --net bridge tomcat
#bridge 就是默认的 docker网络

[root@izwz91mv6i3x6k12jjqh60z ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
d1ede6bb4ad9eee72f847aba4963a98a46503e65565e73728bf3c9514c83ba5b
[root@izwz91mv6i3x6k12jjqh60z ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
d71469651905   bridge    bridge    local
4210c11fb888   host      host      local
d1ede6bb4ad9   mynet     bridge    local
15f30a8dc35d   none      null      local

搭建好网络之后可以测试一下(自定义网络支持使用容器名 ping 通

#创建容器连接自定义网络
[root@izwz91mv6i3x6k12jjqh60z ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
ea54eb784ff876809289e6395e496102c818c3b462abd1ca24615739ddfa0704
[root@izwz91mv6i3x6k12jjqh60z ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
fc645c243cf9f423107410969404133dada0eff3d572dd9940bf1233f16b8e84

#测试是否可以直接 ping 
[root@izwz91mv6i3x6k12jjqh60z ~]# 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.085 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.068 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.069 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.072 ms
^C
--- tomcat-net-02 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.068/0.073/0.085/0.010 ms

#测试是否可以直接 ping 
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec -it tomcat-net-02 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.059 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.077 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.083 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.075 ms
^C
--- tomcat-net-01 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.059/0.073/0.083/0.012 ms

总结:自定义网络的好处,可以使不同的集群使用不同的网络,保证集群是安全健康的。

不同网络的连通问题 #

自定义网络的问题:两个连接了不同网卡网络的容器怎么 ping 通?使用容器连接网络命令!

image-20210518084738578.png

使用容器连接网络命令

image-20210518084830260.png

[root@izwz91mv6i3x6k12jjqh60z ~]# docker network connect mynet tomcat01
[root@izwz91mv6i3x6k12jjqh60z ~]# docker network inspect mynet

image-20210518085327772.png

发现:连通之后就是将 tomcat01 放到了 mynet 网络中。

测试是否可以连通:

#连通成功
[root@izwz91mv6i3x6k12jjqh60z ~]# 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.087 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.081 ms
^C
--- tomcat-net-01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.078/0.082/0.087/0.003 ms

#未加入网络的连通失败
[root@izwz91mv6i3x6k12jjqh60z ~]# docker run -d -P --name tomcat02 tomcat
40c9e2d12adec923c53139b0fea151e811d1341c81e813a1497b21f34829a5d0
[root@izwz91mv6i3x6k12jjqh60z ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known