理解Docker0网卡

29684-tr2gsst6iqp.png

问题: docker 是如何处理容器网络访问的?

  • 我们通过命令查看某一个容器的内部ip 可以看出容器内部的ip和docker0网卡是在同一网段的
  • 并且宿主机和容器之间是可以相互ping通的
docker exec -it tomcat1 ip addr

77598-5q4381v46rc.png

原理

  • 每启动一个容器, docker就会给容器分配一个ip. 只要安装了docker 就会有一个docker0的网卡
  • docker0的网卡和真实的物理网卡之间是桥接模式
  • 使用的技术是 evth-pair技术

evth-pair 技术

  • 当我们启动容器的时候就会生成一对网卡
  • evth-pair 就是一对虚拟设备接口, 他们都是成对出现的 一段连着协议, 一段彼此相连
  • 有了这种特性 evth-pair 充当一个桥梁,连接各种虚拟设备

24034-yds8lzhwgkq.png
06812-rqz8sfmlcps.png

画图理解

75492-to9cuhy2v9.png

结论

  • tomcat01 和 tomcat02 是公用一个路由器 docker0
  • 容器在不指定网络的情况下, 都是走docker0 路由的 docker会给容器分配一个默认的ip
  • Docker中所有的网络接口都是虚拟的
    93211-0tos63kx77z.png

容器互联 --link

  • 通过上面我们会发现容器之间可以通过ip地址是可以ping通的
  • 那么再某些情况下不用ip 我们可不可以用容器名的方式 ping通?
  • 可以使用 --link 来解决上面的问题
# 我们重新启动一个tomcat 并且 --link tomcat1
docker run -d -P --link tomcat tomcat

# 完成之后我们就可以ping通了
docker exec -it jovial_chebyshev ping tomcat1

PING tomcat1 (172.17.0.4) 56(84) bytes of data.
64 bytes from tomcat1 (172.17.0.4): icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from tomcat1 (172.17.0.4): icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from tomcat1 (172.17.0.4): icmp_seq=4 ttl=64 time=0.069 ms
--- tomcat1 ping statistics ---
  • 这样做有一个弊端就是 反向 ping 是不通的
  • 原理就是在 jovial_chebyshev 容器中的 /etc/host 中有写
docker exec -it jovial_chebyshev 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.17.0.4    tomcat1 612aeb07e2e7
172.17.0.2    e7613df5b961
  • --link 就是在我们 hosts 中增加了一条虚拟域名

自定义网络

查看所有的docker网络

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
ea834618e218        bridge              bridge              local
2da75ecdb782        host                host                local
d7c3fa26b1bd        none                null                local

网络模式

  • bridge : 桥接模式(docker默认)
  • none : 不配置网络
  • host : 和宿主机共享网络
  • container : 容器网络连通(用的少, 局限很大)

创建自定义网络

  • --subnet 子网
  • --gateway 网关
  • --driver 默认桥接模式 不写也可以
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

查看自己创建的网络

  • 命令: docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "6eb44c49b01928fd5c010c72c2738980814855e372a215eac422d35bdb1c70c4",
        "Created": "2020-09-22T05:58:08.319032125Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

使用自己创建的网络

  • --net
docker run -d -P --net mynet --name tomcat-net-01 tomcat
再次测试
  • 使用自己的网络创建两个容器并且相互ping 都是可以ping通的
  • 比之前的 --link 要好很多
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.073 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.063 ms

#反向ping 也是可以的
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.100 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.078 ms

网络连通

容器在不同的网段内如何实现互通?

示意图

13263-x84wd8oss4.png

  • 我们会发现不同网段的容器不能ping通的.
docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
  • 所以需要使用 --network connect 命令

连通

docker network connect mynet tomcat01

查看

docker network inspect mynet

[
    {
        "Name": "mynet",
        .....
        .....
        ...
        "Containers": {
            "0796e3b7250d5c49372183e28266de528dfe072bb884220aeff9f0ccab4521a7": {
                "Name": "tomcat-net-01",
                "EndpointID": "e53cde49134bf3fb72f9bcd801ac73e208705b8cae416b689a726511b1125d49",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "2a187f1b05a15d33c5cc382c2b84d0b93fa4748f3e2ce4daed0ca0bc7a4d0500": {
                "Name": "tomcat01",
                "EndpointID": "652193a8312425944682a4b48f2f1a1d35ec5e4cea6806fbe0d5be11380627e8",
                "MacAddress": "02:42:c0:a8:00:04",
                "IPv4Address": "192.168.0.4/16",
                "IPv6Address": ""
            },
           .....
        },
        "Options": {},
        "Labels": {}
    }
]
  • 连通之后我们可以看到 tomcat01 容器直接放到了 mynet的网络下
  • 这就是一个容器两个ip地址
  • 这样我们就可以ping通了
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.082 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.074 ms

标签: Docker

添加新评论