CodeFarmer 技術週報 #17 - 初學 Kubernetes (1):Docker 快速入門
近期工作上要碰到使用 K8s 做部署的需求,不過在那之前能把 Docker 這個前置知識打穩一點可能在理解 K8s 中各種眼花撩亂的元件前會更好,因此第一篇將會是一個快速理解各種 Docker 概念的筆記
嗨嗨大家,歡迎閱讀不小心遲了一天發的第 17 期的 CodeFarmer 真。技術週報!
你沒看錯,這期終於重返技術學習的懷抱,主要是因為在新工作的這個 sprint 中,被指派要開始碰部署相關的任務,其實也就是把先前做的差不多的前端專案翻新部署到測試環境上,而因爲公司各種 CD 服務都是使用 Kubernetes (簡稱 K8s) 來做,因為先前沒有任何相關知識實在有點慌。
遙想幾年前在團隊中常跟 DevOps 工程師說有一天也想學部署的玩意,他回道:「那有什麼難的,就是設定檔複製貼上改一下參數就完事了。」時至今日在手無寸鐵之下就被推上戰場時,翻著各個專案的 YAML 設定檔,比對不同環境、tech stack 部署的相同與相異處,剪剪貼貼好像看起來有點樣子,看似能動但心裡總是不踏實。
因此突然有個靈感是可以用週報開一個新系列來做一下初學 K8s 的筆記,算是逼自己每週固定惡補一下知識點,如果你剛好也有興趣學習歡迎一起討論交流,若是這方面的高手也請不吝 review 與指教,有任何錯誤或可以講的更好的地方也歡迎補充。
雖說是要學 K8s,不過在那之前能把 Docker 這個前置知識打穩一點可能在理解 K8s 中各種眼花撩亂的元件前會更好,因此第一篇將會是一個快速理解各種 Docker 概念的筆記。雖然網路上已經有許多詳細深入的 Docker 學習,但如果需要一個速成版筆記或許這篇會是一個選擇,在學習過程中找到不少很棒的學習資源,就統一附在最下方。
本篇目錄
Docker 簡介
VM vs Container
Docker 基本三元素
什麼是 Dockerfile?
實際演練
Docker 簡介
Docker 是一個用來 build、run、share 各種應用程式 (後面簡稱 app) 的平台,就像他的 logo 一樣,可以把各種 app 打包成一個個貨櫃,這隻鯨魚就可以幫我們把 app 載到各種地方。
想像今天沒有 Docker 的話,如果你需要開發一個前後端分離的全端專案,那你可能每次在不同開發機器上配置環境時就要像上圖一樣安裝各種套件與做各種設定。甚至未來要部署到測試環境、正式環境時,你也要從頭進到機器裡再操作一遍,也可能因為環境不同導致有不同問題需要 debug。
有了 Docker 後就可以更方便地將你做好的這個 app 打包並部署到各個環境中。
VM vs Container
先說 Docker 並不等於 Container,Docker 是一種容器化技術的實現、解決方案與平台,而容器是一種虛擬化技術
VM (虛擬機) 的環境間是相互隔離的,讓你可以在同一台機器上運行各種不同的作業系統 (OS)。但缺點是啟動速度慢、資源浪費的問題。
大部分狀況下,我們只是要在某個環境下跑起某個 app,並不需要啟一整個 OS 來運行,因此容器化的做法在這種場景下就相當適合。
容器與 VM 的不同是他在運行時不需要啟動許多的 OS,而是直接用主機本體的運算資源,所以啟動速度相比之下快上不少。使用資源少所以可以在同一台主機上運行更多的 app。
Docker 基本三元素
Image (映像檔、鏡像)
唯獨的模板,可以用來創建容器
Container (容器)
Docker 的運行實例 (instance),提供一個獨立且可移植的環境,可以在這個環境中運行 app
補充:Image vs Container 的關係
以物件導向語言概念來解釋的話,可以想成 image 就是 class,而 container 是 object 或是 instance。
白話版 (參考下圖)
Image 就像一個食譜,詳細描述如何製作一道菜。
Container 則是你根據食譜做出來的那道菜。
你可以根據食譜做出很多道菜,而這些菜都是根據同一個食譜去做出來的,只要嚴格按造食譜去做就都能做出許多完全一樣的菜。
你也可以把食譜分享給其他朋友,讓他做出一樣的菜,也就是把它放到 Registry 上 (push),讓別人去下載 (pull) 下來。
Registry (倉庫)
用來儲存 image 的地方
最流行的是 Dockerhub,可以想像是 Docker 世界中的 Github,可以在這裡直接下載現成的 image 服務,也可以上傳到自己做好的 image 到上面供別人共享與複用
Docker 架構
Docker 的底層架構採用 client-server 模式,client 與 server 間採用 socket 或 RESTful API 通訊
參考上圖中的 docker daemon 就是 server 端的各種監聽 process,負責處理 Docker CLI 發出的命令 (像是 docker run、docker build 等)、管理 Docker 資源 (詳細底層知識可以參考這篇精彩的文章)
docker client 負責向 daemon 發送請求,daemon 收到請求後,處理後將結果返回給 client
什麼是 Dockerfile?
所謂容器化顧名思義就是將 app 打包成容器,並在容器中運行這個 app 的過程。
那這件事要怎麼做到呢?就需要依靠 Dockerfile 這個設定檔來讓 Docker 知道怎麼打包,會像是以下的步驟:
創建一個 Dockerfile,告訴 Docker 構建成 app image 的步驟和設定
使用 Dockerfile 來 build 出 image
使用 build 好的 image 來創建容器和運行容器
實際演練
最後講了這麼多基本概念,就實際用一個簡單的 hello world 來實際練習下吧。
首先會需要先安裝 Docker Desktop 這個應用程式並把它 run 起來,這部份可以參考各種教學文件完成。
有了 Docker 的環境後就可以實際建立一個專案來試試看,參考以下指令建一個專案:
$ mkdir hello-docker
$ cd hello-docker
$ touch index.js
一個相當基本的資料夾裡面有個 JavaScript 檔案,可以用 VS Code 開啟後簡單隨便加一段 console.log 即可。
接著可以安裝 VS Code 的 Docker 這個 extensions,在撰寫 Dockerfile 時會更方便。
新增一個 Dockerfile 的檔案,並包含以下內容:
FROM node:22-alpine
COPY index.js /
CMD node /index.js
這些設定的意思分別是下面這樣:
使用官方的 Node.js 22 版本的 Alpine Linux 發行版作為 base image (備註:alpine 是一種非常輕量的 Linux Distribution)
將本機的 index.js 複製到容器的根目錄中
指定容器啟動時要執行的指令
Dockerfile 都設定好之後可以在 terminal 上執行這個指令來 build image:
docker build -t hello-docker .
build 完後可以用以下指令確認 build 出來的 image 資訊 (以下兩種都可以):
$ docker image ls
$ docker images
最後就可以實際來運行看看:
$ docker run hello-docker
# or by image id
$ docker run 7f9ba56d3d10
運行後就可以在 terminal 上看到你剛在 index.js 中寫的 console.log 訊息,可喜可賀!
參考資源與延伸閱讀
以上就是這期週報的所有內容了。若內容有什麼問題與討論也都歡迎透過以下管道與我交流,或直接留言與回覆這封電子信我也能收到:
Email:codefarmer.tw@gmail.com