array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 Docker网络(五)--技术流ken - 爱码网
kenken2018

 

本章内容

 

1.dokcer默认自带的几种网络介绍

2. 自定义网络

3. 容器间通信

4. 容器与外界交互

docker网络分为单个主机上的容器网络和多个主机上的哇网络,本文主要讲解单个主机上的容器网络。

 

1. dokcer默认自带的几种网络介绍

 

一、none

二、host

三、bridge

 

可以使用如下命令进行查看

[root@ken1 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
d8cf2efc8881        bridge              bridge              local
2fb7c9abfab5        host                host                local
d300d17755a4        none                null                local

 

一、none网络

none网络没有网络,只有lo即本地地址,没有任何的网卡。创建容器时可以使用--network=none来指定none网络:

[root@ken1 ~]# docker run --network=none -it busybox
/ # ip a
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

none网络的应用场景主要是用于对于安全性要求比较高的场景。

 

二、host网络

连接到host的网络的容器共享主机的网络栈,容器的网络配置与宿主机完全一样,创建容器时可以通过--network=host指定使用host网络:

[root@ken1 ~]# docker run --network=host -it busybox
/ # ip a
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:0c:29:2d:5b:b8 brd ff:ff:ff:ff:ff:ff
    inet 172.20.10.2/24 brd 172.20.10.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2408:84e1:41:da2a:20c:29ff:fe2d:5bb8/64 scope global dynamic 
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe2d:5bb8/64 scope link 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue qlen 1000
    link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 qlen 1000
    link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:59:83:33:89 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:59ff:fe83:3389/64 scope link 
       valid_lft forever preferred_lft forever
35: vetha2d50be@if34: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether 3e:ba:6b:44:3a:e6 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::3cba:6bff:fe44:3ae6/64 scope link 
       valid_lft forever preferred_lft forever

并且hostname也是宿主机的

/ # hostname
ken1

直接使用主机的网络最大的好处就是性能,如果容器对网络传输效率有较高的要求,则可以选择宿主机的网络。但是需要考虑端口冲突的问题,宿主机已经使用的端口就不能再用了。

 

三、bridge网络

docker安装时会创建一个docker0的linux brdge。如果不指定--network,创建的容器more都会挂到docker0上:

[root@ken1 ~]# brctl show 
bridge name    bridge id        STP enabled    interfaces
docker0        8000.024259833389    no        
virbr0        8000.525400da7083    yes        virbr0-nic

当前的docker0上interfaces处没有任何其他的网络设备,我们创建一个容器看看有什么变化:

[root@ken1 ~]# docker run -it busybox
/ #

[root@ken1 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024259833389 no vethca1bd59
virbr0 8000.525400da7083 yes virbr0-nic

再来看一下网卡信息

[root@ken1 ~]# ip a
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether 00:0c:29:2d:5b:b8 brd ff:ff:ff:ff:ff:ff
    inet 172.20.10.2/24 brd 172.20.10.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 2408:84e1:41:da2a:20c:29ff:fe2d:5bb8/64 scope global mngtmpaddr dynamic 
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe2d:5bb8/64 scope link 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:59:83:33:89 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:59ff:fe83:3389/64 scope link 
       valid_lft forever preferred_lft forever
41: vethca1bd59@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether ca:82:1f:2a:2a:3d brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::c882:1fff:fe2a:2a3d/64 scope link 
       valid_lft forever preferred_lft forever

使用ip a可以发现我们每启动一个容器相关的网卡信息也都会显示出来。

 

我们启动了一个容器,产生了一个新的网络接口vethca1bd59被挂到了docker0上,vethca1bd59就是新创建容器的虚拟网卡。下面看一下容器的网络配置:

[root@ken1 ~]# docker run -it busybox
/ # 
/ # ip a
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
40: eth0@if41: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

容器有一个网卡eth0@if41,实际上eth0@if41和vethccd6a69是一对veth pair。veth pair是一种成对出现的椰树网络设备,可以把它想象成一根虚拟网线连接起来的一对网卡,网卡的一头(eth0@if41)在容器中,另一头(vethca1bd59)挂在docker0上,其效果就是将eth0@if41也挂在了docker0上。

可以看到eth0@if41已经配置开了IP 172.17.0.3,那为什么会是这个网段那?可以通过如下的命令查看网络的配置信息:

[root@ken1 ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "d8cf2efc88817902c3a1c8fff7adb22194ee3c78a427bda5b0543987c1db1bd7",
        "Created": "2019-01-26T20:27:17.164824695+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
...

原来beidge网络配置的subnet就是172.17.0.0/16,并且网关是172.17.0.1,其实这个网关就是docker0. 

容器创建时,docker会自动从172.17.0.0/16中分配一个IP。

 

2. 自定义网络

 

除了none,host,bridge这三个自动创建的网络,用户也可以根据业务需要创建 user-defined 网络。

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

我们可通过 bridge 驱动创建类似前面默认的 bridge 网络,例如:

新增了一个网桥 br-e2e6bf5189a6,这里 br-e2e6bf5189a6 正好新建 bridge 网络ken 的短 id。执行 docker network inspect 查看一下 my_net 的配置信息:

这里 172.19.0.0/16 是 Docker 自动分配的 IP 网段。

我们可以自己指定 IP 网段吗?
答案是:可以。

只需在创建网段时指定 --subnet 和 --gateway 参数:

[root@ken1 ~]# docker network  create --driver bridge --subnet 172.21.0.0/16 --gateway 172.21.0.1 ken3
504f7cd9a219ebad812a673f86fef67b2e5d20fd388a56854d055f807cb415e3

查看网络

 

容器要使用新的网络,需要在启动时通过 --network 指定:

 

到目前为止,容器的 IP 都是 docker 自动从 subnet 中分配,我们能否指定一个静态 IP 呢?

答案是:可以,通过--ip指定。

注:只有使用 --subnet 创建的网络才能指定静态 IP

 

3. 容器间通信

 

容器之间可通过 IP,Docker DNS Server 或 joined 容器三种方式通信。

 

我们接下来启动两个容器并且指定同一个网络验证是否可以通信:

可见同一网络中的容器、网关之间都是可以通信的。

 

再ping一个不是同一个网段 的容器:

显然是不能通信的,那如何实现不同网段之间的容器间的通信那?

答案是:为 另外一个 容器添加一块 ken3的网卡。这个可以通过docker network connect 命令实现。

[root@ken1 ~]# docker network connect ken3 dc4c1258f267

查看网络信息

容器中增加了一块网卡eth1,分配了ken3的IP,现在两个容器之间就可以访问了。 

 

从上面的列子可以得出这样一个结论:两个容器要能通信,必须要有属于同一个网络的网卡。

满足这个条件后,容器就可以通过 IP 交互了。具体做法是在容器创建时通过 --network 指定相应的网络,或者通过 docker network connect 将现有容器加入到指定网络。

 

Docker DNS Server

通过 IP 访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定 IP,部署之后再指定要访问的 IP 会比较麻烦。对于这个问题,可以通过 docker 自带的 DNS 服务解决。

从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。方法很简单,只要在启动时用 --name 为容器命名就可以了。

 

使用 docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的。下面验证一下:

 

joined容器

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

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

先创建一个 busybox 容器,名字为 web1。

[root@ken1 ~]# docker run --rm -it --name=web1 busybox
/ # 

查看信息

 

然后创建 busybox 容器并通过 --network=container:web1 指定 jointed 容器为 web1:

 

 看!busybox 和 web1 的网卡 mac 地址与 IP 完全一样,它们共享了相同的网络栈。busybox 可以直接用 127.0.0.1 访问 web1。

 

joined 容器非常适合以下场景:

  1. 不同容器中的程序希望通过 loopback 高效快速地通信,比如 web server 与 app server。

  2. 希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序。

 

4. 容器与外界交互

 

容器访问外部世界:

只要宿主机可以访问外网,默认容器是可以访问外网的:

外部世界访问容器:

即端口映射详情参考我之前的文章《Docker端口映射及创建镜像演示(二)--技术流ken

分类:

技术点:

Docker

相关文章:

  • 2019-02-20
  • 2019-02-21
  • 2019-02-18
  • 2019-02-18
  • 2019-02-19
  • 2019-01-30
  • 2018-11-26
  • 2019-01-23
猜你喜欢
  • 2019-03-11
  • 2019-02-11
  • 2019-01-31
  • 2019-02-10
  • 2019-02-12
  • 2019-02-17
  • 2020-05-24
相关资源
相似解决方案