容器间的网络设计
1、背景及概述
1.1、背景
最近在做的一个项目,需要进行容器的网络设计,容器的网络可以分为三种:①容器与宿主机的通信。②容器与外部PC的通信。③容器之间的通信。本文档主要讲容器之间的通信。目标有两点:①容器ip得到固定。②容器之间能互相通信。
1.2、概述
本手册以如下网络关系作讲解,为了使得验证具有普遍性,特设计两个容器ip为自定义非同网段ip,HOST主机ip与容器非同网段。本手册介绍三种可以实现不同容器之间通信的方案。
图1 网络关系图
2、方案一
第一种方法是将app1容器连接到app2容器的网络上。
2.1、建立网络
建立两个网络mynetwork1和mynetwork2,网段分别配置为192.17.0.0/24和132.28.0.0/24
$ docker network create -d bridge --subnet=192.17.0.0/24 mynetwork1
$ docker network create -d bridge --subnet=132.28.0.0/24 mynetwork2
$ docker network ls
2.2、配置容器网络
分别配置app1的网络为192.17.0.22,app2的网络为132.28.0.33。注:这里的镜像换成自己的。
$ docker run --net=mynetwork1 -itd --name=app1 --ip 192.17.0.22 970b9230259a
$ docker run --net=mynetwork2 -itd --name=app2 --ip 132.28.0.33 970b9230259a
2.3、加入网络
目前无法通过网络在容器之间进行通信。只有通过将容器添加到同一网络才能进行通信。
往app1容器中添加app2的mynetwork2网络。
$ docker network connect mynetwork2 app1
2.4、验证
$ docker exec -it app1 bash
$ ifconfig
可以看到,这是app1中多了一张和app2的mynetwork2同网段的网卡,并且此时容器之间可以通信。但是app2是和app1中新增的eth1网卡通信,无法与eth0通信。
3、方案二
修改iptables,增加DOCKER-USER的数据链。不同网络中的容器无法相互通信,因为iptables会丢弃此类数据包。这在过滤器表中的DOCKER-ISOLATION-STAGE-1和DOCKER-ISOLATION-STAGE-2链中显示。
$ iptables -t filter -vL
3.1、条件准备
参考2.1和2.2,提前建立网络,配置容器网络。
3.2、添加规则
将规则添加到DOCKER-USER链以允许不同网络之间的通信。需要首先找到网络的桥接接口名称(mynetwork1和mynetwork2)。它们的名称通常看起来像br-37bd4e7b41f5或br-7154a0067392,可以使用命令“ifconfig”或“ip link show”找到它们。由于存在多个桥接接口,为了识别感兴趣的网络的正确接口,桥接接口的inet地址(如ifconfig所示)应与命令’docker network inspect mynetwork1’中显示的子网地址匹配,这里的网桥和ip配为自己的。
$ iptables -I DOCKER-USER -i br-37bd4e7b41f5 -o br-7154a0067392 -s 192.17.0.22 -d 132.28.0.33 -j ACCEPT
$ iptables -I DOCKER-USER -i br-7154a0067392 -o br-37bd4e7b41f5 -s 132.28.0.33 -d 192.17.0.22 -j ACCEPT
可以看到规则添加到DOCKER-USER链以允许两个网络之间通信。
3.3、验证
两个容器相互ping,以验证网络可通信。
$ docker exec -it app1 bash
$ ping 132.28.0.33
$ docker exec -it app2 bash
$ ping 192.17.0.22
3.3、扩展
若在app2网络mynetwork2中在添一个app3是否能和app1通信?答案是不能的。因为添加的链只能是指定的app1和app2之间的网络能通信。
可以通过添加DOCKER-USER链时,不指定特定ip,指定网络网桥来配置解决。
$ iptables -I DOCKER-USER -i br-37bd4e7b41f5 -o br-7154a0067392 -j ACCEPT
$ iptables -I DOCKER-USER -i br-7154a0067392 -o br-37bd4e7b41f5 -j ACCEPT
4、方案三
第三种方法是将app1容器连接到app2容器的ip都配置到一个网段的网络上。
4.1、建立网络
建立一个网络mynetwork,网段配置为192.17.0.0/24。
$ docker network create -d bridge --subnet=192.17.0.0/24 mynetwork
$ docker network ls
4.2、配置容器网络
分别配置app1的网络为192.17.0.22,app2的网络为192.17.0.33。注:这里的镜像换成自己的。
$ docker run --net=mynetwork -itd --name=app1 --ip 192.17.0.22 970b9230259a
$ docker run --net=mynetwork -itd --name=app2 --ip 192.17.0.33 970b9230259a
4.3、验证
两个容器相互ping,以验证网络可通信。
$ docker exec -it app1 bash
$ ping 192.17.0.33
$ docker exec -it app2 bash
$ ping 192.17.0.22