最近在專案中使用到docker和dubbo,想在docker中執行乙個服務並把該服務自身的資訊發布到dubbo註冊中心。
剛開始測試時候將所有容器都放在同一臺主機中,測試過程很順利,但是當進行docker主機擴充套件,將容器部署在不同的主機時候,就發現乙個奇怪的現象:應用之間除錯不通了。
這裡對具體問題解釋一下:dubbo提供了乙個方便的服務發現機制,每個服務(這裡稱為提供者)只要向dubbo註冊中心註冊過,註冊中心就會將服務的位址傳送給同樣在註冊中心註冊的服務呼叫方(這裡稱為消費者),之後即使dubbo註冊中心掛了也不影響服務的呼叫。
解決方案
設定容器的ip與主機ip在同一網段內,使容器ip可直接訪問(會占用大量的ip位址,且ip會限制在同一網段,在生產環境中往往不可能)。
通過複雜的iptables路由規則,通過多層橋接方式打通網路(此法是可行的,也是今後要考慮的,但是操作起來略麻煩)。
對dubbo進行擴充套件,擴充套件dubbo protocol配置,增加配置項publish host、 publish port,對應主機的ip和port,並且在註冊服務時將主機的ip和port寫到註冊中心。(這種方法需要對dubbo進行擴充套件,不太建議)
以上三種方法都有一定的侷限性和複雜性,我就想能否有更加簡單便捷的方法可以解決這個問題。
最後查閱資料時發現dubbo是先通過hostname(通過ping hostname)來得到本機的ip位址的,換句話說也就是dubbo是讀取/etc/hosts檔案得到主機的ip的,又因為docker在重啟時候ip位址會重置,即/etc/hosts檔案在docker重啟時候會被重置,所以考慮在docker啟動的指令碼中動態修改/etc/hosts檔案,從而改變docker主機的ip。
實施start.sh
#!/bin/sh
sed -i "s/.*$(hostname)/$docker_ip $(hostname)/" /etc/hosts
在啟動docker時候將宿主機的ip作為乙個環境變數傳遞給docker主機,然後docker主機中將執行上面的start.sh指令碼,該指令碼的作用是在啟動服務之前,通過查詢/etc/hosts檔案把現有的docker主機名對應的ip修改為宿主機的ip,從而使得註冊到dubbo中心的是宿主機的ip和埠。
一切都似乎沒問題,然後在執行的時候卻出現乙個意想不到的錯誤:
sed: cannot rename /etc/sed8dbrgm: device or resource busy
原來/etc/hosts檔案是在宿主機掛載到docker中,所以使用sed/awk等命令時候將導致裝置或者資源忙的錯誤。
既然不能直接修改原來的檔案,那麼就變通一下,把原來的檔案複製乙份,通過修改複製後的檔案,然後通過cat複製檔案重定向到/etc/hosts去,問題得到解決!
新的指令碼如下:
start.sh
#!/bin/sh
cp /etc/hosts /etc/hosts.temp
sed -i "s/.*$(hostname)/$docker_ip $(hostname)/" /etc/hosts.temp
cat /etc/hosts.temp > /etc/hosts
摘自:
Docker容器跨主機通訊
兩台主機上的docker容器直接通過ip位址進行通訊 各項配置如下 docker version 1.13.1 ip資訊根據個人需求部署 主機1的ip位址為 192.168.1.128 主機2的ip位址為 192.168.1.129 為主機1上的docker容器分配的子網 172.17.1.0 24...
docker跨主機容器通訊
docker 網路模式詳解 路由器位址192.168.1.1用route n檢視 parent enp7s0的乙太網名用ifcofig查詢 apt install net tools iputils ping ydocker network create driver macvlan subnet ...
Docker容器跨主機通訊
預設情況下docker容器需要跨主機通訊兩個主機節點都需要在同乙個網段下,這時只要兩個docker容器的宿主機能相互通訊並且該容器使用net網路模式,改實現方式為網橋模式通訊 除此之外我們還可以通過使用第三方工具為不同主機間建立乙個覆蓋網路,使之能夠跨節點通訊,這裡將使用flanneld實現 建立 ...