在使用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.json
和composer.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都有非常不錯的生態,...