Docker Linux 映像檔 容器

正確撰寫Dockerfile 製作最好用容器映像檔

2017-10-16
容器映像檔是容器技術堆疊時最基本的元件,本文將示範如何依照不同發行版本的基礎映像檔,加入所需的套件和功能,逐步一層層堆疊成特定用途的容器映像檔。然後介紹Dockerfile,並提供撰寫時所需注意的事項。

2. 新增檔案,例如執行「echo "Hello World!!!" > hello.html」指令。

3. 開啟另一個終端畫面,查看目前容器狀態,採用「docker ps」指令。

4. 找到執行中的Nginx容器ID,執行「docker commit CONTAINER_ID IMAGE_NAME」,原本啟動的容器便會儲存成映像檔。

5. 最後利用「docker history IMAGE_NAME」查看各個資料層,如圖5所示。


▲圖5 Docker Commit映像檔之差異。

從圖5中可看到新增hello.html的檔案大小正好為15 Bytes,以History看不出詳細內容,只有顯示sh程式,但使用Dockerfile卻能清楚看出。

因為容器的隔離性,所以在Host主機上可以同時執行多個容器,如圖6所示,同時執行著用Debian基礎映像檔所建立的Apache服務,以及BusyBox容器。


▲圖6 同時執行兩種發行版容器之示意圖。

Dockerfile介紹及最佳實踐

上面介紹了兩種產生Docker映像檔的方法,Docker Commit和撰寫Dockerfile,除此之外,還有Docker Hub Auto-build,但嚴格來說,仍算是撰寫Dockerfile,差別在於Docker Hub的公開映像檔中會標示為「Automated Build」,有助於搜尋和「docker search」排序。不過,筆者只推薦使用官方製作的公開映像檔,其建置的映像檔內容較安全無慮。

撰寫Dockerfile

建立Dockerfile須注意大小寫,且不具副檔名,必須完全一模一樣(亦可使用「docker build -f OTHERNAME .」指定其他檔名的Dockerfile),Dockerfile屬於文字檔案,可以使用任何編輯軟體撰寫,是以行為單位的指令和參數所組成,並以#標示為註解行,以下是簡單的Nginx Dockerfile範例:


一個Dockerfile必須以FROM作為開頭,後面參數為各種發行版的基礎映像檔,如Debian 8(Jessie)或是Windows作業系統的「microsoft/nanoserver」,亦可是自行製作的映像檔。

LABEL

此指令用來標註映像檔的Metadata,如作者、Email、映像檔描述等等,當透過「docker inspect IMAGE_ID」查看時,在「ContainerConfig」下的Labels中可查詢到相關資訊。

RUN

透過RUN來執行映像檔中所具有的命令或程式,包括套件安裝、建立目錄或執行程式產生設定檔等,其中RUN後面參數,可分成Shell形式和Exec形式(RUN ["命令", "參數"]),Shell形式是以Linux Bash Shell環境的執行方式,而Exec則是透過exec命令執行,差別在於exec執行完後便會登出。

從圖7中上下兩個映像檔之差異,便可看出Shell形式和Exec形式的不同。


▲圖7 以Shell和Exec形式建置映像檔之差異。

COPY

將本機上的檔案或目錄,複製到容器的絕對路徑中,例如「COPY ../../test.txt /data/test.txt」,本機來源檔案的路徑必須為當下目錄的相對路徑,而容器則必須使用絕對路徑。至於與ADD指令的差別在於,ADD的來源可以是網址或壓縮檔,若是壓縮檔會自動解壓縮到容器指定目錄,因此在製作基礎映像檔時,會將rootfs壓縮成tar.gz格式,此情境會使用ADD指令,一般情況建議使用COPY,避免有料想不到的情形發生。

EXPOSE

用來宣告映像檔會使用到的連接埠,上面範例為TCP 80 Port,若只開放UDP,則是80/udp,兩者皆宣告為EXPOSE 80,此EXPOSE指令目的是能讓「docker run -P IMAGE_ID」自動對應宣告的連接埠,不用特別指定。即便沒有使用EXPOSE,仍舊可以透過「docker run -p 80:80 IMAGE_ID」開通連接埠。

ENTRYPOINT

定義映像檔啟動成容器時,預設所要執行的程式或命令,前面範例是執行nginx網頁伺服器,與RUN指令一樣,支援Shell形式和Exec形式,官方建議啟動容器程式或命令的ENTRYPOINT使用Exec形式,其容器內程序是以PID 1運行,當容器程序停止時,可確保一併停止容器。若採用Shell形式,部分特殊程式有可能會無法正常停止(SIGTERM),導致容器無法完全退出,殘留程序仍舊占用著系統資源。

CMD

就跟ENTRYPOINT指令一樣,也是定義啟動為容器所要執行的程式或命令,但與ENTRYPOINT不同之處是,CMD可以在執行「docker run IMAGE_ID」的後頭加上指令或參數,覆蓋過原本CMD所定義的命令。例如當不想啟動nginx網頁伺服器,而是欲進入到容器,可輸入「docker run -ti nginx sh」,以sh取代nginx,當然與RUN和ENTRYPOINT指令一樣,支援Shell形式和Exec形式。同樣地,官方也建議採用Exec形式,理由同上。


追蹤我們Featrue us

本站使用cookie及相關技術分析來改善使用者體驗。瞭解更多

我知道了!