Docker 网络

Posted wshenjin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker 网络相关的知识,希望对你有一定的参考价值。

docker的几种原生网络模式

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

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

[[email protected]_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 网络。

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

创建bridge
[[email protected]_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:指定网段

[[email protected]_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
[[email protected]_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看一下:

[[email protected]_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启一个容器
[[email protected]_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的信息:

[[email protected]_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在设计上是隔离了不同的网络,因此两个网络下的容器实例是无法互通的

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

#事先创建一个192.168.2.0/24段的网络net_bridge_192.168.2.0/24 
[[email protected]_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这个段了:

[[email protected]_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: [email protected]: <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: [email protected]: <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
joined 容器

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

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

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

[[email protected]_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:

[[email protected]_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容器实例的网络

[[email protected]_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: [email protected]: <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

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

容器与外部通信

未完待续...

以上是关于Docker 网络的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装

markdown [Docker] Docker片段列表和命令#linux #docker #snippets

markdown docker-compose片段

sh Docker片段

《Docker 源码分析》全球首发啦!