问题描述
Docker 容器内部可以ping得通宿主机,但是访问不了宿主机的端口。
注意:
文中所描述的只是“Docker 容器无法访问宿主机”的众多情况中的一种,仅供大家参考。
测试环境
宿主机IP地址:192.168.0.100
Docker 容器网关(docker0网卡)地址:172.17.0.1
容器1 IP地址:172.17.0.2
容器2 IP地址:172.17.0.3
容器2 对外映射了5000端口用于提供http服务,服务运行正常。
容器都是采用桥接模式。
具体操作
使用ping
、curl
或telnet
测试网络情况,如果命令不存在,可参考以下命令进行安装。
# 安装ping 和 telnet 用于测试
sudo apt-get update
sudo apt-get install telnet
sudo apt-get install inetutils-ping
在容器1内部ping得通宿主机,但是访问不了宿主机的5000端口。
[root@宿主机 ~]# sudo docker exec -it 容器1 ping 192.168.0.100
PING 192.168.0.100 (192.168.0.100) 56(84) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=1 ttl=64 time=0.198 ms
64 bytes from 192.168.0.100: icmp_seq=2 ttl=64 time=0.120 ms
64 bytes from 192.168.0.100: icmp_seq=3 ttl=64 time=0.109 ms
64 bytes from 192.168.0.100: icmp_seq=4 ttl=64 time=0.125 ms
[root@宿主机 ~]# sudo docker exec -it 容器1 curl http://192.168.0.100:5000/
curl: (7) Failed to connect to 192.168.0.100 port 5000: No route to host
原因说明
Docker 容器在访问宿主机时,被宿主机的iptables拦截。
处理思路
在iptables的INPUT链中添加放行规则。
注意:Docker 容器间的访问,最好是用容器内部地址或容器名称去访问。
firewalld 配置示例:
# 其中 172.17.0.0/24 为docker容器所在的网段
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="172.17.0.0/24" port protocol="tcp" port="5000" accept'
sudo firewall-cmd --reload
iptables.service 配置示例:
sudo iptables -I INPUT -s 172.17.0.0/24 -d 172.17.0.0/24 -p tcp --dport 5000 -j ACCEPT
# 保存规则
sudo service iptables save
为了安全,端口的开放范围越小越好,比如只对指定的IP开放端口的访问。