问题简述
前不久,部门在一台生产环境服务器上部署好了docker服务,并通过官方镜像启动了一个mysql容器,将3306端口expose到宿主机的3308端口上,一切顺利,一片和谐。
然而当我们需要在该服务器上再启动一台新的mysql容器,将3306端口expose到宿主机的3310端口上时,却开始报错,容器处于created状态,但就是无法启动。
下面是部分报错的内容:
iptables failed: iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.17.0.3 --3306 ! -i docker0 failed: iptables: No chain/target/match by that name.
很明显,指向的是iptables,查了一下服务器的iptables,发现空空如也,什么都没配(当然,CentOS7默认是不安装iptables.service的)。
接着,我试着docker run时不指定-p 3310:3306,发现这次容器顺利起起来了,这就基本确认镜像和启动命令都没问题(查过history目录,比对过之前成功启动的那个容器的命令),那么问题的关键,还是iptables!
问题分析
查看当前生效的iptables
iptables-save > /etc/sysconfig/iptables
cat /etc/sysconfig/iptables
结果如下:
# Generated by iptables-save v1.4.21 on Fri Mar 17 10:13:06 2017
*nat
:PREROUTING ACCEPT [18937:1136549]
:INPUT ACCEPT [18937:1136549]
:OUTPUT ACCEPT [30984:1859072]
:POSTROUTING ACCEPT [31046:1862792]
: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 POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 3306 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 3308 -j DNAT --to-destination 172.17.0.2:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1024 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1025 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1026 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1027 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1028 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1029 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1030 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1031 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1032 -j DNAT --to-destination 172.17.0.3:3306
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1033 -j DNAT --to-destination 172.17.0.3:3306
COMMIT
# Completed on Fri Mar 17 10:13:06 2017
# Generated by iptables-save v1.4.21 on Fri Mar 17 10:13:06 2017
*filter
:INPUT ACCEPT [163678181:9546648072]
:FORWARD ACCEPT [116881666:54259777562]
:OUTPUT ACCEPT [193776014:9477299313]
-A INPUT -p tcp -m tcp --dport 3308 -j ACCEPT
COMMIT
# Completed on Fri Mar 17 10:13:06 2017
结合之前的报错信息,也就是说,在iptables文件里并没有找到-A DOCKER DOCKER链,因此无法启动。
解决办法
修改*filter域的内容如下:
*filter
:INPUT ACCEPT [163678181:9546648072]
:FORWARD ACCEPT [116881666:54259777562]
:OUTPUT ACCEPT [193776014:9477299313]
:DOCKER - [0:0]
-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 INPUT -p tcp -m tcp --dport 3308 -j ACCEPT
COMMIT
保存后,安装iptables-service服务,并启动。
yum-install -y iptables-service
systemctl start iptables.service
systemctl enable iptables.service
如果之前已经安装过iptables-service服务,只需重启即可。
systemctl restart iptables.service
删除原来未绑定端口的MySQL容器,重新使用端口绑定的方式启动它,顺利完成。
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
288f3fa28cff mysql:5.5.54 "docker-entrypoint.sh" About an hour ago Up About an hour 0.0.0.0:3310->3306/tcp mysql-envicloud
791792e250aa mysql:5.5.54 "docker-entrypoint.sh" 11 days ago Up 11 days 0.0.0.0:3308->3306/tcp mysql-wwy
再查看一下当前生效的iptables,DOCKER链已成功匹配。
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:tns-server
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.3 tcp dpt:mysql