Docker网络

  • 基础知识

    Docker容器的本质是 共享内核,资源隔离、资源限制、文件系统rootfs

    Docker网络的实现主要就是如何在共享内核的基础上,实现socket的隔离,虚拟设备的隔离和通信.

    虚拟网络接口

    ​ Linux网络协议栈中,IP层不与物理网络设备(网络驱动)直接通信,而是和抽象的网络接口(lo、eth0、eth1等)交互。这为Docker不同容器中能够模拟网络环境提供的基础。

    • 主机上的通信

      img

      img

    • 虚拟机的通信

      img

    • Docker的通信

      img

    namespase

    ​ Docker是轻量级的虚拟化,他和虚拟机的一个主要区别是不同的Docker容器共享Linux内核。 共享内核就会存在资源可见性的问题。为此,Linux支持为不同资源设置不同的namespace,不同namespace的资源相互隔离、相互不可见。

    img

    veth

    ​ namespace用于实现网络资源的隔离,但是Docker容器与宿主机经常需要进行通信,这就需要Linux系统中veth-pair技术的支持。

    ​ veth是虚拟网络设备接口,它总是成对出现,用于连通两个namespace(容器与容器、容器与宿主机)。从其中一个端口发出的数据包,可以直接出现在与它对应的另一个端口上。

    ​ 查看网络接口:ip link show

    ​ 查看网络信息:ip addrifconfig

    img

    bridge

    ​ Linux网络内核引入网桥bridge来实现多个网络接口之间的通信,可以将一台机器上的若干接口连通起来。在OSI网络模型中,网桥属于数据链路层。

    ​ 查看网桥的连接:bridge link

    img

    路由表

    ​ Linux网络内核通过路由表来指定数据包的转发路径。 一台Linux主机里可能有多个虚拟网络接口、多个物理网络设备,在TCP/IP协议中,IP数据包里包含了目的地址,但是并不知道如何到达目标地址。路由表则用于指示要抵达目的地址,数据包下一条应该先到哪里去。

    ​ 查看路由表:route -n

    Docker的网络模式

    可以通过docker network ls查看网络,默认创建三种网络:bridgehostnone

    ###Docker的几种网络模型

    • bridge: Docker容器有自己的Network-Namesapce,通过veth-pair和Linux-Bridge技术实现容器与宿主机的网络通信。brige模式是Docker的默认网络模式。
    • host: Docker容器与宿主机共享网络,容器不会有自己的Network-Namesapce,与宿主机不进行网络隔离。
    • overlay: 将多个Docker Daemon连接到一起。
    • IPvlan: 用户可以完全控制IPv4和IPv6寻址。支持对二层VLAN tag和三层网络路由的完全控制。
    • macvlan: 支持为容器设置mac地址,让Docker daemon能够基于Mac地址路由流量。
    • none: 这种模式下的容器禁用所有网络。
    • Network plugins: 安装使用第三方的Docker网络插件。

    Bridge模式

    img

    ​ 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上,附加在其上的任何网卡之间都能自动转发数据包。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

    ​ 从docker0子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Dockerveth pair 设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。可以通过brctl show命令查看。

    img

    ###简介

    ​ 同一个宿主机上的多个docker容器之间可以通过使用容器的ip地址来通信,也可以通过宿主机的ip加上容器暴露出的端口号来通信,但是前者会导致ip地址的硬编码,不方便迁移,并且容器重启后ip地址会改变,除非使用固定的ip,而后者的通信方式比较单一,只能依靠监听在暴露出的端口的进程来进行有限的通信。

    ​ 相比之下,docker的link机制可以通过一个name来和另一个容器通信,link机制方便了容器去发现其它的容器并且可以进行一些安全的数据传递.

    ​ 例如:docker run --name wordpress --link mysqldb:mysql -p 8080:80 -d wordpress,其中mysqldb是容器名,mysql是自己起的别名<alias>

    ​ 现在已经不推荐使用 --link了。

    原理

    ​ 使用了link机制后,可以通过指定的名字来和目标容器通信,这通过设置环境变量和修改/etc/hosts文件的ip和容器映射来实现。

    ​ docker会在接收容器(使用--link的容器)中设置名为<alias>_NAME的环境变量,该环境变量的值为:<alias>_NAME=/接收容器名/源容器<alias>

    ​ 另外,docker还会在接收容器中创建关于源容器暴露的端口号的环境变量,这些环境变量有一个统一的前缀名称:

    <name>_PORT_<port>_<protocol> = ***

    ​ (其中:<name>表示链接的源容器alias;<port>是源容器暴露的端口号;<protocol>是通信协议:TCP or UDP)

    ​ 推荐使用自定义网络。

    自定义网络

    查看所有的docker网络–默认开启的

    image-20220718224131129

    实例测试

    • 简介

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      # 我们直接启动的命令 --net bridge,不写的时候也是默认启动docker0模式的网络
      docker run -d -P --name mysql01 mysql
      docker run -d -P --name mysql01 --net bridge mysql

      #docker0 特点:默认、域名不能访问(name 达咩),可以使用 --link 连接
      #高级一点
      #我们可以自定义一个网络 在这个网络中 容器可以直接相互连接
      Usage: docker network create [OPTIONS] NETWORK

      Create a network

      Options:
      --attachable Enable manual container attachment
      --aux-address map Auxiliary IPv4 or IPv6 addresses used by
      Network driver (default map[])
      --config-from string The network from which to copy the configuration
      --config-only Create a configuration only network
      -d, --driver string Driver to manage the Network (default "bridge")
      --gateway strings IPv4 or IPv6 Gateway for the master subnet
      --ingress Create swarm routing-mesh network
      --internal Restrict external access to the network
      --ip-range strings Allocate container ip from a sub-range
      --ipam-driver string IP Address Management Driver (default "default")
      --ipam-opt map Set IPAM driver specific options (default map[])
      --ipv6 Enable IPv6 networking
      --label list Set metadata on a network
      -o, --opt map Set driver specific options (default map[])
      --scope string Control the network's scope
      --subnet strings Subnet in CIDR format that represents a
      network segment

    • 开始创建

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      #--driver bridge 
      #--subnet 10.1.0.0/16 子网
      #192.168.0.0/24代表是A类地址,主机为8位,表示192.168.0固定,后面是可变,掩码为255.255.255.0。
      #192.168.0.0/16代表B类地址,主机为16,表示192.168固定,后面是可用。
      #--gateway 10.1.0.1 网关 路由器地址
      #mynet 自定义网络的名字
      docker network create --driver bridge --subnet 10.1.0.0/16 --gateway 10.1.0.1 mynet
      28859b171621785d1905ce61c4f607e97d7666784ddff53b55d239df915a20ca
      docker network ls
      NETWORK ID NAME DRIVER SCOPE
      bb12db42a612 bridge bridge local
      8a88783267a2 host host local
      28859b171621 mynet bridge local
      dc411ab66580 none null local

      image-20220718225930029

    • 创建容器进行测试

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      [root@io yio]# docker run -d -P --name tomcat-net-01 --net mynet tomcat  
      8d0e68b6f973392b8e4886bee199f94ab2e74a9f85ca11b72c4c3f5d8de021cf
      [root@io yio]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
      19c44acd2ce7ac0bc2783d28fe381d22253aff122afd83975a42e2a85908a45b
      [root@io yio]# docker inspect mynet
      [
      "ConfigOnly": false,
      "Containers": { "19c44acd2ce7ac0bc2783d28fe381d22253aff122afd83975a42e2a85908a45b": {
      "Name": "tomcat-net-02",
      "EndpointID": "aaf25223812cbbebea77884f98c5a167081928006827e09c29e18f477afc3d34",
      "MacAddress": "02:42:0a:01:00:03",
      "IPv4Address": "10.1.0.3/16",
      "IPv6Address": ""
      }, "8d0e68b6f973392b8e4886bee199f94ab2e74a9f85ca11b72c4c3f5d8de021cf": {
      "Name": "tomcat-net-01",
      "EndpointID": "17f7119ef2e9c3de5b655baa7ebe282950ffd8bcf393fe40bfffefcdc4751baf",
      "MacAddress": "02:42:0a:01:00:02",
      "IPv4Address": "10.1.0.2/16",
      "IPv6Address": ""
      }
      },
      "Options": {},
      "Labels": {}
      }
      ]
      [root@io yio] # docker exec -it tomcat-net-01 /bin/bash
      root@8d0e68b6f973:/usr/local/tomcat# apt-get install inetutils-ping
      root@8d0e68b6f973:/usr/local/tomcat# ping 10.1.0.3
      PING 10.1.0.3 (10.1.0.3): 56 data bytes
      64 bytes from 10.1.0.3: icmp_seq=0 ttl=64 time=0.189 ms
      64 bytes from 10.1.0.3: icmp_seq=1 ttl=64 time=0.157 ms
      64 bytes from 10.1.0.3: icmp_seq=2 ttl=64 time=0.091 ms
      64 bytes from 10.1.0.3: icmp_seq=3 ttl=64 time=0.110 ms
      ^C--- 10.1.0.3 ping statistics ---
      20 packets transmitted, 20 packets received, 0% packet loss
      round-trip min/avg/max/stddev = 0.091/0.170/0.250/0.046 ms
      [root@io yio] # docker exec -it tomcat-net-02 /bin/bash
      root@19c44acd2ce7:/usr/local/tomcat# apt-get update && apt-get install inetutils-ping
      root@19c44acd2ce7:/usr/local/tomcat# ping 10.1.0.2
      PING 10.1.0.2 (10.1.0.2): 56 data bytes
      64 bytes from 10.1.0.2: icmp_seq=0 ttl=64 time=0.213 ms
      64 bytes from 10.1.0.2: icmp_seq=1 ttl=64 time=0.147 ms
      64 bytes from 10.1.0.2: icmp_seq=2 ttl=64 time=0.170 ms
      64 bytes from 10.1.0.2: icmp_seq=3 ttl=64 time=0.156 ms
      64 bytes from 10.1.0.2: icmp_seq=4 ttl=64 time=0.197 ms
      ^C--- 10.1.0.2 ping statistics ---
      5 packets transmitted, 5 packets received, 0% packet loss
      round-trip min/avg/max/stddev = 0.147/0.177/0.213/0.025 ms
      # 我们可以直接连接两个容器了,不需要使用--link了
    • 我们自定义的网络docker已经帮我们维护好了对应的关系,推荐这样使用网络。

    网络连通

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@io yio]# 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

    小例子看一下

    • 连接connect

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      [root@io yio]# docker run -d -P --name  tomcat01 tomcat 
      250fb427dea0158f055d8063e6645d2e5be35248f5a81ef819835d8e0f85c488
      [root@io yio]# docker exec -it tomcat01 bash
      root@250fb427dea0:/usr/local/tomcat# apt-get update
      root@250fb427dea0:/usr/local/tomcat# apt-get install inetutils-ping
      root@250fb427dea0:/usr/local/tomcat# ping 10.1.0.2
      PING 10.1.0.2 (10.1.0.2): 56 data bytes
      ^C--- 10.1.0.2 ping statistics ---
      9 packets transmitted, 0 packets received, 100% packet loss
      #进行连通
      [root@io yio]# docker network connect mynet tomcat01
      [root@io yio]# docker exec -it tomcat01 ping 10.1.0.2
      PING 10.1.0.2 (10.1.0.2): 56 data bytes
      64 bytes from 10.1.0.2: icmp_seq=0 ttl=64 time=0.172 ms
      64 bytes from 10.1.0.2: icmp_seq=1 ttl=64 time=0.250 ms
      64 bytes from 10.1.0.2: icmp_seq=2 ttl=64 time=0.148 ms
      ^C--- 10.1.0.2 ping statistics ---
      3 packets transmitted, 3 packets received, 0% packet loss
      round-trip min/avg/max/stddev = 0.148/0.190/0.250/0.044 ms
      #看一下自定义的网络
      [root@io yio]# docker inspect mynet
      [
      "Containers": {
      "19c44acd2ce7ac0bc2783d28fe381d22253aff122afd83975a42e2a85908a45b": {
      "Name": "tomcat-net-02",
      "EndpointID": "aaf25223812cbbebea77884f98c5a167081928006827e09c29e18f477afc3d34",
      "MacAddress": "02:42:0a:01:00:03",
      "IPv4Address": "10.1.0.3/16",
      "IPv6Address": ""
      },
      "250fb427dea0158f055d8063e6645d2e5be35248f5a81ef819835d8e0f85c488": {
      "Name": "tomcat01",
      "EndpointID": "0d0d279a755b1cac495682256f6bfdd913db35ebe5bdf8e30e800c701a25e506",
      "MacAddress": "02:42:0a:01:00:04",
      "IPv4Address": "10.1.0.4/16",
      "IPv6Address": ""
      },
      "8d0e68b6f973392b8e4886bee199f94ab2e74a9f85ca11b72c4c3f5d8de021cf": {
      "Name": "tomcat-net-01",
      "EndpointID": "17f7119ef2e9c3de5b655baa7ebe282950ffd8bcf393fe40bfffefcdc4751baf",
      "MacAddress": "02:42:0a:01:00:02",
      "IPv4Address": "10.1.0.2/16",
      "IPv6Address": ""
      }
      },
      "Options": {},
      "Labels": {}
      }
      ]
    • 查看ip网络

      ip addr

      image-20220718234105155

    • 再加一个容器

      1
      2
      3
      4
      [root@io yio]# docker run -d -P --name tomcat02 tomcat  
      e561099a4ce4d540c1e46ab3c8537c0c05132fc2b57b7debc57e2b22e15162e5
      #查看ip
      [root@io yio]# ip addr

      image-20220718234402463

      我们可以看到多了一对veth-pair

    • 再将该容器接入mynet,查看ip

      1
      2
      [root@io yio]# docker network connect mynet tomcat02
      [root@io yio]# ip addr

      image-20220718234613363

      看啊,他又多了一对。这相当于一个容器有了两个ip,就好像阿里云的一个公网ip,一个私网ip

    • 如果要跨网络操作别的容器,就需要使用docker network connect连通!!😯

    参考

    作者: Meow Mii

    本文链接: https://blog.yiochin.top/p/3849e8ae.html

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议,转载请注明出处!


    📝 Comment