Docker鏡像構(gòu)建速度優(yōu)化實現(xiàn)
背景
在最近臨時支持的項目中,發(fā)現(xiàn)項目的構(gòu)建流程耗時比較長,嚴(yán)重的影響了開發(fā)的進(jìn)度。參照文檔要發(fā)測試環(huán)境的時候,發(fā)現(xiàn)10分鐘過去了還沒有發(fā)布完成。項目是通過Docker
來構(gòu)建鏡像部署的,所以想看看有沒有什么方案,可以對Docker
鏡像構(gòu)建進(jìn)行優(yōu)化。
現(xiàn)狀
Dockerfile
是長這樣子的:
Dockfile文件分析
以下主要分析Dockerfile
構(gòu)建過程中主要執(zhí)行的操作
一、基礎(chǔ)鏡像選擇
首先定義了一個基礎(chǔ)鏡像FROM node:20.18.1-alpine AS base
,這里選擇了基于Alpine
系統(tǒng)的Node.js
版本20.18.1
作為基礎(chǔ)鏡像。
二、依賴安裝階段(deps)
基于
base
鏡像創(chuàng)建了deps
鏡像。執(zhí)行
RUN apk add --no - cache libc6 - compat
,這是在Alpine
系統(tǒng)下安裝libc6 - compat
庫,--no - cache
表示不使用緩存。將
package.json
、yarn.lock*
、package - lock.json*
、pnpm - lock.yaml*
復(fù)制到當(dāng)前工作目錄(/app)
。根據(jù)不同的
lock
文件類型進(jìn)行依賴安裝:如果存在yarn.lock
文件,執(zhí)行yarn --frozen - lockfile
,這是使用Yarn
安裝依賴并且確保使用lock
文件中的版本,以保證可重復(fù)性。如果存在package - lock.json
文件,執(zhí)行npm ci
,這是使用npm
安裝依賴并且確保按照package - lock.json
中的版本精確安裝。如果存在pnpm - lock.yaml
文件,先全局安裝pnpm(yarn global add pnpm)
,然后執(zhí)行pnpm i --frozen - lockfile
,同樣是按照lock
文件安裝依賴。如果沒有找到任何lock
文件,則輸出Lockfile not found.
并以錯誤碼1
退出。
三、構(gòu)建階段(builder)
基于
base
鏡像創(chuàng)建builder
鏡像。從
deps
鏡像復(fù)制/app/node_modules
到當(dāng)前工作目錄下的node_modules
。復(fù)制當(dāng)前目錄
(.)
下的所有文件到/app
。執(zhí)行
yarn build:test
,可能是使用Yarn
構(gòu)建測試版本的項目。
四、運行階段(runner)
基于
base
鏡像創(chuàng)建runner
鏡像。設(shè)置環(huán)境變量
NODE_ENV為production
,表示生產(chǎn)環(huán)境。從
builder
鏡像復(fù)制/app/public
到當(dāng)前工作目錄下的public
。從
builder
鏡像復(fù)制/app/.next/standalone
到當(dāng)前工作目錄下從
builder
鏡像復(fù)制/app/.app/.next/static
到當(dāng)前工作目錄下的.next/static
構(gòu)建鏡像
通過運行Docker build
的命令,我們可以看著在構(gòu)建鏡像的過程中,主要做了什么操作,每個操作耗時分別是多少:
可以看出,Docker
鏡像打包過程總共花費了614.6s
,主要耗時集中在以下幾個操作上:
[internal] load metadata for docker.io/library/node:20.18.1-alpine
: 4.4s=> [internal] load build context
: 23.8s=> transferring context: 712.33MB
: 23.8s=> [deps 1/4] RUN apk add --no-cache libc6-compat
: 3.0s=> [deps 4/4] RUN if [ -f yarn.lock ]; then yarn --frozen-lockfile; elif [ -f package-lock.json ]; then npm ci; eli
: 258.1s=> [builder 2/4] COPY --from=deps /app/node_modules ./node_modules
: 35.9s=> [builder 3/4] COPY . .
: 4.7s=> [builder 4/4] RUN yarn build:test
: 234.2s
優(yōu)化
之前沒有太多的Docker
鏡像打包經(jīng)驗,都是直接build
寫好的Dockerfile
或者是基于開源的Dockerfile進(jìn)行定制化開發(fā)(復(fù)制其他項目的拿過來改一下??),所以搜了一下看看都有哪些優(yōu)化的方案。單純從Docker
鏡像打包來看,可以從以下幾個方向入手:
使用更小的基礎(chǔ)鏡像
多階段構(gòu)建
(Multi-stage Builds)
利用緩存加速構(gòu)建
減少鏡像層數(shù)
使用
.dockerignore
文件分層打包
(Layered Packaging)
靜態(tài)二進(jìn)制文件和“臨時”基礎(chǔ)映像
因為當(dāng)前的項目已經(jīng)做了1、2、6,所以我們還可以從4、5、7這三個方面考慮。
優(yōu)化一:減少文件復(fù)制的時間
通過添加
.dockerignore
文件,過濾掉一些非必要的文件,來減少文件復(fù)制的時間。我們看到之前的Dockerfile里,有一個復(fù)制
node_modules
的操作,花費了35.9s
,可以想辦法把這個去掉。
基于以上兩點,對項目文件以及Dockerfile
進(jìn)行修改.
一、添加.dockerignore文件
內(nèi)容如下:
node_modules .next src/.DS_Store .vscode .husky
二、Dockerfile調(diào)整
三、構(gòu)建看效果
我們可以看到,=> [builder 3/4] COPY . .
從 4.7s
降到了 1.8s
, => [builder 2/4] COPY --from=deps /app/node_modules ./node_modules
這一步的耗時已經(jīng)沒有了。
優(yōu)化二:重新構(gòu)建一個新的鏡像作為基礎(chǔ)鏡像
通過觀察Dockerfile
,我們發(fā)現(xiàn)以node:20.18.1-alpine
鏡像為基礎(chǔ)鏡像進(jìn)行構(gòu)建的時候,還需要安裝libc6-compat
,受網(wǎng)絡(luò)波動的影響libc6-compat
有時候下載比較慢。那我們可以把在node:20.18.1-alpine
環(huán)境下,下載好libc6-compat
單獨打包成一個鏡像,上傳到公司內(nèi)部的鏡像倉庫中,直接使用這個新鏡像來作為基礎(chǔ)鏡像就可以了。如何構(gòu)建鏡像上傳到公司內(nèi)部鏡像倉庫,大家可以去看看Docker
的教程就可以了,這里就不展開了。
一、Dockerfile調(diào)整
二、構(gòu)建效果
我們可以看到通過構(gòu)建一個新的鏡像上傳到內(nèi)部鏡像倉庫中使用,不僅鏡像下載速度變快了,還可以節(jié)省下了 => [deps 1/4] RUN apk add --no-cache libc6-compat
下載的時間。
[internal] load metadata for docker.io/library/node:20.18.1-alpine
: 4.4s => 0.7s=> [internal] load build context
: 23.8s => 11.3s=> transferring context: 712.33MB
: 23.8s => 9.9s=> [deps 1/4] RUN apk add --no-cache libc6-compat
: 3.0s => 0s
總結(jié)
由于是臨時支持了這個項目,在對項目改動不大的情況下去進(jìn)行了一些嘗試,而且僅針對Docker
鏡像自身構(gòu)建的優(yōu)化。通過這次實踐來看,這個項目單純從Docker
方面來進(jìn)行優(yōu)化,效果相對來說還是不夠的,減少了70s
左右的時間。整個構(gòu)建耗時的流程還是在安裝依賴以及項目本身的構(gòu)建上,如果要想顯著的提高項目發(fā)布速度,還得從這兩方面入手。
其他
中間嘗試還進(jìn)行了npm
包的下載速度優(yōu)化,因為這個改動相對來說也比較小。配置國內(nèi)的npm
源,速度確實會提升不少,如果公司內(nèi)部搭建有完整的私有npm
倉庫,那速度將會大大提升。
還有另外一種方案,就是利用Docker
多階段構(gòu)建來對依賴進(jìn)行分批下載,下載完成之后再合并到一起進(jìn)行打包構(gòu)建,這樣子也許可以節(jié)省一些時間。
到此這篇關(guān)于Docker鏡像構(gòu)建速度優(yōu)化實現(xiàn)的文章就介紹到這了,更多相關(guān)Docker鏡像構(gòu)建速度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker Swarm結(jié)合Docker Compose部署集群的實現(xiàn)
本文主要介紹了Docker Swarm結(jié)合Docker Compose部署集群的實現(xiàn),通過部署和配置幫助讀者更好地理解并應(yīng)用這些工具,感興趣的可以了解一下2023-12-12Docker中鏡像構(gòu)建文件Dockerfile與相關(guān)命令的詳細(xì)介紹
這篇文章主要介紹了Docker中鏡像構(gòu)建文件Dockerfile與相關(guān)命令的相關(guān)資料,文中介紹的很詳細(xì),相信對大家具有一定的參考價值,有需要的朋友們下面來一起看看吧。2017-02-02vscode中啟用docker擴(kuò)展顯示無權(quán)限的問題解決
這篇文章主要介紹了如何解決vscode中啟用docker擴(kuò)展顯示無權(quán)限的問題,并介紹允許VSCode進(jìn)入Docker內(nèi)部進(jìn)行調(diào)試的插件,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-03-03Docker構(gòu)建Java鏡像并部署Java項目的完整步驟
這篇文章主要給大家介紹了關(guān)于Docker構(gòu)建Java鏡像并部署Java項目的完整步驟,Docker是一種容器化技術(shù),可以幫助開發(fā)者輕松打包應(yīng)用程序和依賴項,并在任何地方運行它們,需要的朋友可以參考下2023-10-10docker安裝elasticsearch和kibana的方法步驟
這篇文章主要介紹了docker安裝elasticsearch和kibana的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06