本文解析在docker默认bridge内容器的通信。这个bridge网络是你安装docker时自动创建的,名称为bridge。
与外部网络通信
容器是否能与外部网络通信取决于两个因素。第一个因素是主机是否转发IP数据包。第二个因素是主机的iptables是否允许这个连接。
ip数据包是否转发由ip_forward系统参数决定。数据包只能在参数为1的情况下才能转发。通常情况你会使docker默认设置–ip-forward=true,docker将在启动时设置ip_forward为1。如果你设置–ip-forward=false且你的系统内核已经启用转发,那么–ip-forward=false不会有影响。检查你系统这个参数的设置或手动启用该参数:
- $ sysctl net.ipv4.conf.all.forwarding
- net.ipv4.conf.all.forwarding = 0
- $ sysctl net.ipv4.conf.all.forwarding=1
- $ sysctl net.ipv4.conf.all.forwarding
- net.ipv4.conf.all.forwarding = 1
这个设置不会对使用network=host的容器产生影响。
如果你设置daemon的参数–iptables=false,docker将不会更改你的iptables规则。否则docker server会附加forwarding规则到DOCKER过滤链。
Docker不会删除或更改DOCKER过滤链中预存在的规则。这允许用户创建限制访问容器所需的任意高级规则。
Docker的forward规则默认允许所有的外部源IP。要只允许一个指定的IP或网络访问容器,在DOCKER过滤链顶部插入一条DROP规则。例如,只允许IP 8.8.8.8访问容器:
- $ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP
其中ext_if是提供外部连接的接口名称。
容器间通信
在操作系统级别两个容器是否能够通信取决于两个因素:
如果你设置–icc=false,那么当你想让两个容器间能够访问该怎么办呢?答案是使用–link=CONTAINER_NAME_或_ID:ALIAS选项。如果docker daemon的参数–icc=false和–iptables=true,那么当docker run调用–link=选项时,docker server将插入一对iptables ACCEPT规则以使得新创建的容器能够连接到另一个容器。
你可以执行iptables命令来查看FORWARD链默认策略是ACCEPT还是DROP:
- # When –icc=false, you should see a DROP rule:
- $ sudo iptables -L -n
- …
- Chain FORWARD (policy ACCEPT)
- target prot opt source destination
- DOCKER all — 0.0.0.0/0 0.0.0.0/0
- DROP all — 0.0.0.0/0 0.0.0.0/0
- …
- # When a –link= has been created under –icc=false,
- # you should see port-specific ACCEPT rules overriding
- # the subsequent DROP policy for all other packets:
- $ sudo iptables -L -n
- …
- Chain FORWARD (policy ACCEPT)
- target prot opt source destination
- DOCKER all — 0.0.0.0/0 0.0.0.0/0
- DROP all — 0.0.0.0/0 0.0.0.0/0
- Chain DOCKER (1 references)
- target prot opt source destination
- ACCEPT tcp — 172.17.0.2 172.17.0.3 tcp spt:80
- ACCEPT tcp — 172.17.0.3 172.17.0.2 tcp dpt:80