利用構建快取機制縮短Docker映象構建時間

2021-09-12 17:29:17 字數 4466 閱讀 6869

在使用docker部署php或者node.js應用時,常用的方法是將**和環境映象打包成乙個映象然後執行,一些雲廠商提供了非常便捷的操作,只需要把我們的**提交到vcs上,然後它們就會幫我們拉取**並根據**包內的dockerfile構建我們的映象然後部署到集群裡。

php和node.js都有非常不錯的生態,有各種各樣的包,但是一旦引入的包多了我們的專案內的檔案就會變得非常多,所以在使用vcs協作的時候我們都會忽略掉依賴包目錄(node_modules / vendor)。但是我們忽略了包目錄後在構建映象的時候就要使用composer或者npm把包重新裝回去,所以dockerfile大概長這樣

from node

copy . /src

run cd /src && npm install

這樣看起來沒什麼問題,但是如果包一旦多起來安裝的時候需要花費很長的時間,修復緊急bug的情況下等待的時間就是煎熬,那我們有沒有什麼辦法能讓這個過程更快一些呢?

我們知道docker構建是分層的,一條指令一層,在沒有帶--no-cache=true指令的情況下如果某一層沒有改動,docker就不會重新構建這一層而是會使用快取,先來看看docker官方文件的描述

簡單來說就是如果第n層有改動,則n層以後的快取都會失效,大多數情況下判斷有無改動的方法是判斷這層的指令和快取中的構建指令是否一致,但是對於copy和add命令會計算映象內的檔案和構建目錄檔案的校驗和然後做比較來判斷本層是否有改動。

最理想的情況下,我們希望package.json或者composer.json變動的時候會重新的安裝包,在沒有變動的情況下使用快取縮短構建時間。

了解上面的規則後我們再來看看上面那個dockerfile,如果我們不修改任何**的話第二次構建也是能使用快取的,但是如果我們修改了**,copy . /src這層的快取就會失效,同時下一層的快取也會失效。但是大多數情況下,重新構建映象就意味著**有修改,但是package.jsoncomposer.json這兩個檔案並不會頻繁的修改,所以我們需要把這兩個檔案以及install的操作分離出來,所以有

from node

copy package.json /src/package.json

run cd /src && npm install

copy . /src

package.json裡面寫乙個依賴包

}

然後再寫乙個index.js

然後我們進行第一次構建,看看docker history的輸出

lin2ur:~ lin2ur$ docker history demo

image created created by size comment

3c913c9e997b 6 seconds ago /bin/sh -c #(nop) copy dir:e3c12f06720cf5f3b… 1.6mb

21373087419a 6 seconds ago /bin/sh -c cd /src && npm install 3mb

64896ee5240d 14 seconds ago /bin/sh -c #(nop) copy file:87de28b86afd2c1c… 53b

把每一層的image id和dockerfile裡面的指令對應起來就是

64896ee5240d => copy package.json /src/package.json

21373087419a => run cd /src && npm install

3c913c9e997b => copy . /src

現在我們來修改一下index.js模擬我們業務**變動然後再進行構建

lin2ur:~ lin2ur$ docker history demo

image created created by size comment

5d697905ad0a 6 seconds ago /bin/sh -c #(nop) copy dir:d698db67dac047bd2… 1.6mb

21373087419a 4 minutes ago /bin/sh -c cd /src && npm install 3mb

64896ee5240d 4 minutes ago /bin/sh -c #(nop) copy file:87de28b86afd2c1c… 53b

可以看到除了最上一層外其他兩層的image id是沒有變化的,再來看看docker build命令的輸出

lin2ur:~ lin2ur$ docker build --rm -f "dockerfile" -t demo .

sending build context to docker daemon 1.902mb

step 1/4 : from node

---> c63e58f0a7b2

step 2/4 : copy package.json /src/package.json

---> using cache

---> 64896ee5240d

step 3/4 : run cd /src && npm install

---> using cache

---> 21373087419a

step 4/4 : copy . /src

---> 5d697905ad0a

successfully built 5d697905ad0a

successfully tagged demo:latest

可以看到步驟2和3都使用了快取,比第一次構建的時間縮短不少。現在我們在package.json裡面再加乙個包模擬依賴包變動

lin2ur:~ lin2ur$ docker history demo

image created created by size comment

020ce95b1987 29 seconds ago /bin/sh -c #(nop) copy dir:ea4d7afd475895520… 1.6mb

d9697dfc7022 31 seconds ago /bin/sh -c cd /src && npm install 3mb

71d8a2fb458a 38 seconds ago /bin/sh -c #(nop) copy file:87bd25345a96e6b3… 51b

這次底下兩層的image id都變了,意味著沒有使用快取,再來看看docker build命令的輸出

lin2ur:~ lin2ur$ docker build --rm -f "dockerfile" -t demo .

sending build context to docker daemon 1.902mb

step 1/4 : from node

---> c63e58f0a7b2

step 2/4 : copy package.json /src/package.json

---> 71d8a2fb458a

step 3/4 : run cd /src && npm install

---> running in ce424d6af936

step 4/4 : copy . /src

---> 020ce95b1987

successfully built 020ce95b1987

successfully tagged demo:latest

由於第二層的package.json改動導致這層及後續的快取失效,然後重新安裝包,實現了我們希望的結果。

利用構建快取機制縮短Docker映象構建時間

在使用docker部署php或者node.js應用時,常用的方法是將 和環境映象打包成乙個映象然後執行,一些雲廠商提供了非常便捷的操作,只需要把我們的 提交到vcs上,然後它們就會幫我們拉取 並根據 包內的dockerfile構建我們的映象然後部署到集群裡。php和node.js都有非常不錯的生態,...

利用構建快取機制縮短Docker映象構建時間

在使用docker部署php或者node.js應用時,常用的方法是將 和環境映象打包成乙個映象然後執行,一些雲廠商提供了非常便捷的操作,只需要把我們的 提交到vcs上,然後它們就會幫我們拉取 並根據 包內的dockerfile構建我們的映象然後部署到集群裡。php和node.js都有非常不錯的生態,...

利用構建快取機制縮短Docker映象構建時間

在使用docker部署php或者node.js應用時,常用的方法是將 和環境映象打包成乙個映象然後執行,一些雲廠商提供了非常便捷的操作,只需要把我們的 提交到vcs上,然後它們就會幫我們拉取 並根據 包內的dockerfile構建我們的映象然後部署到集群裡。php和node.js都有非常不錯的生態,...