博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
docker容器网络 - 同一个host下的容器间通信
阅读量:6501 次
发布时间:2019-06-24

本文共 8381 字,大约阅读时间需要 27 分钟。

hot3.png

    对于复杂的应用,不可避免需要多个服务部署在多个容器中,并且服务间存在相互间通信的情况。比如服务A需要连接mysql的容器。本文将介绍docker的容器网络,并通过实践解决在同一个docker Host主机下的容器间通信的问题。

    在安装好docker后,docker将创建一个linux网桥docker0,它在内核层连通了其他的物理或虚拟网卡,也就是所有容器和本地主机都放到同一个物理网络。我们可以通过 brctl 命令查看网桥的信息,brctl是需要自行安装的。

[root@localhost ~]# brctl showbridge name	bridge id		STP enabled	interfacesbr-1a83283cbf04		8000.0242123432ad	no		br-70590112bbda		8000.0242927ea6d9	no		docker0		8000.024232ccc082	no

    另外,docker还会给我们创建三个网络:bridge/host/none。我们可以通过network ls命令查看当前宿主机中所有的docker网络。

[root@localhost ~]# docker network lsNETWORK ID          NAME                DRIVER              SCOPE5a9ac72df73f        bridge              bridge              local7d9eb4bd321c        host                host                local4b740dab2aab        none                null                local

    其中,网桥bridge模式是在实际项目中常用的。接下来,以交互模式启动两个busybox容器。在没有指定相关网络的情况下,容器都会连接到默认的bridge网络。我们可以通过 --network 参数指定容器连接的网络。

[root@localhost ~]# docker run -itd --name=busybox1 busybox2813aba53acd688fa69807158830bef27b4ea8dc2ecfe13e7e357ce98a204f0b[root@localhost ~]# docker run -itd --name=busybox2 busybox83fbeeb4e0527ece0602729415a57383b474284143a381e0a27561a69d75b1f5

启动容器后,检查当前默认bridge网络情况。busybox1和busybox2容器已经连接到了bridge网络,除此之外,还可以获取到两个容器的IP地址。

[root@localhost ~]# docker network inspect bridge[    {        "Name": "bridge",        "Id": "5a9ac72df73f19beaade92a28d705509fd24c350497dd90ecae224fdb18214bc",        "Created": "2018-12-25T16:30:26.58008782+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"                }            ]        },        "Internal": false,        "Attachable": false,        "Ingress": false,        "ConfigFrom": {            "Network": ""        },        "ConfigOnly": false,        "Containers": {            "2813aba53acd688fa69807158830bef27b4ea8dc2ecfe13e7e357ce98a204f0b": {                "Name": "busybox1",                "EndpointID": "522f2b4b072098525939cc6b313f5673f82444d8ef6807bac0efcdce6a7c8418",                "MacAddress": "02:42:ac:11:00:02",                "IPv4Address": "172.17.0.2/16",                "IPv6Address": ""            },            "83fbeeb4e0527ece0602729415a57383b474284143a381e0a27561a69d75b1f5": {                "Name": "busybox2",                "EndpointID": "e277940484662a341730766300149c2f63974d0b9e9cbd6c531bc7c8c37f31f9",                "MacAddress": "02:42:ac:11:00:03",                "IPv4Address": "172.17.0.3/16",                "IPv6Address": ""            }        },        "Options": {            "com.docker.network.bridge.default_bridge": "true",            "com.docker.network.bridge.enable_icc": "true",            "com.docker.network.bridge.enable_ip_masquerade": "true",            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",            "com.docker.network.bridge.name": "docker0",            "com.docker.network.driver.mtu": "1500"        },        "Labels": {}    }]

接下来,我们测试下两个容器的互通情况。

    进入busybox1容器,分别ping 容器busybox2的IP和容器名,可以发现可以通过IP地址ping通busybox2,但是不能通过容器ping通。其中,172.17.0.3是busybox2的IP地址。

