作者:杨冬 欢迎转载,也请保留这段声明。谢谢!

出处: https://andyyoung01.github.io/http://andyyoung01.16mb.com/

本篇文章主要探索Docker的单机容器网络,了解一下单个Docker主机上网络的各种模式,从而为后续理解跨主机容器网络打下基础。

Docker默认容器网络的建立和控制是一种结合了network namespace,iptables,Linux网桥及route table等多种技术的综合解决方案,本篇主要针对于如何使用单主机网络的各种模式,对于实现细节不做过多的探索(这篇文章 http://tonybai.com/2016/01/15/understanding-container-networking-on-single-host/ 对于docker单主机网络的实现机制做了详细的探索)。

Docker的网络模式

Docker支持的网络模式主要有如下几种:

None

启动容器时,使用了参数 --network="none" 。在此种模式下,容器和外部网络没有连接。在容器中只有loopback的网络接口,但它没有对外的任何路由。

Bridge

启动容器时,使用了参数 --network="bridge" 或者未指定此参数。这是docker默认的网络模式。它允许此主机上的容器彼此进行通信,也允许容器访问主机的外部网络。下图显示了Docker bridge网络的示意图:

在主机上,docker创建了一个通常名为docker0的网桥,这里它的ip设置为172.17.0.1.在创建每个容器时,同时创建了一对veth网络接口。接口的一端连接到docker0的网桥上,另一端连接到容器的内部。从容器发起的到外部网络的连接是通过IP forwarding和设置了NAT规则的iptables rules实现的(图中的绿色箭头)。从外部网络到容器内部的连接使用了一条完全不同的路径。如果容器将自身的端口映射到主机上,则docker会启动一个docker-proxy进程来进行监听,通过此proxy将数据转发到容器中(图中的红色箭头)。

默认情况下,同一台docker主机上的容器彼此之间可以通过他们的IP地址进行通信。如果需要通过容器的主机名进行通信,容器之间必须设置了link。

Host

启动容器时,使用了参数 --network="host" 。在这种模式下,容器共享主机的networking namespace,所以主机上的网络接口对容器都可用,同时在bridge模式下docker所做的各种网络设置都被略过,这意味着容器的网络性能和普通的主机网络性能 一样快 。在运行一些对网络性能要求较高的应用时,如负载均衡器或高性能web服务器时,应使用此模式。

但此模式给予容器对本地系统服务的完全访问权限,所以比其它模式的安全性要差。

Container

启动容器时,使用了参数 --network="container:<name|id>" 。这种模式下容器使用了另外一个容器的networking namespace,也就是说它与另外一个容器共享网络栈。

User-defined network

在这种模式下,用户可以使用Docker网络驱动或外部网络驱动plugin来创建自定义的网络。用户可以将多个容器连接到同一个网络上。一旦容器连接到用户自定义的网络后,容器可以使用另外一个容器的ip地址 或名称 来彼此通信。此功能需要Docker 1.10之后的版本。在较新版本的docker daemon中内置了一个DNS服务器,对于任意在创建时指定了name或net-alias或通过link提供了别名的容器,它可以提供内置的 服务发现功能 ,从而无需再使用第三方软件提供的DNS服务(无需再使用文章“ 使用resolvable通过DNS查找容器 ”中提供的方法)。

对于overlay网络或使用了支持多主机连接的插件的容器,连接到同一多主机网络但从不同主机上启动的容器也可以彼此之间以这种方式通信。

Docker的network命令

Docker的network命令既可以用于单主机网络的相关操作,也可以用于多主机overlay网络的操作,本篇主要使用其与单主机网络相关的命令。

创建网络

当在主机上安装docker后,docker引擎自动创建三个网络,可用如下命令列出默认的三个网络:

[yangdong@centos7 ~]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
2a820cde1d0c bridge bridge local
54be0bc791bf host host local
8488a8a4ca59 none null local

除此之外,用户还可以创建自己的bridge或overlay的网络。如果运行 docker network create 命令并且指定一个网络名称,则此命令为用户创建一个bridge网络:

[yangdong@centos7 ~]$ docker network create simple-network
a88875cc258fb24bbf55db67efefd05976dc8d1a8e25a2166a1acbd1dc9e125a
[yangdong@centos7 ~]$ docker network inspect simple-network
[
{
"Name": "simple-network",
"Id": "a88875cc258fb24bbf55db67efefd05976dc8d1a8e25a2166a1acbd1dc9e125a",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1/16"
}
]
},
"Internal": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]

连接容器

