centos7 docker 容器访问宿主机的 ip 配置问题

场景描述

centos7 运行 docker 容器应用时,须要链接宿主机的 mysql3306 端口,发现链接不上,docker 容器没法访问宿主机的 mysql 数据库。可是,在容器内访问外部网络是能够 ping 通的。mysql

缘由分析

centos7 上部署 docker 容器,其网络模式采用的是 bridge 模式。
启动 docker 时,docker 进程会建立一个名为 docker0 的虚拟网桥,用于宿主机与容器之间的通讯。当启动一个 docker 容器时,docker 容器将会附加到虚拟网桥上,容器内的报文经过 docker0 向外转发。sql

若是 docker 容器访问宿主机,那么 docker0 网桥将报文直接转发到本机,报文的源地址是 docker0 网段的地址。而若是 docker 容器访问宿主机之外的机器,dockerSNAT 网桥会将报文的源地址转换为宿主机的地址,经过宿主机的网卡向外发送。docker

所以,当 docker 容器访问宿主机时,若是宿主机服务端口会被防火墙拦截,那么就没法连通宿主机,出现 No route to host 的错误。数据库

而访问宿主机所在局域网内的其余机器,因为报文的源地址是宿主机 ip,所以,不会被目的机器防火墙拦截,因此能够访问。centos

解决问题

首先设置了 mysql 的配置文件,保证 mysql 能够被任何 ip 访问:安全

[mysqld]
bind-address = 0.0.0.0

修改完配置文件重启生效。
但为了安全考虑,防火墙的 3306 端口仍然是不开放外网访问的。 bash

容器访问宿主机的地址使用 eth0 的地址,即宿主机内网 ip 地址。
运行 ipconfig 命令,查看网络的虚拟网桥相关信息。 网络

注意:宿主机会把容器 ip 地址段当成外网 ip。(当前说明是 centos7 环境)测试

编辑防火墙文件 /etc/firewalld/zones/public.xml,添加下面 docker0 地址段到配置:centos7

<rule family="ipv4">
  <source address="172.18.0.0/16"/>
  <accept/>
</rule>

重启防火墙,docker 容器便可正常访问宿主机端口。

service firewalld restart

🎨 若是有用到 docker-compose 命令,则会自动建立一个名为 br-"docker network id" 的虚拟网桥。
🎨 此时一样须要将虚拟网桥地址段配置到防火墙白名单,才能正常访问,添加配置:

<rule family="ipv4">
  <source address="172.20.0.0/16"/>
  <accept/>
</rule>

image

测试端口

在容器中测试宿主机端口是否能够链接,可使用 wget 内网ip:端口 命令。

$ wget 172.17.25.162:3306  
wget: can not connect to remote host (172.17.25.162): Host is unreachable  #不能够链接

$ wget 172.17.25.162:3306
wget: bad header line: 5.7.29-log  #能够链接
相关文章
相关标签/搜索