場景描述
在 centos7
運行 docker
容器應(yīng)用時荒适,需要連接宿主機的 mysql
的 3306
端口算途,發(fā)現(xiàn)連接不上稳懒,docker
容器無法訪問宿主機的 mysql
數(shù)據(jù)庫坤塞。但是徘熔,在容器內(nèi)訪問外部網(wǎng)絡(luò)是可以 ping
通的门躯。
原因分析
在 centos7
上部署 docker
容器,其網(wǎng)絡(luò)模式采用的是 bridge
模式酷师。
啟動 docker
時讶凉,docker
進程會創(chuàng)建一個名為 docker0
的虛擬網(wǎng)橋,用于宿主機與容器之間的通信山孔。當(dāng)啟動一個 docker
容器時懂讯,docker
容器將會附加到虛擬網(wǎng)橋上,容器內(nèi)的報文通過 docker0
向外轉(zhuǎn)發(fā)台颠。
如果 docker
容器訪問宿主機褐望,那么 docker0
網(wǎng)橋?qū)笪闹苯愚D(zhuǎn)發(fā)到本機,報文的源地址是 docker0
網(wǎng)段的地址串前。而如果 docker
容器訪問宿主機以外的機器瘫里,docker
的 SNAT
網(wǎng)橋會將報文的源地址轉(zhuǎn)換為宿主機的地址,通過宿主機的網(wǎng)卡向外發(fā)送荡碾。
因此谨读,當(dāng) docker
容器訪問宿主機時,如果宿主機服務(wù)端口會被防火墻攔截坛吁,那么就無法連通宿主機劳殖,出現(xiàn) No route to host
的錯誤。
而訪問宿主機所在局域網(wǎng)內(nèi)的其他機器拨脉,由于報文的源地址是宿主機 ip
哆姻,因此,不會被目的機器防火墻攔截玫膀,所以可以訪問矛缨。
解決問題
首先設(shè)置了 mysql
的配置文件,保證 mysql
可以被任何 ip
訪問:
[mysqld]
bind-address = 0.0.0.0
修改完配置文件重啟生效。
但為了安全考慮箕昭,防火墻的 3306
端口仍然是不開放外網(wǎng)訪問的誉简。
容器訪問宿主機的地址使用 eth0
的地址,即宿主機內(nèi)網(wǎng) ip
地址盟广。
運行 ipconfig
命令闷串,查看網(wǎng)絡(luò)的虛擬網(wǎng)橋相關(guān)信息。
注意:宿主機會把容器 ip
地址段當(dāng)成外網(wǎng) ip
筋量。(當(dāng)前說明是 centos7
環(huán)境)
編輯防火墻文件 /etc/firewalld/zones/public.xml
烹吵,添加下面 docker0
地址段到配置:
<rule family="ipv4">
<source address="172.18.0.0/16"/>
<accept/>
</rule>
重啟防火墻,docker
容器即可正常訪問宿主機端口桨武。
service firewalld restart
?? 如果有用到 docker-compose
命令肋拔,則會自動創(chuàng)建一個名為 br-"docker network id"
的虛擬網(wǎng)橋。
?? 此時同樣需要將虛擬網(wǎng)橋地址段配置到防火墻白名單呀酸,才能正常訪問凉蜂,添加配置:
<rule family="ipv4">
<source address="172.20.0.0/16"/>
<accept/>
</rule>
測試端口
在容器中測試宿主機端口是否可以連接,可以使用 wget 內(nèi)網(wǎng)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 #可以連接