Docker 下的网络模式

前言


Docker 常用指令详解 一文中介绍了 Docker 的常用指令, 在构建容器的时候使用了 --net anyesu_net 这个选项, 意思是让容器使用自定义的网络 anyesu_net , 本文就 Docker 下的网络模式做一个简单介绍。

四种网络模式的选择


  • bridge

这是 Docker 默认使用的模式, Docker Daemon 启动时默认会创建 Docker0 这个网桥, 网段为 172.17.0.0/16 , 宿主机 IP172.17.0.1 , 作为这个虚拟子网的 网关

当然, 也可以新建一个名为 anyesu_net 网段为 172.18.0.0/16 的网桥:

docker network create --subnet=172.18.0.0/16 anyesu_net

启动 容器 时指定 --net anyesu_net 即可。

docker network 命令相关资料

  • host

容器 共享 宿主机 的网络 ( IP端口 ) 。使用 Docker 有相当一部分目的是为了隔离 宿主机容器 , 使用 host 模式就违背了这一点, 不是很好。另外有很多 镜像tomcat 默认监听 8080 端口的, 使用 host 模式后开多个 容器 就会造成端口冲突, 而不得不修改 tomcat 的监听端口。

  • none

这种模式下, 创建的 容器 拥有自己的 Network Namespace, 但是没有任何网络配置, 所以默认是没有网络的, 可以自己对 容器网卡IP 进行配置, 适合用来配置比默认设置更加复杂的网络环境。

  • container

类似于 host 模式, 不过这种模式是共享已存在的 容器 使用的网络。

给容器分配固定 IP


默认应该是按 容器 创建或启动顺序依次分配的, 所以 容器 重启后 IP 就可能会变化, 这对于一些需要定向访问 容器 的功能来说就比较麻烦了。一种解决办法是使用 link 来链接 容器, 原理就是动态配置 hosts , 不过这种方式启动顺序有依赖关系, 因此本人不习惯使用。还有一种方法, 是启动 容器 的时候使用自定义网络, 如 anyesu_net , 并指定 --ip 选项来固定 IP

当然, 网上还有很多教程借助 pipeworknsenter 等工具实现固定 IP 的功能, 甚至可以分配到 宿主机 所在物理网段上的 IP 。不过, 步骤都比较复杂, 有兴趣的小伙伴可以参考下面的几篇文章自己尝试哦。

关于容器中 hosts 文件的修改


启动 容器 的时候指定 --link--add-host 选项修改 hosts 文件内容, 但都是追加内容而无法覆盖已有内容, 比如我要重设 localhost 使其指向 宿主机IP 172.17.0.1 而不是默认的 127.0.0.1 ( 可能也就我吃饱了撑着要这么做吧 ) 就不能用这种方法了。

了解到 容器hosts 文件是 容器 启动时先在 宿主机 上动态创建后再挂载到 容器 上的 ( 源文件位于 宿主机/var/lib/docker/containers/[容器id] 目录下 ) , 因此, 容器 重启之后还会重新创建, 即之前所做的修改都没了。于是想到在容器的 启动命令 中动态修改, 但是 hosts 文件是不允许直接修改的, 于是采用下面的办法:

# 拷贝hosts内容
cp /etc/hosts /etc/hosts.tmp
# 替换字符串
sed -i 's$127.0.0.1$172.17.0.1$' /etc/hosts.tmp
# 覆盖hosts
cat /etc/hosts.tmp > /etc/hosts

# CMD参数中 使用 sh -c "... && ... && ..." 的方式来运行多个指令

个人觉得这也不是一种好办法, 就换了一种更简单粗暴的方法: -v /etc/hosts:/etc/hosts , 使用 宿主机 文件映射 容器hosts 文件 ( 或者新建一个 hosts 文件专门给 容器 用而不影响 宿主机hosts ) 达到覆盖的目的, 再配合 容器 固定 IP 配置, 多个 容器 共用一套 hosts 文件, 将所有 容器 的主机名和 IP 配置进去, 容器 之间也可以通过主机名或子网 IP 直接访问。

相关文章:

Docker 下使用 dubbo


公司项目中使用了 dubbo 来搭建分布式系统, 本地开发环境统一使用 localhost 来连接 ZooKeeper , 绑定不同端口实现 伪分布式 。后来就在测试环境上使用 Jenkins + Svn + Maven + Docker 的方式完成 一键构建 , 将每个服务部署在单独的容器之中, 使用默认的 bridge 网络模式。

遇到的问题

1. 访问宿主机上的 ZooKeeper

