docker學習之雜談

docker學習之雜談

docker,離我第一次“近距離”接觸已過去兩年有餘,這次爲追趕潮流再次學習一番,此文記錄自己對docker的一些認識和見解。

我對docker的認識

docker,本質上我認爲是一個虛擬化技術,與虛擬機類似,虛擬機可以在宿主機上模擬完整的硬件環境,從而可以獨立安裝操作系統,docker則是在宿主機上模擬一個完整軟件環境,從而達到獨立運行應用程序的目的。這種模擬完整軟件環境用於運行特定應用程序的技術,被稱爲容器技術,docker是其中最閃耀的一種。

鏡像與容器

一般情況下,可以設想我們如何從零開始部署一個Node.js服務:

  1. 購買虛擬主機,即在電腦上安裝操作系統
  2. 安裝Node
  3. 上傳代碼
  4. 安裝npm依賴
  5. 通過Node啓動服務

上述5步中的每一步,都依賴其上一步且作爲下一步的依賴,docker中這每一步依賴的“實體”,稱之爲鏡像,其中第一步的依賴是docker的鏡像基礎"Kernel"。5個步驟的其中任意步都產生了一個獨一無二的鏡像,用一個唯一ID標識,而第五步產生的鏡像是一個階段性的收穫,可用於後面運行容器。當然第二步也有一個階段性收穫,可以作爲其他Node環境的基礎鏡像。

鏡像是一層疊一層且的只讀實體,而容器則是在鏡像的基礎上再加上一個動態可寫的層,鏡像好比如在一臺裸機上安裝軟件,每安裝一個軟件都生成一個鏡像,容器則是在安裝完的機器上運行軟件。

docker的核心優勢

docker的核心優勢在於部署,特別是複雜場景下的部署,假設我們一個應用程序需要獨立運行10個實例,即需要在10臺獨立的機器上部署。如果沒有docker,我們需要分別對每一臺機器安裝一系列的環境軟件,隨後上傳代碼再啓動服務,而在安裝一系列環境軟件時,有可能遇到一些奇奇怪怪的問題,然後浪費數小時,10臺機器都需要重複這樣的操作,甚至遇到不同的問題,這對運維來說是苦不堪言。

苦不堪言還沒完,當一次部署完成後,由於預期流量將繼續增加導致需要增加10臺機器,運維的痛苦x2,又或者預期流量將下降,只需要5臺機器,那麼空出來的5臺機器又希望用來部署其他業務,這對運維來說同樣是一個痛苦的事。

而docker的出現能夠很好應對上述場景,10臺甚至更多機器只需要安裝docker,然後在本地將需要部署的服務構建成一個docker鏡像發佈到10臺機器上,繼而運行即可,需要增加或減少機器也都變成分分鐘的事情,運維高高興興,再也不需要加班。

使用docker,每臺機器不會受到業務服務部署所帶來的環境影響,比如A業務服務使用Node.js 6.x版本,而B業務服務使用Node.js 8.x版本,如果一臺機器先部署了A服務,後面由於流量減少空閒出來用於部署B服務,環境中就遺留了A服務的Node.js 6.x版本。使用docker則完全沒有這種問題。

docker的適用性

前面講了docker的核心優勢,但並不是所有公司都應該使用docker化部署技術,主要考慮以下幾點:

  • 學習成本

如果沒有獨立運維人員,作爲一個開發,也許傳統的機器部署完成的還不錯,但要轉向docker化部署,需要一定的學習成本,甚至可能學不好

  • 性能損耗

docker作爲一種虛擬化技術,在其中運行應用服務肯定有性能損耗,到底損耗10%、20%又或者是30-40%,我並沒有嚴謹的數字

  • 邊際成本問題

邊際成本主要是針對規模問題,比如公司唯一核心業務全部部署在一臺2核4G的服務器上,預期未來兩年都夠使用,這種情況下搞docker化,那麼成本就是這一個業務一臺機器均攤,但如果公司業務多、機器多,那麼docker化這一套,成本平均到每臺機器上,就非常划算

上訴講到三點,在現實情況中作爲決策者最需要考慮的是最後一點,作爲開發就無所謂。之所以寫這一部分,就是因爲我曾在一個創業公司中深有體會,總共就兩臺生產機器,分別部署兩個不同業務,自己當時覺得去搞什麼docker化部署,有點笑話,所以兩年內都沒怎麼接觸docker。