可以将容器动态得连接到一个或多个网络上。一旦连接后,容器可以通过其它容器的ip地址或名称进行通信。下面看一下例子:

首先创建两个容器:

[yangdong@centos7 ~]$ docker run -itd --name=container1 busybox
bdaadbef1c5b3a53c1cf54ddda70e170e386fc578c815f07b09d21ca2fcd3b20
[yangdong@centos7 ~]$ docker run -itd --name=container2 busybox
126cf3af1ddd033a0925ca879e8d744293cb95949d560877ca630a29b4630630

然后创建一个隔离的bridge的网络用于测试:

[yangdong@centos7 ~]$ docker network create -d bridge --subnet 172.25.0.0/16 isolated_nw
38159357c0979fdbc6ca0be29475867115e002ef27d8f79fee014b03ffd86b8d

这里通过命令行参数 --subnet 指定了容器使用的子网网段。下面将container2连接到刚才创建的网络上:

[yangdong@centos7 ~]$ docker network connect isolated_nw container2

然后启动第三个容器,在启动的同时将其连接到isolated_nw网络上,同时手动指定该容器的ip:

[yangdong@centos7 ~]$ docker run --network=isolated_nw --ip=172.25.3.3 -itd --name=container3 busybox
d649491fd218c65fb0dc26aa79cb0d6f43dabac2bdc2f404c515f97042e60206

只要容器连接到一个由用户指定子网网段(通过 --subnet )的网络上时,就可以为容器指定ip地址。

上述命令运行完毕后,整个主机上的网络状态如下图所示:

使用docker attach命令连接到运行的container2容器内部并查看其网络栈:

[yangdong@centos7 ~]$ docker attach container2
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:05
inet addr:172.17.0.5 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:9 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:718 (718.0 B) TX bytes:648 (648.0 B) eth1 Link encap:Ethernet HWaddr 02:42:AC:19:00:02
inet addr:172.25.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe19:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:32 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3282 (3.2 KiB) TX bytes:648 (648.0 B) lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

可见eth0连接到了默认的bridge网络,eth1连接到了用户创建的isolated_nw网络,此网络可以通过docker内置的DNS服务器进行其它容器的名称解析,所以在container2中可以通过名称ping通container3:

/ # ping -w 4 container3
PING container3 (172.25.3.3): 56 data bytes
64 bytes from 172.25.3.3: seq=0 ttl=64 time=0.146 ms
64 bytes from 172.25.3.3: seq=1 ttl=64 time=0.113 ms
64 bytes from 172.25.3.3: seq=2 ttl=64 time=0.100 ms
64 bytes from 172.25.3.3: seq=3 ttl=64 time=0.112 ms --- container3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.100/0.117/0.146 ms

然而在默认的bridge网络中,并不是这样。在默认的bridge网络中,Docker并不支持自动的服务发现:

/ #  ping -w 4 container1
ping: bad address 'container1'

在默认的bridge网络中,可以使用传统的 docker run --link 命令来启用通过名称的解析。当然,在没有使用 --link 时,可以通过彼此的ip地址进行通信。

退出container2的终端,使用快捷键CTRL-p然后CTRL-q。

在这个示例当中,container2连接到了两个网络上,所以它可以与container1和container3通信。但container1和container3并不在一个网络当中所以它们之间并不能通信。下面连接到container3的控制台然后测试一下(container1的ip为172.17.0.4):

[yangdong@centos7 ~]$ docker attach container3
/ # ping 172.17.0.4
PING 172.17.0.2 (172.17.0.2): 56 data bytes
^C
--- 172.17.0.2 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss

断开容器连接

用户可以通过 docker network disconnect 命令断开容器到某个网络的连接,当断开此连接后,容器就不能通过此网络与其它容器通信了:

[yangdong@centos7 ~]$ docker network disconnect isolated_nw container2
[yangdong@centos7 ~]$ docker attach container2
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:05
inet addr:172.17.0.5 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1222 (1.1 KiB) TX bytes:1152 (1.1 KiB) lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:922 (922.0 B) TX bytes:922 (922.0 B)
/ # ping container3
ping: bad address 'container3'

移除一个网络

当一个网络中所有的容器都停止或断开连接后,可以移除该网络:

[yangdong@centos7 ~]$ docker network disconnect isolated_nw container3
[yangdong@centos7 ~]$ docker network rm isolated_nw
isolated_nw
[yangdong@centos7 ~]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
2a820cde1d0c bridge bridge local
54be0bc791bf host host local
8488a8a4ca59 none null local
a88875cc258f simple-network bridge local

