通过配置Linux系统'ip_forward'的值,解决无法从外部访问容器内部服务的问题。

背景

今天在一台新虚拟机上需要临时启动一个consul服务,安装Docker后使用docker启动,但是在执行启动命令后发现docker有一个警告:

WARNING: IPv4 forwarding is disabled. Networking will not work.

当时没仔细看,使用docker ps查看容器状态后启动正常,但是使用宿主机ip+port在浏览器访问consul-ui时发现网路无法连接,但是在宿主机本身访问服务是正常的,忽然想起来之前启动时的WARN警告,所以重新启动了一个新容器将问题复现。

原因

因为之前未出现过这样的问题,经过google后发现:可能是与Linux的ip_forward设置有关系:

出于安全考虑,Linux系统默认是禁止数据包转发的。所谓转发即当主机拥有多于一块的网卡时,
其中一块收到数据包,根据数据包的目的ip地址将数据包发往本机另一块网卡,
该网卡根据路由表继续发送数据包。这通常是路由器所要实现的功能。

要让Linux系统具有路由转发功能,需要配置一个Linux的内核参数net.ipv4.ip_forward。这个参数指定了Linux系统当前对路由转发功能的支持情况;
其值为0时表示禁止进行IP转发;如果是1,则说明IP转发功能已经打开。

使用过docker的小伙伴都知道,单机docker的网络架构实质上是在宿主机上安装了一个docker0的网桥,从外部访问容器内部时只需要访问宿主机的地址和对应的容器映射的地址,访问的数据包到宿主机上后经过ip包解析后通过目的port和iptables的规则会将数据包由eth0网卡转发至docker0网桥上进行下一步路由。

所以如果容器的宿主机上的ip_forward未打开,那么该宿主机上的容器则不能被其他宿主机访问

解决方案

检查宿主机的ip_forward:

[root@dev ~]# cat  /proc/sys/net/ipv4/ip_forward
0

由查询结果得知,我的这台新虚拟机确实没有将ip_forward打开,所以具体的解决方案就是修改ip_forward的值为1

临时解决

直接修改/proc/sys/net/ipv4/ip_forward文件的内容:

[root@dev ~]# echo 1 >  /proc/sys/net/ipv4/ip_forward
[root@dev ~]# cat  /proc/sys/net/ipv4/ip_forward
1

永久解决

修改/etc/sysctl.conf文件

[root@dev ~]# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
[root@dev ~]# sysctl -p
[root@dev ~]#systemctl restart network
[root@dev ~]#systemctl restart docker.service

然后启动新的容器,就可以通过宿主机ip:port来访问容器服务了!!!

人生苦短,我用Python。