zoukankan      html  css  js  c++  java
  • Docker 网络

    个人学习笔记,谢绝转载!!!
    原文:https://www.cnblogs.com/wshenjin/p/9720067.html


    docker的几种原生网络模式

    • host:该模式下,容器将不会虚拟出自己的网卡,配置自己的IP等,而是共享 Docker host 的网络栈,容器的网络配置与 Docker host 完全一样
    • None:该模式关闭了容器的网络功能,除了 lo,没有其他任何网卡。
    • Bridge:该模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。

    以上三种网络模式,在docker服启动时就有无需手动创建

    [root@Docker_Machine_192.168.31.130 ~]# docker network ls
    NETWORK ID          NAME                        DRIVER              SCOPE
    82c93f2e5beb        bridge                      bridge              local
    4af713fd5747        host                        host                local
    826a79dc0dc7        none                        null                local
    

    Bridge模式

    bridge模式是docker服务自带的,该模式下,连在同一网桥上的容器可以相互通信,这里讲讲与外部的通信

    与外部的通信,其实是借助宿主机的转发实现的:

    宿主机的Iptable规则有这么几条规则:

    *nat
    -A POSTROUTING -s 172.18.0.0/16 ! -o docker0 -j MASQUERADE
    

    这条规则会将源地址为172.17.0.0/16的包(也就是从Docker容器产生的包),并且不是从docker0网卡发出的,进行源地址转换,转换成主机网卡的地址。

    自定义网络

    除了 Host、None、Bridge 这三个自动创建的网络,也可以根据业务需要创建 user-defined 网络。

    在user-defined 网络模式下,我们可以使用任何docker支持的第三方网络driver来定制容器的网络。而基于bridge driver的网络,docker会自动为其创建iptables规则,保证与其他网络之间、与docker0之间的网络隔离。

    Docker 提供三种 user-defined 网络驱动:bridge, overlay 和 macvlan。overlay 和 macvlan 用于创建跨主机的网络。

    创建bridge

    [root@Docker_Machine_192.168.31.130 ~]# docker network create --driver bridge --gateway 192.168.1.1 --subnet 192.168.1.0/24 net_bridge_192.168.1.0/24    
    4e16d60bb7c39e245268b56b3f54968e37f6f75dea0c94227eb363d772425ace
    

    --driver bridge:创建bridge类型的网络,默认

    --gateway 192.168.1.1:网关IP

    --subnet 192.168.1.0/24:指定网段

    [root@Docker_Machine_192.168.31.130 ~]# docker network ls
    NETWORK ID          NAME                        DRIVER              SCOPE
    5def56a9fbe1        bridge                      bridge              local
    4af713fd5747        host                        host                local
    4e16d60bb7c3        net_bridge_192.168.1.0/24   bridge              local
    826a79dc0dc7        none                        null                local
    [root@Docker_Machine_192.168.31.130 ~]# docker network inspect net_bridge_192.168.1.0/24 
    [{
        "Name": "net_bridge_192.168.1.0/24",
        "Id": "4e16d60bb7c39e245268b56b3f54968e37f6f75dea0c94227eb363d772425ace",
        "Created": "2018-09-28T14:25:32.567131021+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.1.0/24",
                    "Gateway": "192.168.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }]
    

    用brctl show看一下:

    [root@Docker_Machine_192.168.31.130 ~]# brctl  show 
    bridge name     bridge id               STP enabled     interfaces
    br-4e16d60bb7c3         8000.0242b3c8e7e3       no
    docker0         8000.02429152de4e       no
    

    从brctl show的结果来看,新建的bridge name就是br-[bridge id]:br-4e16d60bb7c3

    用创建好的bridge启一个容器

    [root@Docker_Machine_192.168.31.130 ~]# docker run -tid --network=net_bridge_192.168.1.0/24 --ip 192.168.1.2 --name=busybox_192.168.1.20 busybox
    983b254119c1d4789cf270843264b864cdb6de4e4f2ca226fb4e7c0efb7f9dfa
    

    --network=net_bridge_192.168.1.0/24 :指定使用的网络

    --ip 192.168.1.2 :指定IP地址

    只有使用 --subnet 创建的网络才能指定静态 IP,否则容器实例在重启之后,IP地址会改变

    这时候,查看一下新建的bridge的信息:

    [root@Docker_Machine_192.168.31.130 ~]# docker network  inspect net_bridge_192.168.1.0/24 
    [{
        "Name": "net_bridge_192.168.1.0/24",
        "Id": "4e16d60bb7c39e245268b56b3f54968e37f6f75dea0c94227eb363d772425ace",
        "Created": "2018-09-28T14:25:32.567131021+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.1.0/24",
                    "Gateway": "192.168.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "983b254119c1d4789cf270843264b864cdb6de4e4f2ca226fb4e7c0efb7f9dfa": {
                "Name": "busybox_192.168.1.20",
                "EndpointID": "82911a84c7e2a60fcac7d7a0a9bf7f9d0e27f9cc84a6aa19eb94470908109e1d",
                "MacAddress": "02:42:c0:a8:01:02",
                "IPv4Address": "192.168.1.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }]
    

    Containers 这段已经表明了,容器busybox_192.168.1.20使用了IP192.168.1.2/24

    一个容器实例,跨多个网络

    目前,机器上有两个bridge:

    • docker默认的bridge(172.17.0.0/16)

    • 新建的net_bridge_192.168.1.0/24(192.168.1.0/24)

    由于docker在设计上是隔离了不同的网络,因此两个网络下的容器实例是无法互通的,如下iptables规则:

    -A DOCKER-ISOLATION-STAGE-1 -i br-4e16d60bb7c3 ! -o br-4e16d60bb7c3 -j DOCKER-ISOLATION-STAGE-2
    -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
    -A DOCKER-ISOLATION-STAGE-2 -o br-4e16d60bb7c3 -j DROP
    -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
    

    上面四条规则大概的解释是:从br-4e16d60bb7c3网卡进来并且从docker0出去的数据包,和从docker0网卡进来并且从br-4e16d60bb7c3网卡出去的数据包都被DROP了

    那如何让两个不同网络下的容器实例相互通信呢?可以让容器实例绑定一个另一个网络的网卡:

    #事先创建一个192.168.2.0/24段的网络net_bridge_192.168.2.0/24 
    [root@Docker_Machine_192.168.31.130 ~]# docker network connect net_bridge_192.168.2.0/24 --ip 192.168.2.10 busybox_192.168.1.100
    

    这样,busybox_192.168.1.100 这个实例就有了一个192.168.2.0/24段的IP地址192.168.2.10,也可以直接访问192.168.2.0/24这个段了:

    [root@Docker_Machine_192.168.31.130 ~]# docker exec -ti  busybox_192.168.1.100 sh 
    / # ip ad
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
    32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:c0:a8:01:64 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    38: eth1@if39: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:c0:a8:02:0a brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.10/24 brd 192.168.2.255 scope global eth1
       valid_lft forever preferred_lft forever
    / # ping -c3 192.168.2.100
    PING 192.168.2.100 (192.168.2.100): 56 data bytes
    64 bytes from 192.168.2.100: seq=0 ttl=64 time=0.308 ms
    64 bytes from 192.168.2.100: seq=1 ttl=64 time=0.131 ms
    64 bytes from 192.168.2.100: seq=2 ttl=64 time=0.151 ms
    

    container模式(joined 容器)

    joined 容器是另一种实现容器间通信的方式。

    joined 容器非常特别,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。

    这里起一个192.168.1.0/24段的ngx容器:

    [root@Docker_Machine_192.168.31.130 ~]# docker run -tid 
                                            --network=net_bridge_192.168.1.0/24 
                                            --ip=192.168.1.80 
                                            --name=nginx_test1_192.168.1.80 
                                            -v /data/dokcer/docker_local_volume/nginx_test1_80/conf/:/data/conf/nginx/:ro 
                                            -v /data/dokcer/docker_local_volume/nginx_test1_80/web/:/data/web/ 
                                            -v /data/dokcer/docker_local_volume/nginx_test1_80/logs/:/data/logs/ 
                                            volumes/my_nginx_server:v1.14.0           
    104b9e850a1104b245b837f3d2f2a39f0d0b9afc752dd84ca1e44031f66ecae8
    

    然后创建一个busybox容器,让它join到nginx_test1_192.168.1.80:

    [root@Docker_Machine_192.168.31.130 ~]# docker run -itd --name=ngx_cli --network=container:nginx_test1_192.168.1.80 busybox 
    bc510baba23b1fc314c394da344b96241effb617b45c330c920cf41e6c6145da
    

    --network=container:nginx_test1_192.168.1.80:共享nginx_test1_192.168.1.80容器实例的网络

    [root@Docker_Machine_192.168.31.130 ~]# docker exec -it ngx_cli sh 
    / # ip ad
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
    46: eth0@if47: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
        link/ether 02:42:c0:a8:01:50 brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.80/24 brd 192.168.1.255 scope global eth0
           valid_lft forever preferred_lft forever
    

    他俩共享了同一个网络栈,确实完全独立的容器,可以分别进入容器查看里面的进程

    容器与外部通信

    未完待续...

  • 相关阅读:
    Ansible 日常使用技巧
    Linux下科学计数法(e)转化为数字的方法 [shell中几种数字计算说明]
    业务日志清理脚本
    Kubernetes容器集群
    Kubernetes 之Pod学习
    数据结构之数组
    Java Class 文件中Method的存储
    理解Flink Transformation
    理解Java BlockingQueue
    理解Java FutureTask
  • 原文地址:https://www.cnblogs.com/wshenjin/p/9720067.html
Copyright © 2011-2022 走看看