Docker的单主机容器网络的更多相关文章

  1. docker容器网络—单主机容器网络

    当我们在单台物理机或虚拟机中运行多个docker容器应用时,这些容器之间是如何进行通信的呢,或者外界是如何访问这些容器的? 这里就涉及了单机容器网络相关的知识.docker 安装后默认 情况下会在宿主 ...

  2. docker1.12在cento7里的跨多主机容器网络

    docker1.12在cento7里的跨多主机容器网络

  3. Docker入门篇(二)之docker的单主机网络

    Docker 安装时会自动在host上创建三个网络,我们可用 docker network ls命令查看: [root@localhost ~]# docker network ls NETWORK ...

  4. Swarm基于多主机容器网络 - overlay networks 梳理

    前面介绍了Docker管理工具-Swarm部署记录,下面重点说下Swarm基于多主机容器通信的覆盖网络 在Docker版本1.12之后swarm模式原生支持覆盖网络(overlay networks) ...

  5. Docker:跨主机容器间通信之overlay [十五]

    一.配置overlay类型网络准备工作 1.在luoahong3主机上 docker run -d -p 8500:8500 -h consul --name consul progrium/cons ...

  6. 【转】理解Docker容器网络之Linux Network Namespace

    原文:理解Docker容器网络之Linux Network Namespace 由于2016年年中调换工作的原因,对容器网络的研究中断过一段时间.随着当前项目对Kubernetes应用的深入,我感觉之 ...

  7. Kubernetes & Docker 容器网络终极之战(十四)

    目录 一.单主机 Docker 网络通信 1.1.host 模式 1.2 Bridge 模式 1.3 Container 模式 1.4.None 模式 二.跨主机 Docker 网络通信分类 2.1 ...

  8. 理解Docker(6):若干企业生产环境中的容器网络方案

    本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  9. Docker 0x07: Docke 容器网络

    目录 Docke 容器网络 Container Network Model (CNM) 具体项目中代码对象有哪些 Implementations实现的网络(直接英文版) Libnetwork incl ...

随机推荐

  1. Web 开发人员必备的12款 Chrome 扩展程序

    之前已经分享过一些帮助 Web 开发人员和设计师的 Chrome 扩展,这次我们继续展示一组很有用的 Chrome 应用程序.这些免费的 Chrome 应用程序可以简化您的工作流程,为了加快您的工作流 ...

  2. 20款免费的 PSD 网站模板【免费下载】

    如果你的新项目预算很低,那么免费网站模板对你来说是一个很好的解决方案.有很多的预先设计的网站模板 PSD 素材可以使用和自由定制.在这里,你会发现可供下载的超级棒的免费网站模板.你可以使用它们来创建自 ...

  3. CSS尺寸单位 % px em rem 详解

    在CSS中,尺寸单位分为两类:相对长度单位和绝对长度单位.相对长度单位按照不同的参考元素,又可以分为字体相对单位和视窗相对单位.字体相对单位有:em.ex.ch.rem:视窗相对单位有:vw.vh.v ...

  4. Moqui简介

    Moqui简介 Moqui是一个生态系统理念,是需要一系列的能够用于构建企业自动化办公的开源软件的组合,如:eCommerce, ERP, CRM, SCM, MRP, EAM, POS, 等等. 架 ...

  5. 浅析正则表达式模式匹配的String方法

    在JavaScript代码中使用正则表达式进行模式匹配经常会用到String对象和RegExp对象的一些方法,例如replace.match.search等方法,以下是对一些方法使用的总结. Stri ...

  6. AE常见接口之间的关系(较笼统)+arcgis常见概念

    常见的接口有如下关系 IworkspaceFactory-------------->IworkSpace------------------>IfeatureWorkSpace ---- ...

  7. SharePoint 2013 通过HttpModule 管理视图权限

    HttpModule工作原理 HttpModule负责监听HttpRequest,当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任 ...

  8. IOS中限制TextField中输入的类型以及长度

    -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementSt ...

  9. 微信小程序之后台https域名绑定以及免费的https证书申请

    微信小程序在11月3号发布了,这是一个全新的生态,没有赶上微信公众号红利的开发者,运营者可别错过这趟车了. 但是微信的后台需要全https,之前我还不相信,后台注册了后进后台才发现,服务器配置如下图 ...

  10. Android图表类库:WilliamChart

    WilliamChart是基于Views的Android图表类库,帮助开发者在Android应用中实现折线图.柱状图和堆叠柱状图.数值发生变化时图表也会以动画的效果发生变化. At the momen ...