您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么選擇一個最好的Node.js Docker鏡像”,在日常操作中,相信很多人在怎么選擇一個最好的Node.js Docker鏡像問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么選擇一個最好的Node.js Docker鏡像”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
我們在使用FROM node:latest
或只是FROM node
時,很容易忽略他潛在的風(fēng)險。如果你不知道總體的安全風(fēng)險并且把他引入到了CI/CD的流程中,那無疑是加劇了這個風(fēng)險。
下面這個例子非常典型,你可以從很多教程或者博客文章中看到這個Node.js Dockerfile的配置。但是這個Dockerfile的配置存在很大的問題,非常不推薦這樣使用:
FROM node
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN npm install
CMD "npm" "start"
當(dāng)你構(gòu)建一個Node.js鏡像的時候,實際上有很多選擇。其中就包括了Node.js核心團隊維護的官方Docker鏡像,以及從特定的基礎(chǔ)鏡像中選擇的特殊Node.js鏡像版本。還可以選擇其他的,比如谷歌在distroless
項目上構(gòu)建的Node.js應(yīng)用程序,或者是Docker官方團隊提供的一個名為scratch
的鏡像。
在這些Node.js的Docker鏡像中,哪一個是最適合你的呢?
讓我們一個一個的去分析,了解更多他們的好處和潛在風(fēng)險。
我們先從維護的node鏡像開始。它是由進行正式地維護的,包含了一些基礎(chǔ)的鏡像tag。這些tag對應(yīng)到不同的底層發(fā)行版(Debian、Ubuntu、Alpine)以及不同版本的Node.js運行時本身。還有針對不同CPU架構(gòu)的特定版本tag,例如amd64
和arm64x8
(新版蘋果的M1)。
Debian發(fā)行版中最常見的node
鏡像,例如bullseye
或buster
,他們都是基于由另一個團隊維護的buildpack-deps
的。
當(dāng)你基于這個默認的node
鏡像構(gòu)建Node.js Docker鏡像時會發(fā)生什么?
FROM node
使用docker build --no-cache -f Dockerfile1 -t dockerfile1
構(gòu)建鏡像時,就會出現(xiàn)下面這些:
我們沒有指定Node.js運行時版本,所以node
是node:last
的一個別名,他的版本指向的是18.2.0
這個Node.js Docker鏡像大小是952MB
這個最新的Node.js鏡像的依賴和安全漏洞足跡是什么呢?我們可以用docker scan dockerfile1
來運行一個Synk-powered
容器,就會得到下面的結(jié)果:
共有409個依賴項 - 這些是使用操作系統(tǒng)包管理器檢測到的開源庫,比如curl/libcurl4
、git/git-man
、imagemagick/imagemagick-6-common
。
共有289個安全問題在這些依賴中被發(fā)現(xiàn),例如,Buffer Overflows
、use-after-free errors
、out-of-bounds write
等。
Node.js 18.2.0運行時版本容易出現(xiàn)7個安全問題。例如,DNS Rebinding
、HTTP Request Smuggling
、Configuration Hijacking
譯者注:
Buffer Overflows - 緩沖區(qū)溢出
Use After Free - 一種內(nèi)存破壞漏洞,通常存在于瀏覽器中
out-of-bounds write - 越界寫入
DNS Rebinding - DNS重綁定攻擊
HTTP Request Smugglin - HTTP請求夾帶攻擊技術(shù)
Configuration Hijacking - 配置劫持
你真的需要在Node.js鏡像中給你的應(yīng)用提供wget
、git
、curl
嗎?在Node.js Docker鏡像中,有成百上千個依賴和工具,而這些依賴又對應(yīng)著成百上千個漏洞。Node.js運行時的特性對應(yīng)著7個不同的安全漏洞,給潛在攻擊留下了很大的空間??偟膩碚f,情況并不是很樂觀。
如果你在Node.js Docker Hub倉庫上瀏覽可用tags,你將會發(fā)現(xiàn)有兩個Node.js鏡像tags - node:buster
和node:bullseye
。
這兩個Docker鏡像tags都基于Debian發(fā)行版。buster
鏡像tag對應(yīng)著Debian10,將會在2022年8月到2024年進入到他的End of Life日期,所以buster
不是一個很好的選擇。bullseye
鏡像tag對應(yīng)著Debian11,被當(dāng)做Debian的當(dāng)前穩(wěn)定版本,預(yù)計EOL日期為2026年6月。
譯者注:
End of Life。特指產(chǎn)品壽命的結(jié)束,通??s寫為EOL。
因此,十分建議你將所有新的和現(xiàn)有的Node.js Docker鏡像從node:buster
遷移到node:bullseye
或者其他合適的可替代版本。
我們先構(gòu)建一個新的Node.js Docker鏡像基于:
FROM node:bullseye復(fù)制代碼
如果你構(gòu)建了這個Node.js Docker鏡像tag并且與之前使用node:latest
的結(jié)果進行比較,將會得到完全相同的大小、依賴數(shù)量和發(fā)現(xiàn)的漏洞。原因是node
、node:latest
、node:bullseye
全部指向了同一個正在構(gòu)建的Node.js鏡像tag。
官方的Node.js團隊還維護了一個顯式地針對功能性Node.js環(huán)境所需工具的鏡像tag并且不會存在其他的東西。
這個Node.js鏡像tags是通過slim
鏡像tag變量來引用的,比如node:bullseye-slim
,或者帶有Node.js指定版本,像node:14.19.2 -slim
。
我們再來基于Debian的當(dāng)前穩(wěn)定版本的bullseye
構(gòu)建一個Node.jsslim
鏡像:
FROM node:bullseye-slim
鏡像的大小已經(jīng)急劇下降,從接近1GB的容器鏡像降到246MB的鏡像大小
掃描他的內(nèi)容也顯示了整體軟件足跡的大幅下降,只有97個依賴項和56個漏洞。
就容器鏡像大小和安全狀況而言,node:bullseye-slim
已經(jīng)是一個比較好的起點了。
到目前為止,我們的Node.js Docker鏡像基于當(dāng)前版本的Node.js,即Node.js18。但是根據(jù)Node.js的發(fā)布時間表,這個版本直到2022年10月才進入正式的Active LTS
狀態(tài)。
譯者注:LTS - Long-term support,即長期支持版本。
如果我們總是依賴于我們正在構(gòu)建的Node.js Docker鏡像中的LTS版本的話會怎么樣?我們先更新這個Docker鏡像tag并構(gòu)建一個新的Node.js鏡像:
FROM node:lts-bullseye-slim
瘦身后的Node.js LTS版本(16.15.0)在鏡像上帶來了相似數(shù)量的依賴、安全漏洞和一個略小的體積(188MB)。
因此,盡管你可能需要在LTS和當(dāng)前Node.js運行時版本中選擇,但他們都不會對Node.js鏡像的軟件占用空間有大的影響。
Node.js Docker團隊維護了一個node:alpine
鏡像tag以及他的變體,以便將Alpine Linux發(fā)行版的特定版本與Node.js運行時的特定版本進行匹配。
Alpine Linux項目經(jīng)常因為其非常小的鏡像體積而被引用,小體積意味著更新的軟件占用空間和更少的漏洞,確實十分不錯。
下面的命令會讓Dockerfile去生成一個node環(huán)境,這個將會增加未壓縮的鏡像體積:
FROM node:alpine
這個將會產(chǎn)生一個178MB大小的docker鏡像,和slim
Node.js鏡像大小差不多,但是在alpine
鏡像tag中,只檢測到了16個系統(tǒng)依賴漏洞和2個安全安全漏洞。這就意味著alpine
鏡像tag對于小體積和漏洞數(shù)量來說是一個比較好的選擇。
alpine
對Node.js鏡像可能提供了一個較小的鏡像體積和更少的漏洞數(shù)量。但是,我們必須意識到Alpine項目使用musl
作為C標(biāo)準(zhǔn)庫的實現(xiàn)。而Debian的Node.js鏡像tag依賴于glibc
實現(xiàn),比如bullseye
和slim
。這些差異可以解釋性能問題、功能性的bug或者是潛在的應(yīng)用程序崩潰,這些都是由于底層C庫的差異造成的。
選擇一個alpine
的Node.js鏡像tag意味著你實際上是在選擇一個非官方的Node.js運行時。Node.js Docker團隊并不會正式支持基于alpine
的容器鏡像構(gòu)建。因此,他聲明基于Alpine的鏡像tag是實驗性的,并且可能和官方的構(gòu)建不一致。
如果你正在選一個一個基于Alpine的Node.js Docker鏡像,需要記住一點,Docker安全工具(例如Trivy或Snyk)目前無法檢測到Alpine鏡像中與運行時相關(guān)的漏洞的。雖然這種情況未來可能會改變,但是目前還不能找到Node.js18.2.0alpine
基礎(chǔ)鏡像tag的安全漏洞,而18.2.0運行時本身實際上是容易受到攻擊的。這與安全工具本身有關(guān),而不是與Alpine基礎(chǔ)鏡像有關(guān),但是也應(yīng)該考慮到這一點。
distroless
(無損)Docker鏡像我們的基準(zhǔn)測試的最后一個比較項目是谷歌的Distroless容器鏡像。
distroless
容器鏡像?這種鏡像甚至比slim
的Node.js鏡像更加小,因為distroless
鏡像只針對這個應(yīng)用和應(yīng)用運行時的依賴性而已。因此,一個distroless
的docker鏡像沒有容器包管理器、shell、或者其他通用工具的依賴性,這使得它們的體積更小,漏洞也更少。
幸運的是,Distroless項目為Node.js維護了一個特殊運行時的distroless
docker鏡像,通過其完整的命名空間識別為grc.io/distroless/nodejs-debian11
,并且可以在谷歌的容器注冊表中找到(這個是gcr.io
的部分)。
因為Distroless容器鏡像沒有軟件,我們可以使用一個docker的多階段工作流來為我們的容器安裝依賴項,并且把它們復(fù)制到Distroless鏡像:
FROM node:16-bullseye-slim AS build
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN npm install
FROM gcr.io/distroless/nodejs:16
COPY --from=build /usr/src/app /usr/src/app
WORKDIR /usr/src/app
CMD ["server.js"]
構(gòu)建這個distroless
docker鏡像將產(chǎn)生112MB的文件,而在slim
和alpine
鏡像tag來說,這已經(jīng)減小了很多文件的體積了。
如果你正在考慮使用distroless
docker鏡像,有一些重要的事項需要注意:
好的一點是,它們是基于當(dāng)前穩(wěn)定的Debian發(fā)行版本,這意味著它們是最新的,很久才會到EOL的日期。
因為它們是基于Debian的,所以它們依賴glibc
實現(xiàn),并且不太可能在生產(chǎn)環(huán)境出現(xiàn)一些奇怪的問題。
你很快就會發(fā)現(xiàn)Distroless團隊沒有維護細粒度的Node.js運行時版本。這意味著你需要依賴于通用的nodejs:16
的標(biāo)記(該標(biāo)記經(jīng)常更新),或者在一個特定時間點根據(jù)鏡像的SHA256哈希值進行安裝。
我們可以參考下面的表格來總結(jié)不同Node.js Docker鏡像tags之間的比較:
Image tag | Node.js runtime version | OS dependencies | OS security vulnerabilities | High and Critical vulnerabilities | Medium vulnerabilities | Low vulnerabilities | Node.js runtime vulnerabilities | Image size | Yarn available |
---|---|---|---|---|---|---|---|---|---|
node | 18.2.0 | 409 | 289 | 54 | 18 | 217 | 7 | 952MB | Yes |
node:bullseye | 18.2.0 | 409 | 289 | 54 | 18 | 217 | 7 | 952MB | Yes |
node:bullseye-slim | 18.2.0 | 97 | 56 | 4 | 8 | 44 | 7 | 246MB | Yes |
node:lts-bullseye-slim | 16.15.0 | 97 | 55 | 4 | 7 | 44 | 6 | 188MB | Yes |
node:alpine | 18.2.0 | 16 | 2 | 2 | 0 | 0 | 0 | 178MB | Yes |
gcr.io/distroless/nodejs:16 | 16.17.0 | 9 | 11 | 0 | 0 | 11 | 0 | 112MB | No |
我們來通過之前學(xué)習(xí)到的每個不同的Node.js鏡像tags的數(shù)據(jù)和見解,然后確定哪個是最理想的。
如果你選擇使用的Node.js鏡像tag取決于開發(fā)的一致性(這意味你希望為開發(fā)和生產(chǎn)完全相同的環(huán)境進行優(yōu)化),那么這可能已經(jīng)是一場失敗的battle了。在大多數(shù)情況下,所有3個主要操作系統(tǒng)都使用不同的C庫實現(xiàn)。Linux依賴glibc,Alpine依賴musl,而macOS有自己的BSD libc實現(xiàn)。
有時候,鏡像大小也很重要。更準(zhǔn)確地說,我們的目標(biāo)不是擁有最小的體積,而是擁有最小的整體軟件占用。在這種情況下,slim
鏡像tags和alpine
沒有太大的區(qū)別,而且它們對于一個容器鏡像來說平均大概是200MB。當(dāng)然,slim
鏡像的軟件占用相對于alpine
來說還是相當(dāng)高的(slim
97個 VS alpine
16個),因此,漏洞數(shù)量對于alipne
來說也更高(slime
56個 VS slpine
2個)。
漏洞是一個重要的問題,并且一直是很多文章的中心——關(guān)于你為什么應(yīng)該減少容器鏡像的大小。
忽略node
和node:bullseye
這種由于較大的軟件占用而跟著增加安全漏洞的鏡像,我們可以更關(guān)注稍微小一點的鏡像類型。在slim
、alpine
、distroless
之間對比,高危和關(guān)鍵安全漏洞的絕對數(shù)量并不高,范圍在0到4之間,這是一個可控的風(fēng)險,并不會影響到你的應(yīng)用程序。
最理想的Node.js Docker鏡像應(yīng)該是一個基于現(xiàn)代Debian OS的操作系統(tǒng)的精簡版本,它有一個穩(wěn)定且活躍的Node.js長期支持版本。
歸根結(jié)底就是選擇node:lts-bullseye-slim
Node.js鏡像tag。我贊成使用確定性圖像標(biāo)記,因此我要做的細微更改是使用實際的底層版本號,而不是lts
別名。
最理想的Node.js Docker鏡像tag是**node:16.17.0-bullseye-slim**
。
如果你在一個成熟的開發(fā)團隊工作,該團隊可以支持自定義基礎(chǔ)鏡像,那么我的第二個最佳建議是選擇谷歌的distroless
鏡像tag,因為它保持了glibc
對官方Node.js運行時版本的兼容性。這個工作流會需要一些維護,所以我只是建議而已。
到此,關(guān)于“怎么選擇一個最好的Node.js Docker鏡像”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。