再進入docker volume之前,讓我們來看看 multi-stage dockerfile 這個寫dockerfile 的方式吧!
一樣又是getting-started這個範例...XD
Build image 的時候,要儘量讓image的檔案大小愈小愈好,而 image 的大小和 image layer 的數量有關,每使用 RUN
、COPY
等指令都會疊加新的一層 layer在舊有的 image上,故看前人編寫的dockerfile中,都可以看出使用shell tricks、或極力精簡架構、或一直刪除前一步驟的 artifacts 的習慣,這些作為都是在盡力縮小 image 的大小。
在 docker reference 中有提到,為減少映像的大小,也可以採取使用兩個Dockerfile,一個用於開發 (dockerfile.build),一個用於生產環境 (dockerfile),但要維護兩個 dockerfile,在實際上較為不理想。
若採用 Multi-stage builds,可解決以上的難處:在 multi-stage 的dockerfile 中,可以用多個 FROM
引用不同的映像(同時代表多個 stage),並在 stage 之間互相引用其他 stage 的 artifacts,藉此,可以在同一個 dockerfile 中達成開發和部署,也可以藉由移動artifact來減少映像檔的大小(只會用最後一個image,過程中使用的image的不會被納入image中)。
以上述的 getting-started 為例,在一開始使用了python:alpine 映像建立 base
,並 build 出/app/site
的 artifacts,接著用 node:12-alpine 建立 app-zip-creator
build出靜態的網頁,壓縮成zip檔app.zip
;在最後實際的環境使用nginx:alpine,並複製base
的/app/site
和app-zip-creator
的app.zip
,整份映像檔在build 的時候只會有 nginx
、/app/site
、app.zip
三個必要的部分,不會有開發時需要的node modules等等其他在部署時非必要的檔案,整份映像檔也因此變得更輕量,部署也會更快速。
我們可以使用FROM <image> AS <alias-name>
(記得去除腳括弧),幫映像取名為<alias-name>
。
要使用其他 stage 的 artifacts 時利用 COPY --from=<image-name> <item> <item> ..
便可以複製東西出來到當前的image中。
Best practices for writing Dockerfiles | Docker Documentation
Use multi-stage builds | Docker Documentation