docker与iptables之间的网络通信

docker的几种网络模式

  • (1)host:与主机公共同一网络(network namespqce),器将不会虚拟出自己的网卡,配置自己的ip,而是使用宿主机的ip和端口
  • (2)container:指和已经存在的一个容器共享一个network namespaces,那两个容器除了网络方面,其它的资源还是隔离的,两个容器的进程可以通过lo网卡设备通信。
  • (3)none:拥有自己的network namespaces,但是docker进行任何网络配置,需要我们自己为docker容器添加网络、配置ip
  • (4)bridge:默认的网络设置,此模式会为每个容器分配network namespace、设置ip等,并将一个主机的docker容器连接到一个虚拟网络上

当docker deamon 启动的时候会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似。

容器发包出去的过程:ip包会从container发往自己默认的网关docker0,到包到达docker0时就时到达了主机,这时候会查询主机的路由表,发现包应该从主机的网卡eth0出去,如下的iptables的规则就起作用,对包做nat转换,将原地址转成eth0的地址,这样对于外部来说docker容器就是不可见的:

1
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

启动容器报错

当关闭了iptables之后,再启动带端口映射的容器会报如下错误,内容的意思是容器添加iptables规则失败。

1
2
3
docker: Error response from daemon: driver failed programming external connectivity on endpoint happy_ptolemy (9cedc114be35eb86cd6f7f7bb4f11f93b5f8d2c0745afc72664cef8e96aad439): iptables failed: iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.17.0.2 --dport 3000 -j ACCEPT: iptables: No chain/target/match by that name.

(exit status 1).

这种情况重启docker就好了。原因是docker在启动过程中会将一些docker网络需要的规则写入iptables表,生产环境不能总是靠重启来解决问题。docker daemon启动过程会初始化一系列的iptables规则以及修改部分内核参数。

启动docker前iptables的规则:

1
2
3
4
5
6
7
8
9
10
11
# Generated by iptables-save

*filter

:INPUT ACCEPT [87:6944]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [69:7184]

COMMIT

重启docker后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 

*nat

:PREROUTING ACCEPT [32:1280]

:INPUT ACCEPT [0:0]

:OUTPUT ACCEPT [2:283]

:POSTROUTING ACCEPT [2:283]

:DOCKER - [0:0]

-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER

-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

-A DOCKER -i docker0 -j RETURN

COMMIT

#

*filter

:INPUT ACCEPT [107:8246]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [88:11662]

:DOCKER - [0:0]

:DOCKER-ISOLATION - [0:0]

-A FORWARD -j DOCKER-ISOLATION

-A FORWARD -o docker0 -j DOCKER

-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

-A FORWARD -i docker0 ! -o docker0 -j ACCEPT

-A FORWARD -i docker0 -o docker0 -j ACCEPT

-A DOCKER-ISOLATION -j RETURN

COMMIT

#

ipv4转发被关闭

Docker容器启动报WARNING: IPv4 forwarding is disabled. Networking will not work

将/etc/sysctl中的net.ipv4.ip_forward改为1,重启network就可以了。

参考:https://www.jianshu.com/p/5e941739196d

分享