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
    

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

    容器与外部通信

    未完待续...

  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/wshenjin/p/9720067.html
Copyright © 2011-2022 走看看