简单的方法是在项目配置文件中使用环境变量或主机名 ZkServer 作为注册中心地址, 相应的对 容器 进行环境变量和 hosts 的配置即可。不过,作为一个懒人, 项目中已经写好了使用 localhost 就不想改成 ZkServer 了, 方法也简单, 就是使用上面的方法替换 localhostIP172.17.0.1 , 即 宿主机的 IP

在Docker中运行Dubbo应用

2. 服务提供者注册 IP 问题

容器 内的服务默认注册到 zookeeper 上的地址是一个 IP ( 如 172.17.0.2 ) , 是一个内网地址, 对于 宿主机运行在其上的所有容器 之外的其他机器来说是不可访问的。如果要使服务对其他机器可用的话就要另辟蹊径了, 主要方法有:

  1. 容器使用 host 网络模式或设置为宿主机物理网段上的 IP
  2. 对宿主机和服务消费者之间的网络设置路由规则, 使消费者可访问容器内网 IP
  3. 修改 dubbo 源码来指定服务注册 IP

上面的方法实践起来有点复杂, 也不是很可靠, 还得另寻方法。

查了下 dubbo 的源码, 在 com.alibaba.dubbo.config.ServiceConfig 类的 doExportUrlsFor1Protocol 方法中, 如果配置中没有指定 host 属性或者使用了回环地址则调用 InetAddress.getLocalHost().getHostAddress() 来获取本机可用 IPInetAddress.getLocalHost 这个方法在 Windows 下应该是取所有网卡中第一个可用的 IP, 在 Linux 下应该是取主机名对应的 IP ( 先去 /etc/hosts 中找, 找不到再去 dns 服务器找, 需要注意这有可能会得到一个错误的 IP) , 因此, 在 Linux 下针对上面的问题只需修改 hosts 文件, 指定主机名对应的 IP宿主机 的局域网 IP 。另外测试了下, 设置的 hostLinux 下只用于提供给服务注册中心而不用于端口绑定, 也就是说可以设置任意 IP ; 而在 Windows 下设置了非本机 IP 会无法绑定端口。

hosts 文件改完还有一个问题:tomcat 默认 shutdown 命令绑定的端口是 localhost:8005, 由于 localhost 已经不再是容器的 IP , 因此端口绑定会失败。简单处理就是修改 tomcat/conf/server.xml 文件中 Server 节点的属性, 添加属性 address="127.0.0.1" , 如下所示:

<Server address="127.0.0.1" port="8005" shutdown="SHUTDOWN">
总结下最终的方案步骤:
  1. 创建自定义网络 ( 172.18.0.0/16 网段 )
  2. 容器 指定 hostname 、自定义网络、固定 IP
  3. 宿主机 ( 局域网 IP : 192.168.1.100)新建文件 /etc/hosts2 挂载到容器的 /etc/hosts 上 ( -v /etc/hosts2:/etc/hosts ) , 内容如下, 所有容器共用此 hosts 文件
172.18.0.1 localhost
192.168.1.100 docker_host1
192.168.1.100 docker_host2
...

  1. 宿主机容器 的端口映射 -p 20880:20880
最终结构图如下所示:
dubbo容器结构

2017-12-25 追加


目前 dubbo 自身已提供环境变量的方式注册 IP 和端口,详见 官方示例

  • 当前 2.5.9 版本有 bug , 监听端口与注册端口不一致会导致找不到对应服务

2.5.x 分支中配置优先级:
系统环境变量 > java 命令参数 ( -Dxxx=yyy ) > 配置文件 host 属性 > /etc/hostshostname-ip 映射关系 > 默认连通注册中心地址的网卡地址 > 第一个可用的网卡地址

参考文章


系列文章


Docker 学习总结

Docker 常用指令详解

使用 Dockerfile 构建镜像

使用 Docker Compose 构建容器

Docker Daemon 连接方式详解


转载请注明出处:http://www.jianshu.com/p/f510aaa470cc

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容

  • 转载自 http://blog.opskumu.com/docker.html 一、Docker 简介 Docke...
    极客圈阅读 10,487评论 0 120
  • docker之容器通信 这节属于了解学习,算是烂尾,最后我也没找到合适的方式去固定容器ip,然后作为正式环境去跑,...
    道无虚阅读 5,475评论 1 7
  • 五、Docker 端口映射 无论如何,这些 ip 是基于本地系统的并且容器的端口非本地主机是访问不到的。此外,除了...
    R_X阅读 1,743评论 0 7
  • 概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求。而容器的网络通信...
    糙老爷们儿吃什么樱桃阅读 3,618评论 1 5
  • 今天是愉快的一天,按照老习惯,起床敷包然后叫醒儿子出去买早餐。愉快早餐后,孩子上学去了,我就去咨询儿子咽炎问题,最...
    梦断蓝桥李春红阅读 232评论 0 0