[root@localhost ~]# docker attach  2813aba53acd/ # ping  172.17.0.3PING 172.17.0.3 (172.17.0.3): 56 data bytes64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.090 ms64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.193 ms/ # ping busybox2

在容器中,可以查看容器的hosts文件,里面没有任何关于busybox2容器的信息。

/ # cat /etc/hosts127.0.0.1	localhost::1	localhost ip6-localhost ip6-loopbackfe00::0	ip6-localnetff00::0	ip6-mcastprefixff02::1	ip6-allnodesff02::2	ip6-allrouters172.17.0.2	2813aba53acd

    在计算机网络中,想通过域名ping通其它网站,有两种方法:一种是本地的hosts文件,里面配置的是路由规则;另一种是DNS服务,通过DNS服务器返回正确的IP地址。那么docker是否也可以通过容器名访问其它容器的方式呢?

(1)link连接

默认的桥接网络支持使用端口映射和 docker run --link 命令,实现容器间互相通信。该方法已经在官方文档中标识为不推荐使用

https://docs.docker.com/network/links/

7d2e34d5c5a5b03c3d07113935d7817f3df.jpg

    下面,继续介绍通过 --link 参数时间容器间通信。我们将创建busybox3和busybox4两个容器,其中busybox4可以通过busybox3容器名与busybox3容器进行通信。

    新建busybox3和busybox4,其中busybox4通过 --link 参数指定连接到 busybox3容器。

[root@localhost ~]# docker run -itd --name=busybox3 busyboxa539a74a9ecad6782f88944604bbdd045f4a1fd6965a3484e04d1dbbec1e511d[root@localhost ~]# docker run -itd --link busybox3  --name=busybox4 busyboxf6c470354b55300106a3a8960c4c935dcdd0cb0f7ad6c941c8f040fdb0cd0a04

重新进入容器busybox4,查看hosts文件,可以看到host文件中已经出现busybox3容器,并配置了路由规则。

/ # cat /etc/hosts127.0.0.1	localhost::1	localhost ip6-localhost ip6-loopbackfe00::0	ip6-localnetff00::0	ip6-mcastprefixff02::1	ip6-allnodesff02::2	ip6-allrouters172.17.0.4	busybox3 a539a74a9eca172.17.0.5	f6c470354b55

测试busybox4连接容器busybox3

/ # ping busybox3PING busybox3 (172.17.0.4): 56 data bytes64 bytes from 172.17.0.4: seq=0 ttl=64 time=0.077 ms64 bytes from 172.17.0.4: seq=1 ttl=64 time=0.125 ms^C--- busybox3 ping statistics ---2 packets transmitted, 2 packets received, 0% packet loss

 

(2)自定义bridge网络,实现容器间通信

    从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。使用默认的bridge网络,不能通过DNS server实现通过容器名通信,但是使用自定义bridge网络可以做到通过容器名互相通信。

通过 docker network create 命令创建一个自定义的bridge网络

[root@localhost ~]# docker network create --driver bridge busybox_bridge1a83283cbf047fea14231daef7edb67e8a11383f61c176e5c4983e961e757a1e[root@localhost ~]# docker network lsNETWORK ID          NAME                DRIVER              SCOPE53c7e86fc3ec        bridge              bridge              local1a83283cbf04        busybox_bridge      bridge              local7d9eb4bd321c        host                host                local4b740dab2aab        none                null                local

分别创建busybox5/busybox6容器,在run命令里加入--network参数使两个容器绑定到前面自定义的网络中。

[root@localhost ~]# docker run -itd --network busybox_bridge --name busybox5 busyboxccd81a357cf48af2c01c64cd1ef7a4c463b415bd477d965f19a3b47be3760208[root@localhost ~]# docker run -itd --network busybox_bridge --name busybox6 busyboxd3e5af0eeb86a480fe868bb9ea7cea2cb29b7f12b7f680cbd5b48288c15b10e9

查看busybox_bridge网络情况,可以看到,busybox5/busybox6容器已经绑定到该网络中。

