iT邦幫忙

2022 iThome 鐵人賽

DAY 6
0

Docker 的 Build Cache 機制,可以在 build image 的過程中得到加速,
今天讓我們來對它做點研究,瞭解如何在實際應用上帶來幫助。


重複 Build image

如果 D2 跟 D5 有跟著做的讀者,當你對相同的程式碼建置第二次時,會發現第二次的過程瞬間就完成了,快到不像有建置一樣,

Docker 確實有執行建置,然而,要說沒建置,也對,因為此時 Docker 並沒有建立出新的 image,

讓我們拿 D5 的建置過程來看看:

  • 第一次 build hello-world-server
$ sudo docker build . -t hello-world-server

Sending build context to Docker daemon  48.64kB
Step 1/6 : FROM node:16-slim
 ---> 572389d8c38d
Step 2/6 : WORKDIR /app
 ---> Running in dae5dd7b2627
Removing intermediate container dae5dd7b2627
 ---> 4541c7e49a33
Step 3/6 : COPY ./package*.json ./
 ---> 29534be2c19c
Step 4/6 : RUN npm ci
 ---> Running in aa9b89c42d52

added 57 packages, and audited 58 packages in 1s

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm notice
npm notice New minor version of npm available! 8.15.0 -> 8.19.2
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v8.19.2>
npm notice Run `npm install -g npm@8.19.2` to update!
npm notice
Removing intermediate container aa9b89c42d52
 ---> 582837243791
Step 5/6 : COPY . .
 ---> fb71c9523268
Step 6/6 : CMD ["npm", "start"]
 ---> Running in eda5c7a196a7
Removing intermediate container eda5c7a196a7
 ---> b33e04f2acb7
Successfully built b33e04f2acb7
Successfully tagged hello-world-server:latest
  • 第二次
$ sudo docker build . -t hello-world-server

Sending build context to Docker daemon  48.64kB
Step 1/6 : FROM node:16-slim
 ---> 572389d8c38d
Step 2/6 : WORKDIR /app
 ---> Using cache
 ---> 4541c7e49a33
Step 3/6 : COPY ./package*.json ./
 ---> Using cache
 ---> 29534be2c19c
Step 4/6 : RUN npm ci
 ---> Using cache
 ---> 582837243791
Step 5/6 : COPY . .
 ---> Using cache
 ---> fb71c9523268
Step 6/6 : CMD ["npm", "start"]
 ---> Using cache
 ---> b33e04f2acb7
Successfully built b33e04f2acb7
Successfully tagged hello-world-server:latest

Image Layer

建置出來的 Docker image,其實是一層一層的,稱之為 Image Layer
可以看到前面 Docker 輸出的過程,寫了 Step m/n,每一個步驟就會產生一層 Layer,

為什麼要有這個結構呢?這是一個容量與建置速度的最佳化,
不同 Image 之間,有可能前幾層都是相同的內容,既然已經知道內容相同,那儲存時就只要存一份並共用就好了,

同時建置時也不用每次都重建,直接拿已存在的相同 Layer 來接續建置就好了,
因此容量跟建置速度都可以藉此得到改善。


Build Cache

接下來我們可以在第二次的輸出中發現 ---> Using cache 的字樣,這代表了 Docker 在 Cache 中與這一層相同的內容,因此直接使用並跳到下一步,這裡的 Cache 就被稱為 Build Cache

(因此這裡 Build CacheBuild 是個名詞,用來形容這是建置過程的 Cache)

我們來做點嘗試:

Time

利用 time 指令來測測看建置速度差異:
(尚未建置 image 的狀態)

  • 第一次
$ time sudo docker build . -t hello-world-server

Sending build context to Docker daemon  48.64kB
Step 1/6 : FROM node:16-slim
 ---> 572389d8c38d
...
Step 6/6 : CMD ["npm", "start"]
 ---> Running in c166f0156483
Removing intermediate container c166f0156483
 ---> a35fdeba8e8c
Successfully built a35fdeba8e8c
Successfully tagged hello-world-server:latest

real	0m3.354s
user	0m0.032s
sys	0m0.007s
  • 第二次
$ time sudo docker build . -t hello-world-server

Sending build context to Docker daemon  48.64kB
Step 1/6 : FROM node:16-slim
 ---> 572389d8c38d
Step 2/6 : WORKDIR /app
 ---> Using cache
...
Step 6/6 : CMD ["npm", "start"]
 ---> Using cache
 ---> a35fdeba8e8c
Successfully built a35fdeba8e8c
Successfully tagged hello-world-server:latest

real	0m0.094s
user	0m0.021s
sys	0m0.017s

3.3 秒 => 0.09 秒
雖然不多,可以發現時間上有改善,
但因為我們的範例很小,自然就看不到多大的差異,

--cache-from

有時,Docker 並不會準確地檢查到 Cache,但已存在的 Image 確實有可以重複使用的地方,

這時我們就可以在建置時加入 --cache-from 這個參數,明確告訴 Docker 要使用什麼 Image 的 Cache 資料,

$ sudo docker build . -t hello-world-server --cache-from another-server

Best practices for writing Dockerfiles

Docker 官網也有針對 Build Cache 寫了一些建議,有興趣的讀者也可以進一步參考 Leverage build cache 這個區塊的內容。


上一篇
D5 - Hello World ft. Express
下一篇
D7 - Docker 概念架構
系列文
其實沒有那麼難 — Docker30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言