linux系统中docker服务和普通服务对外访问端口不通的问题

  前一段时间,在一个新的centos 7.4 服务器上运行项目,共有四个项目,因为特殊原因,两个是通过docker 运行,另外两个是通过nginxtomcat 运行。
  当运行起来以后,发现docker 运行的那两个可以正常在外网访问,而另外两个不是docker 的死活访问不到。
  我的排除问题的方法如下:

1、检查项目是否运行:

查看了tomcat是否运行:
输入如下命令:

ps -aux|grep tomcat

  的确tomcat运行正常,看过日志,运行也没有问题

查看了nginx 映射的另一个项目,端口仍存在,我后来直接输入了ss -tnl 命令:

结果如下:

502 docker 端口冲突 docker端口不通_iptables配置


  奇怪了,端口也是正常运行的,为什么偏偏docker的能对外访问,那两个不行呢。

那现在的情况如下图:

运行环境

外网端口

内网端口

docker服务

7001(正常访问)

10001(正常)

docker服务

7002(正常访问)

10002(正常)

nginx服务

7003(访问失败)

10003(正常)

tomcat服务

7004(访问失败)

10004(正常)

502 docker 端口冲突 docker端口不通_linux防火墙开放端口_02

2、确认内网访问:

  难道是另外两个外网端口忘记开了?我赶紧试一下这两个不通的项目是否可以内网访问:
分别用了如下命令:

curl -i http://localhost:10003

和:

wget http://localhost:10003

  10004 也如上试过了,内网没问题,因此我判断端口没开,赶紧把铁锅甩了出去。

502 docker 端口冲突 docker端口不通_502 docker 端口冲突_03

3、再次排查

  第二天,服务器提供方更狠,直接说内网telnet我的那俩端口访问不到,但是我内网是可以的,真的太奇怪了。

  整个过程我都没有想过防火墙的问题。为什么呢?

因为首先这是个新服务器,并没有设置过端口的规则,docker 的服务是可以的,另外两个不可以,那问题应该不是防火墙的问题(后来发现是自己想的太少了。。)

  后来我们架构师说,你把那两个通的项目先关掉,用那俩不通的项目先试试这两个通的端口,试试能不能外网访问?

502 docker 端口冲突 docker端口不通_linux防火墙开放端口_04


  这想法我怎么没想到,哈哈,我赶紧试试,发现,的确也不能访问,那这样就赖不上人家了,只能自己再看了。

4、最终问题原因

  在最后,我先关掉了一下防火墙,因为centos 7 默认安装的防火墙是firewall ,所以我先将防火墙关掉:

关掉firewall 防火墙

systemctl stop firewalld.service 关闭防火墙

   然后访问了下项目,才发现,项目都通了,竟然都可以正常访问。

502 docker 端口冲突 docker端口不通_linux防火墙开放端口_05

  为什么docker 的可以,其他的竟然不可以,防火墙是肯定没有设置过,为什么呢?难道是docker 在安装的时候,自动设置了?

5、安装iptables

  既然找到了问题,以前没有设置过firewall ,我想直接重新安装iptables 的了。

首先关闭firewall开机启动

systemctl disable firewalld.service

确认防火墙是否关掉
  关闭后显示notrunning即表示已关闭

firewall-cmd --state

安装iptables

yum install iptables 
yum install iptables-services

  如果yum 命令不可用,可以参照另一篇文章,linux命令—使用yum命令时出错,Could not retrieve mirrorlist

启动iptables

service iptables start  或者 systemctl start iptables

设置开机启动iptables

systemctl enable iptables.service

编辑防火墙文件,输入如下命令:

vim /etc/sysconfig/iptables

在其中开启了我的那四个端口:

# sample configuration for iptables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 10001 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 10002 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 10003 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 10004 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

  即如上,我开启了我的 80、10001、10002、10003、10004 端口。
设置完之后,重启iptables

service iptables restart

这样就可以正常访问项目了。

  虽然最后解决了问题,但是我还是没搞明白,为什么docker 运行的项目是可以访问,其他的不行呢?期望大神解惑~

2021年3月2号补充

一位大佬解惑,如下:

  docker 容器创建时,如果你指定了容器映射的宿主机端口,docker 会自动在 iptables 的规则链中加上自己容器对外提供服务所需的规则链,所以 docker 容器跑的服务可以访问到。