[root@localhost ~]# docker network inspect busybox_bridge[    {        "Name": "busybox_bridge",        "Id": "1a83283cbf047fea14231daef7edb67e8a11383f61c176e5c4983e961e757a1e",        "Created": "2018-12-25T22:17:10.981291803+08:00",        "Scope": "local",        "Driver": "bridge",        "EnableIPv6": false,        "IPAM": {            "Driver": "default",            "Options": {},            "Config": [                {                    "Subnet": "172.18.0.0/16",                    "Gateway": "172.18.0.1"                }            ]        },        "Internal": false,        "Attachable": false,        "Ingress": false,        "ConfigFrom": {            "Network": ""        },        "ConfigOnly": false,        "Containers": {            "ccd81a357cf48af2c01c64cd1ef7a4c463b415bd477d965f19a3b47be3760208": {                "Name": "busybox5",                "EndpointID": "4da57d779c14bdee415eee69a92dd802250bf6e89cd744f8543c4498e32aebdc",                "MacAddress": "02:42:ac:12:00:02",                "IPv4Address": "172.18.0.2/16",                "IPv6Address": ""            },            "d3e5af0eeb86a480fe868bb9ea7cea2cb29b7f12b7f680cbd5b48288c15b10e9": {                "Name": "busybox6",                "EndpointID": "6f130cc2055399c051cd556e20835793332605f9ee636885c602f2b257f9db80",                "MacAddress": "02:42:ac:12:00:03",                "IPv4Address": "172.18.0.3/16",                "IPv6Address": ""            }        },        "Options": {},        "Labels": {}    }]

接下来进入busybox5容器,测试是否可以通过容器名ping通busybox6

[root@localhost ~]# docker attach busybox5/ # ping busybox6PING busybox6 (172.18.0.3): 56 data bytes64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.107 ms64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.149 ms

看下容器的hosts文件,文件里是没有busybox6的映射配置的。那么它是怎么通过容器名访问到另一个容器的呢?答案就是内嵌的dns服务器。

/ # cat /etc/hosts127.0.0.1	localhost::1	localhost ip6-localhost ip6-loopbackfe00::0	ip6-localnetff00::0	ip6-mcastprefixff02::1	ip6-allnodesff02::2	ip6-allrouters172.18.0.2	ccd81a357cf4

查看DNS服务,可以看到指定了DNS解析服务地址:nameserver 127.0.0.11 。如果是连接到默认bridge网络的容器,在resolv.conf文件是没有127.0.0.11这个DNS服务器配置的

/ # cat /etc/resolv.conf nameserver 127.0.0.11options ndots:0

容器中的DNS名称解析优先级顺序为:

  • ​ 内置DNS服务器127.0.0.11。
  • ​ 通过--dns等参数为容器配置的DNS服务器。
  • ​ docker守护进程的--dns服务配置(默认为8.8.8.8和8.8.4.4)
  • ​ 宿主机上的DNS设置。

 

文章收录于:

转载于:https://my.oschina.net/thinwonton/blog/2993309

你可能感兴趣的文章
1.12 xshell密钥认证
查看>>
3.2 用户组管理
查看>>
ibatis 动态查询
查看>>
汇编语言之实验一
查看>>
git 调用 Beyond Compare
查看>>
SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)[转]
查看>>
android实现图片识别的几种方法
查看>>
mvc学习地址
查看>>
masonry 基本用法
查看>>
Word产品需求文档,已经过时了【转】
查看>>
dtoj#4299. 图(graph)
查看>>
关于网站的一些js和css常见问题的记录
查看>>
zabbix-3.4 触发器
查看>>
换用代理IP的Webbrowser方法
查看>>
【视频编解码·学习笔记】7. 熵编码算法:基础知识 & 哈夫曼编码
查看>>
spark集群安装部署
查看>>
MySql 查询表字段数
查看>>
mariadb 内存占用优化
查看>>
Centos7安装编译安装zabbix2.219及mariadb-5.5.46
查看>>
Visual Studio Remote Debugger(for 2005/2008) .net远程调试<转>
查看>>