docker實操

由於自己是做Node.js後臺,且對docker的基本概念還有記憶,按照Node.js提供的docker部署指南操作,嘗試將博客項目改成docker部署。

主要分爲以下幾步:

  • 安裝docker

按照官方文檔,在centos系統上安裝docker-ce,沒有遇到任何問題。

  • 下載node.js鏡像

使用命令docker pull node:8.12.0,下載Node鏡像,由於“你懂的”的原因,可能會很慢甚至無法完成

  • 編輯Dockerfile
FROM node:8.12.0

WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD ["npm", "start"]

- 編輯.dockerignore

.git
node_modules
log
  • 構建鏡像

docker build -t amsimple/blog .

  • 運行容器

docker run -d -p 8080:8080 --name blog --add-host=docker.host:172.17.0.1 amsimple/blog

實操問題

實操的過程雖不復雜,但並非一帆風順,其中有遇到一些問題,在此寫出來供大家參考。

無法訪問本機mysql

經費有限,自己mysql服務與博客項目在同一臺機器上,且mysql監聽的是127.0.0.1地址,在初次docker build與run之後發現應用會異常退出,查明是mysql無法連接導致。

故將mysql改爲監聽0.0.0.0,同時修改應用配置文件將連接mysql的host改爲docker.host,然後在啓動容器時通過--add-host將docker.host賦值爲docker在機器上的網橋地址。

另外mysql默認不允許遠程訪問,需要在mysql中使用GRANT ALL PRIVILEGES...進行授權。

拒絕連接

docker容器run成功後,用curl localhost:8080會提示拒絕連接,這個問題是因爲容器中應用啓動時監聽ip爲127.0.0.1,而容器外部訪問容器需要通過網橋,導致無法從外部訪問到服務,提示拒絕連接。

此問題,通過修改應用啓動時綁定IP爲0.0.0.0即可。

兩年前,自己實操docker練習的時候,一直在用iptables整網絡TCP包轉發相關內容,不知道是當時選擇的教程有問題還是現在版本的網絡支持更加智能化,這次完全不需要管網絡這一塊,就可以很輕鬆的完成一次docker化部署。

日誌文件

博客項目的訪問日誌是用寫文件方式實現的,但使用docker化部署後,文件到了容器中,對後續查看和分析挺不友好。

這個問題目前暫未解決,但以目前的認知水平,覺得有以下方案:

  1. 通過docker volumes相關特性,實現容器與主機共享日誌文件,這個針對規模化docker部署沒有什麼幫助
  2. 繼續在容器內部寫日誌,通過腳本每天定時整理與收集
  3. 引入日誌系統,採用網絡方式寫日誌,增加複雜度但能夠應對規模化的docker部署

日誌文件所體現的問題,本質上是容器運行過程中的內容產出應該如何處理,比如使用docker化的mysql、redis等都有類似問題。

自動部署

單臺機器在沒有使用docker部署前,自己通過git-webhook + shell腳本也實現了一個不那麼可靠的自動部署,但這裏提到的自動部署,主要是針對多機器的自動部署,而不是單臺機器自動部署。

這個問題目前暫未解決且客觀條件不充分(窮),同時必要性也沒那麼強,但docker化部署後,後續的自動化具體應該採用什麼解決方案,以及面對真正的複雜場景,方案是否仍舊適用,自己並沒有經驗,無法發表意見。

從這裏再次看出來,docker化部署真正的價值還是需要規模化才能體現,如果只有個位數的機器,折騰學習一下還行,真正使用感覺並沒有創造多少價值。

總結

自己目前不一定要用docker來部署博客,但這次docker化部署,給自己帶來更多其他的思考,比如上述的日誌文件與自動部署問題。這些思考可以說與docker沒有關係,它是關於服務與架構設計的思考,路漫漫其修遠兮,吾將上下而求索。

通過學習和簡單實操,感覺docker是一個非常好的東西,我希望自己能真正用上它,用會它,用好它,而不是像現在這樣,當成一個輕量級虛擬機使用,下一次再學些k8s知識,看是否能達到自己心中docker使用合理的那根線。

博客原文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章