• Docker-基础006-Docker网络


    学习内容总结来自B站UP主"遇见狂神说"的Docker教学视频: https://www.bilibili.com/video/BV1og4y1q7M4

    Docker网络

    理解Docker0

    在宿主机linux上, 运行ip addr, 查看当前的网卡信息

    (root@Aliyun-Alex:/home/alex)# ip addr
    # 打印结果
    # 第一个 lo 为回环IP 127.0.0.1
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        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
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    # 第二个 eth0 为阿里云内网IP 172.19.67.12
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
        link/ether 00:16:3e:10:69:3c brd ff:ff:ff:ff:ff:ff
        inet 172.19.67.12/20 brd 172.19.79.255 scope global dynamic noprefixroute eth0
           valid_lft 310946826sec preferred_lft 310946826sec
        inet6 fe80::216:3eff:fe10:693c/64 scope link 
           valid_lft forever preferred_lft forever
    # 第三个 docker0 为Docker使用的IP 172.17.0.1
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
        link/ether 02:42:92:a2:eb:c6 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:92ff:fea2:ebc6/64 scope link 
           valid_lft forever preferred_lft forever
    

    在宿主机安装了docker后, 就会新增一个名为docker0的网卡

    启动一个容器

    现在运行一个tomcat容器, 尝试linux宿主机ping一下tomcat容器, 看是否能ping通

    docker run -d -P --name tomcat01 tomcat
    

    查看tomcat容器中的ip地址信息

    docker exec -it tomcat01 ip addr
    # 可以看到也有两个地址
    # 第一个 lo 为回环IP 127.0.0.1
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        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
    # 第二个 eth0@if161 为容器的IP 172.17.0.2
    160: eth0@if161: <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
    

    发现容器内的IP地址172.17.0.2和宿主机的docker0172.17.0.1属于同一网段, 那么两者就是能ping通的

    (root@Aliyun-Alex:/home/alex)# 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.077 ms
    64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.059 ms
    64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.069 ms
    64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=3.02 ms
    64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.060 ms
    ^C
    --- 172.17.0.2 ping statistics ---
    5 packets transmitted, 5 received, 0% packet loss, time 63ms
    rtt min/avg/max/mdev = 0.059/0.656/3.016/1.180 ms
    

    再次回到宿主机linux执行ip addr, 发现又多了个网卡 161: veth8dd219c@if160

    161: veth8dd219c@if160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
        link/ether 16:71:2b:b0:4c:f2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet6 fe80::1471:2bff:feb0:4cf2/64 scope link 
           valid_lft forever preferred_lft forever
    

    再启动一个容器

    docker run -d -P --name tomcat02 tomcat
    

    在容器中查看ip addr

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ip addr
    # 同样有一个容器内部的IP 162: eth0@if163
    162: eth0@if163: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    

    在宿主机linux执行ip addr, 发现又多了个网卡 163: veth98c33bb@if162

    163: veth98c33bb@if162: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
        link/ether fa:a3:7c:12:d1:a9 brd ff:ff:ff:ff:ff:ff link-netnsid 1
        inet6 fe80::f8a3:7cff:fe12:d1a9/64 scope link 
           valid_lft forever preferred_lft forever
    

    可以看出规律, 每启动一个容器, 就会给容器分配一个IP, 同时宿主机也多一个IP地址, 且这两个IP地址是有对应关系的

    在宿主机的网卡名为宿主机IP序号: vethxxx@if容器IP序号

    在容器内的网卡名为容器IP序号: eth0@if宿主机IP序号

    这就是veth-pair技术, 就是一对虚拟设备接口, 他们都是成对出现的, 一端连着协议, 一端彼此相连, veth-pair可以充当一个桥梁, 连接各种虚拟网络设备

    如OpenStack, OVS, 和Docker容器之间的连接, 都是使用的veth-pair技术

    由于这两个容器的IP都是在同一网段内(172.17.0.0), 所以可以相互ping通

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat01 ping 172.17.0.3
    PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
    64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.100 ms
    64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.082 ms
    

    Docker网络桥接图

    Docker使用的是Linux的桥接, 宿主机中的docker01是容器间的网桥

    只要删除容器, 对应的网桥一对就没了

    容器间ping时或连接时, 可否直接通过名字连接, 而不是通过固定写死的ip地址, 即若某个容器的ip地址换了, 不修改连接设置, 依然可以进行连接

    可以类比为url的反向解析, 不是直接写死url, 而是给url一个名字, 通过访问名字来访问url, 即使该名字对应的url地址发生了变化, 通过名字也依然可以访问到变化后的url地址

    直接使用容器名称, 在容器01中ping容器02, 发生报错

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat01 ping tomcat02
    ping: tomcat02: Name or service not known
    

    通过--link可以解决这个问题

    再启动一个容器 tomcat03, 使用 --link 连接 tomcat01

    docker run -d -P --name tomcat03 --link tomcat01 tomcat 
    

    进入tomcat03容器中, 直接使用ping tomcat01, 可以ping通

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat03 ping tomcat01
    PING tomcat01 (172.17.0.2) 56(84) bytes of data.
    64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.113 ms
    64 bytes from tomcat01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.072 ms
    64 bytes from tomcat01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.073 ms
    ^C
    --- tomcat01 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 72ms
    rtt min/avg/max/mdev = 0.072/0.086/0.113/0.019 ms
    

    但是反向在 tomcat01 容器中, 直接使用ping tomcat03, 却不能ping通

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat01 ping tomcat03
    ping: tomcat03: Name or service not known
    

    查看tomcat03容器信息, 可以看到 Links 属性, 连接了tomcat01

    docker inspect tomcat03
    # 在输出结果中可以看到 Links 属性, 连接了tomcat01
    "Links": [
    	"/tomcat01:/tomcat03/tomcat01"
    ],
    

    查看tomcat03的/etc/hosts文件也可以看到关联了tomcat01, 这就是--link的实质操作, 在host中添加一个连接信息

    (root@Aliyun-Alex:/home/alex)# 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.17.0.2      tomcat01 db68ef67ca80
    172.17.0.4      340afdc0bb53
    

    但是现在官方已经不建议使用 --link了, 更加高级的做法是使用自定义网络

    自定义网络

    查看所有docker网络docker network ls

    (root@Aliyun-Alex:/home/alex)# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    35b249810e67        bridge              bridge              local
    de155dd42929        host                host                local
    c8ffb814685e        none                null                local
    

    网络连接模式

    • bridge(桥接模式): docker0就是docker容器间的桥梁
    • none: 不配置网络
    • host: 和宿主机共享网络

    当直接启动容器时, 默认使用的一个参数是 --net bridge, 这个bridge就是docker0网卡

    docker run -d -P tomcat
    # 即为
    docker run -d -P --net bridge tomcat
    

    我们可以不使用bridge(docker0) ,而是自己创建一个网络

    创建网络

    # --driver bridge 网络连接模式, 默认为bridge, 因此这里也可以不写这个参数
    # --subnet 子网
    # --getway 网关
    docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
    # 查看网络
    docker network ls
    # 结果多了mynet
    NETWORK ID          NAME                DRIVER              SCOPE
    35b249810e67        bridge              bridge              local
    de155dd42929        host                host                local
    8e7819b11d29        mynet               bridge              local
    c8ffb814685e        none                null                local
    

    查看mynet具体网络信息

    (root@Aliyun-Alex:/home/alex)# docker network inspect mynet
    [
        {
            "Name": "mynet",
            "Id": "8e7819b11d292e30e36a38095dc4b30f310affc9841b4500f5851c670a7f9b48",
            "Created": "2020-07-30T17:41:46.204861397+08:00",
            "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": {}
        }
    ]
    
    

    使用自定义网络, 启动容器

    启动两个容器 tomcat01 和 tomcat02

    docker run -d -P --name tomcat01 --net mynet tomcat
    docker run -d -P --name tomcat02 --net mynet tomcat
    

    再次查看mynet具体网络信息, 可以看到关联的容器

    (root@Aliyun-Alex:/home/alex)# docker network inspect mynet 
    
                        "Subnet": "192.168.0.0/16",
                        "Gateway": "192.168.0.1"
                    }
                ]
            },
            "Internal": false,
            "Attachable": false,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {
                "282a1cd78979de4afcfb24b10fd9c322e21f1eb01879cf5e02918a7dfc9945a4": {
                    "Name": "tomcat01",
                    "EndpointID": "2eccabd1b12d555cdbc4fd0a66e9618a3f0df40f6dd7199c94f01caa2b6c1d15",
                    "MacAddress": "02:42:c0:a8:00:02",
                    "IPv4Address": "192.168.0.2/16",
                    "IPv6Address": ""
                },
                "680e66da888e5c18cff7aae19f51c5189127405a54547925f4482b955a604e79": {
                    "Name": "tomcat02",
                    "EndpointID": "7ce54ee89ba6332ce67920ba687c9af83ba1fd5407aca4e91fcf9e5c23cb5959",
                    "MacAddress": "02:42:c0:a8:00:03",
                    "IPv4Address": "192.168.0.3/16",
                    "IPv6Address": ""
                }
            },
            "Options": {},
            "Labels": {}
        }
    ]
    

    容器间使用容器名相互ping通

    之前使用容器名来ping是ping不同的, 且就算使用了--link也只能单向使用容器名ping通

    现在双向都使用容器名ping通试试看

    • 在容器 tomcat01 中ping 容器 tomcat02, 发现可以ping通
    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat01 ping tomcat02
    PING tomcat02 (192.168.0.3) 56(84) bytes of data.
    64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.118 ms
    64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.076 ms
    64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.093 ms
    ^C
    --- tomcat02 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 8ms
    rtt min/avg/max/mdev = 0.076/0.095/0.118/0.020 ms
    
    • 在容器 tomcat02 中ping 容器 tomcat01, 发现也可以ping通
    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping tomcat01
    PING tomcat01 (192.168.0.2) 56(84) bytes of data.
    64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.101 ms
    64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.095 ms
    ^C
    --- tomcat01 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 3ms
    rtt min/avg/max/mdev = 0.095/0.098/0.101/0.003 ms
    

    发现通过自定义网络比docker0使用起来更加方便, 推荐使用自定义网络

    网络连通

    在前面的步骤中, mynet网络上连接了两个容器, 分别是tomcat01和tomcat02, 他们的网段是192.168.0.0

    我们现在使用默认的网络docker0再创建两个容器tomcat03和tomcat04, 他们的网段是172.17.0.0

    docker run -d -P --name tomcat03 tomcat
    docker run -d -P --name tomcat04 tomcat
    

    现在的网络结构如下:

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping tomcat03
    ping: tomcat03: Name or service not known
    

    直接尝试连接, 发现tomcat02并不能ping通03

    但是我们可以做一个操作, 如果将tomcat02能与Docker0连接, 那么就能和tomcat03和tomcat04连接

    docker network命令中有一个connect命令

    docker network --help
    # 打印结果
    Usage:  docker network COMMAND
    
    Manage networks
    
    Commands:
      connect     Connect a container to a network
      create      Create a network
      disconnect  Disconnect a container from a network
      inspect     Display detailed information on one or more networks
      ls          List networks
      prune       Remove all unused networks
      rm          Remove one or more networks
    
    Run 'docker network COMMAND --help' for more information on a command.
    

    这个命令可以将一个网络连接入一个容器中

    (root@Aliyun-Alex:/home/alex)# docker network connect --help
    
    Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
    
    Connect a container to a network
    
    Options:
          --alias strings           Add network-scoped alias for the container
          --driver-opt strings      driver options for the network
          --ip string               IPv4 address (e.g., 172.30.100.104)
          --ip6 string              IPv6 address (e.g., 2001:db8::33)
          --link list               Add link to another container
          --link-local-ip strings   Add a link-local address for the container
    

    将网络docker0连接容器tomcat02

    docker network connect bridge tomcat02
    

    查看tomcat02的信息, 找到网络属性, 发现该容器有两个网络属性(mynetbridge)和两个IP(192.168.0.3172.17.0.4)

    docker inspect tomcat02
    # 打印结果
    "bridge": {                                                                                                            
        ...
        "NetworkID": "35b249810e679e94e48b0dce387ad422fe4241c3335f82355cf919a56d96bc0c",                                   
        "EndpointID": "cf79813e3322df01cd9e693a0e42d803a26d0f2bf29762e82c5d28c9fa900710",
        "Gateway": "172.17.0.1",
        "IPAddress": "172.17.0.4",
        ...
    },
    "mynet": {
        ...
        "NetworkID": "8e7819b11d292e30e36a38095dc4b30f310affc9841b4500f5851c670a7f9b48",
        "EndpointID": "7ce54ee89ba6332ce67920ba687c9af83ba1fd5407aca4e91fcf9e5c23cb5959",
        "Gateway": "192.168.0.1",
        "IPAddress": "192.168.0.3",
        ...
    }
    

    或者查看网络 docker0 的信息, 可以看到有三个容器连接上了, tomcat02/tomcat03/tomcat04

    docker inspect bridge
    # 打印结果
    "Containers": {                                                                                                                
            "1152c9fa07e21798589e2f36de0dc9529b104b65f95fe4749b54b557cf51fa0c": {                                                   
                "Name": "tomcat03",
                ...
                "IPv4Address": "172.17.0.2/16",
    	},
        "680e66da888e5c18cff7aae19f51c5189127405a54547925f4482b955a604e79": {
            "Name": "tomcat02",
            ...
            "IPv4Address": "172.17.0.4/16",
    	},
        "daf280a8066191e42a4e80168ecb0bc285e9ef92a01723c3d862a0b18b2d38f8": {
            "Name": "tomcat04",
            ...
            "IPv4Address": "172.17.0.3/16",
    	}
    }
    

    此时网络结构如下:

    现在测试tomcat02去ping容器tomcat03或者tomcat04

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping tomcat03
    ping: tomcat03: Name or service not known
    

    发现依然ping不通, 回想一下, 想起了之前说过了Docker0这个网卡默认情况不支持直接通过容器名去ping

    那么测试用tomcat02去ping容器tomcat03的IP地址172.17.0.2或者tomcat04的IP地址172.17.0.3, 发现可以ping通

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping 172.17.0.3
    PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
    64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.134 ms
    64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.080 ms
    ^C
    --- 172.17.0.3 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 48ms
    rtt min/avg/max/mdev = 0.080/0.107/0.134/0.027 ms
    

    那么反过来, 我们将tomcat03连接到mynet网络下, 在自定义的网络中, 是可以实现通过容器名去ping的

    docker network connect mynet tomcat03
    

    现在网络结构如下:

    在测试用tomcat03去ping容器tomcat01, 发现可以ping通

    (root@Aliyun-Alex:/home/alex)# docker exec -it tomcat03 ping tomcat01
    PING tomcat01 (192.168.0.2) 56(84) bytes of data.
    64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.112 ms
    64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.091 ms
    ^C
    --- tomcat01 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 2ms
    rtt min/avg/max/mdev = 0.091/0.101/0.112/0.014 ms
    

    那么结论就是:

    想要不同网段的容器间连接, 需要通过docker network connect network_name docker_name将容器加入到目标网络中即可, 且目标网络最好是自定义的网络, 在自定义的网络中才能直接使用容器名ping通, 而默认的网络docker0(bridge)中只能使用IP地址ping通

  • 相关阅读:
    sqlilab less19-less22
    sqlilab less11-less18
    逆向——序列号相关总结
    xctf攻防世界——crackme writeup
    ESP定律脱壳——NsPack3.x脱壳
    避免全局变量漫天飞
    C语言实现队列
    STM32中的C语言知识点
    超时事件时间戳
    STM32-电源控制、低功耗模式
  • 原文地址:https://www.cnblogs.com/gcxblogs/p/13410600.html
Copyright © 2020-2023  润新知