容器映像檔是容器技術堆疊時最基本的元件,本文將示範如何依照不同發行版本的基礎映像檔,加入所需的套件和功能,逐步一層層堆疊成特定用途的容器映像檔。然後介紹Dockerfile,並提供撰寫時所需注意的事項。
前面幾篇介紹過Docker容器生命週期的相關指令,企業導入容器技術的應用情境,以及Docker Volume和Docker Network的使用及運作原理,接著說明如何製作容器技術堆疊(技術棧)最基本的元件容器映像檔(Docker Image),以及撰寫Dockerfile的最佳實踐和注意事項。
認識Docker映像檔
Docker映像檔是用來建立執行時期的容器實例,就像是虛擬機映像檔,是唯讀的一個模板。之前談到過,執行「docker history ubuntu」,可列出映像檔每一資料層(Layer)的Dockerfile內容,顧名思義,映像檔是由Dockerfile一行定義一個資料層所建置出來。
如圖1所示,最底層是Linux作業系統的內核(Kernel),Linux啟動時會透過Boot Loader載入內核及initrd(統稱為bootfs,Boot File system),由於容器是共用內核,所以bootfs都是使用Host主機端,而rootfs則是Linux各種發行版本所內含的「/dev」、「/proc」、「/bin」等標準檔案系統,不同的Linux發行版所具備的rootfs也會有所差異。
|
▲圖1 映像檔資料層結構。 |
Debian可以透過debootstrap工具來建立這個rootfs資料層,Docker映像檔的基礎映像檔(Base Image)就是透過這樣工具,產製rootfs的tar檔案,再以scratch(空白映像檔,https://docs.docker.com/samples/library/scratch/)建立各種Linux發行版的基礎映像檔,如Debian(https://hub.docker.com/_/debian/)、BusyBox(https://hub.docker.com/_/busybox/)以及Alpine(https://hub.docker.com/_/alpine)等等,如圖2所示。
|
▲圖2 不同基礎映像檔之示意圖。 |
執行Debian映像檔後,「docker run -ti debian」會新增寫入層,便於操作容器之用,如圖3所示。
|
▲圖3 執行容器後的寫入層。 |
接著,依照不同發行版的基礎映像檔,加入所需套件和功能,逐步一層層堆疊成特定用途的容器映像檔,而不同發行版所依賴的套件管理工具也會有所不同,例如Debian是使用apt,CentOS則使用yum。
Dockerfile中每一行定義所製作出的資料層都是唯讀,當啟動執行成容器時,才會再疊上寫入層,如圖4所示,執行期間所增加的額外資料,只存在於容器中,容器一旦刪除,這些額外資料便會一併刪除,這部分與虛擬化映像檔是有差別的。
|
▲圖4 建立唯獨資料層與執行容器。 |
若想要將執行期間的資料保存下來,除了之前談到的Docker Volume方式,也可透過「docker commit CONTAINER_ID」另存成容器映像檔,但不建議以此方式來建立Docker映像檔。雖然目前此種方式已不會破壞資料層繼承結構,上層會參考到下層映像檔(Parent Image)的設計,讓「docker pull」只去下載變動過的資料層,無須從頭到尾重新下載,但對於版本管控紀錄以及可讀性方面,不如文字形式的Dockerfile方便,且在容器開發流程上,Dockerfile方式才能做到自動化。
不過,在練習撰寫Dockerfile過程,仍可以利用Commit方式自行摸索,但正式使用時,還是建議撰寫Dockerfile。
示範Docker Commit
使用Commit方式,並不會將掛載的Volume資料一併存放到映像檔中,務必留意。以下示範如何使用「docker commit」建立映像檔:
1. 啟動Nginx容器,執行「docker run -ti --rm nginx sh」指令。