Docker的大坑小窪

正在學習Docker,留着看看
轉自Docker的大坑小窪mysql

Docker成爲雲計算領域的新寵兒已是不爭的事實,做爲高速發展的開源項目,不免存在這樣或那樣的瑕疵。筆者最近在開發實戰中曾經跌進去一些坑,有些坑還很深,寫出來分享,至關因而在坑邊掛個警示牌,避免你們重蹈覆轍。話很少說,一塊兒來領略Docker的大坑小窪。sql

1.Docker中同種類型不一樣tag的鏡像並不是可互相替代

問題描述:

Docker中同種類型的鏡像,通常會用tag來進行互相區分。如Docker中的mysql鏡像,鏡像tag有不少種,有5.6.17,5.6.22,latest等。用戶的環境中若已經熟練使用mysql:5.6.17,並不表明用戶若是使用mysql:5.6.22,環境依舊工做。docker

緣由剖析:

不一樣tag同種類型的Docker鏡像,會由於如下的緣由致使鏡像差別。 (1).Docker鏡像內容不一樣。同種類型Docker鏡像的tag不一樣,很大程度上是由於鏡像中應用版本的差別。Dockerfile表明Docker鏡像的製做流程,換言之是Dockerfile的不一樣,致使Docker鏡像的不一樣。 (2).Docker鏡像的entrypoint.sh不一樣。entrypoint.sh表明容器中應用進程按照何種形式啓動,entrypoint.sh的差別直接致使應用容器的使用差別。舉例說明:mysql:5.6.17和mysql:5.6.22的entrypoint.sh存在很大差別,二者對於隔離認爲重要的環境變量的定義就不一致,使用的差別天然存在。json

解決方案:

不一樣tag的同類型鏡像做爲替代品時,需謹慎。查看Docker鏡像layer層的差別,查閱Dockerfile與entrypoint.sh的差別,能夠提供起碼的保障。ubuntu

2.不一樣時間段使用tag爲latest的鏡像,效果不盡相同

問題描述:

在一個時間點使用latest鏡像,應用容器運行正常;以後的另外一個時間點按照相應的Dockerfile,build出鏡像再運行應用容器,失效。學習

緣由剖析:

Docker官方關於同種類型Docker鏡像的latest標籤,並未永久賦予某一指定的Docker鏡像,而是會變化。舉例說明:某一個時間點ubuntu鏡像的latest標籤屬於ubuntu:12.04,以後的另外一時間點,該latest標籤屬於ubuntu:14.04,若Dockerfile在這兩個時間點進行build時,結果必然相異。緣由迴歸至上文的第一個坑。ui

解決方案:

慎用latest標籤,最好不用,Docker鏡像都使用指定的tag。雲計算

3.使用fig部署依賴性強的容器時出錯

問題描述:

使用fig部署兩個有依賴關係的容器A和B,容器A內部應用的啓動依賴於容器B內應用的完成。容器A內應用程序嘗試鏈接容器B內部應用時,因爲容器B內應用程序並未啓動完畢,致使容器A應用程序啓動失敗,容器A中止運行。spa

緣由剖析:

容器的啓動分爲三個階段,依次爲dockerinit、entrypoint.sh以及cmd,三個階段都會消耗時間,不一樣的容器消耗的時間不一,這主要取決於docker容器中entrypoint和command到底作了什麼樣的操做。如mysql容器B的啓動,首先執行dockerinit;而後經過dockerinit執行entrypoint.sh,因爲entrypoint.sh執行過程當中須要執行mysql_install_db等操做,會佔據較多時間;最後由entrypoint.sh來執行cmd,運行真正的應用程序mysqld。綜上所述,從啓動容器到mysqld的運行,戰線拉得較長,整個過程docker daemon都認爲mysql容器存活,而mysqld正常運行以前,mysql容器並未提供mysql服務。若是fig中的容器A要訪問mysql容器B時,雖然fig會簡單辨別依賴關係,讓B先啓動,再啓動A,當fig沒法辨別容器應用的狀態,致使A去鏈接B時,B中應用仍然未啓動完畢,最終A一場退出。blog

解決方案:

對自身環境有起碼的預估,如從容器B的啓動到容器B內應用的啓動完畢,所需多少時間,從而在容器A內的應用程序邏輯中添加延時機制;或者使得A內應用程序邏輯中添加嘗試鏈接的機制,等待容器B內應用程序的啓動完畢。 筆者認爲,以上解決方案只是緩解了出錯的可能性,並未根除。

4.Swarm管理多個Docker Node時,Docker Node註冊失敗

問題描述:

筆者的Docker部署方式以下:在vSphere中安裝一臺ubuntu 14.04的虛擬機,在該虛擬機上安裝docker 1.4.1;將該虛擬機制做vm使用的鏡像;建立虛擬機節點時經過該鏡像建立,從而虛擬機中都含有已經安裝好的docker。若是使用Swarm管理這些虛擬機上的docker daemon時,僅一個Docker Node註冊成功,其餘Docker Node註冊失敗,錯誤信息爲:docker daemon id已經被佔用。

緣由剖析:

若是多個Docker Host上的Docker Daemon ID同樣的話,Swarm會出現Docker Node註冊失敗的狀況。原理以下: (1).Docker Daemon在啓動的時候,會爲自身賦一個ID值,這個ID值經過trustKey來建立,trustkey存放的位置爲~/.docker/key.json。 (2).若是在IaaS平臺,安裝了一臺已經裝有docker的虛擬機vm1,而後經過製做vm1的鏡像,再經過該鏡像在IaaS平臺上建立虛擬機vm2,那麼vm1與vm2的key.json文件將徹底一致,致使Docker Daemon的ID值也徹底一致。

解決方案:

(1).建立虛擬機以後,刪除文件~/.docker/key.json ,隨後重啓Docker Daemon。Docker Daemon將會自動生成該文件,且內容不一致,實現多Docker Host上Docker Daemon ID不衝突。 (2).建立虛擬機鏡像時,刪除key.json文件。 建議使用方案二,一勞永逸。

5.Docker容器的DNS問題

問題描述:

Dockerfile在build的過程當中只要涉及訪問外網,所有失效。

緣由剖析:

用戶在建立docker容器的時候,不指定dns的話,Docker Daemon默認給Docker Container的DNS設置爲8.8.8.8和8.8.4.4。而在國內這個特殊的環境下,這兩個DNS地址並不提供穩定的服務。如此一來,只要Docker Container內部涉及到域名解析,則當即受到影響。

解決方案:

(1)使用docker run命令啓動容器的時候,設定–dns參數,參數值爲受信的DNS地址,必須保證該DNS地址Docker Container可訪問。 (2)若是按以上作修改,適用於docker run命令。而使用docker build的時候實際上是多個docker run的疊加,因爲docker build沒有dns參數的傳入,所以docker container不能保證域名的成功解析。

解決方案:

啓動Docker Daemon的時候設定DOCKER_OPTS,添加–dns參數,這樣能夠保證全部的docker run默認使用這個DNS地址。   以上這些坑深淺不一,但基本上還都集中在Docker外圍的配置,行爲模式等方面。

最近雖然在Docker的坑裏摔得鼻青臉腫,可是「Docker虐我千百遍,我待Docker如初戀」的情懷始終不變,這貨必定是雲計算的將來,我堅信。前方的大坑,我來了,duang。。。 。。。

相關文章
相關標籤/搜索