溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么選擇一個最好的Node.js Docker鏡像

發(fā)布時間:2022-12-14 09:38:37 來源:億速云 閱讀:162 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“怎么選擇一個最好的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"

一個可供選擇Node.js Docker鏡像

當(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.js鏡像

我們先從維護的node鏡像開始。它是由進行正式地維護的,包含了一些基礎(chǔ)的鏡像tag。這些tag對應(yīng)到不同的底層發(fā)行版(Debian、Ubuntu、Alpine)以及不同版本的Node.js運行時本身。還有針對不同CPU架構(gòu)的特定版本tag,例如amd64arm64x8(新版蘋果的M1)。

Debian發(fā)行版中最常見的node鏡像,例如bullseyebuster,他們都是基于由另一個團隊維護的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運行時版本,所以nodenode:last的一個別名,他的版本指向的是18.2.0

  • 這個Node.js Docker鏡像大小是952MB

這個最新的Node.js鏡像的依賴和安全漏洞足跡是什么呢?我們可以用docker scan dockerfile1來運行一個Synk-powered容器,就會得到下面的結(jié)果:

  • 共有409個依賴項 - 這些是使用操作系統(tǒng)包管理器檢測到的開源庫,比如curl/libcurl4、git/git-manimagemagick/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 RebindingHTTP 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選項node:buster vs node:bullseye

如果你在Node.js Docker Hub倉庫上瀏覽可用tags,你將會發(fā)現(xiàn)有兩個Node.js鏡像tags - node:busternode: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鏡像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)是一個比較好的起點了。

一個LTS的Node.js Docker鏡像

到目前為止,我們的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:alpine對于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鏡像,和slimNode.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),比如bullseyeslim。這些差異可以解釋性能問題、功能性的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)該考慮到這一點。

Node.js的distroless(無損)Docker鏡像

我們的基準(zhǔn)測試的最后一個比較項目是谷歌的Distroless容器鏡像。

什么是distroless容器鏡像?

這種鏡像甚至比slim的Node.js鏡像更加小,因為distroless鏡像只針對這個應(yīng)用和應(yīng)用運行時的依賴性而已。因此,一個distroless的docker鏡像沒有容器包管理器、shell、或者其他通用工具的依賴性,這使得它們的體積更小,漏洞也更少。

幸運的是,Distroless項目為Node.js維護了一個特殊運行時的distrolessdocker鏡像,通過其完整的命名空間識別為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)建這個distrolessdocker鏡像將產(chǎn)生112MB的文件,而在slimalpine鏡像tag來說,這已經(jīng)減小了很多文件的體積了。
如果你正在考慮使用distrolessdocker鏡像,有一些重要的事項需要注意:

  • 好的一點是,它們是基于當(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哈希值進行安裝。

Node.js Docker鏡像tags的比較

我們可以參考下面的表格來總結(jié)不同Node.js Docker鏡像tags之間的比較:

Image tagNode.js runtime versionOS dependenciesOS security vulnerabilitiesHigh and Critical vulnerabilitiesMedium vulnerabilitiesLow vulnerabilitiesNode.js runtime vulnerabilitiesImage sizeYarn available
node18.2.040928954182177952MBYes
node:bullseye18.2.040928954182177952MBYes
node:bullseye-slim18.2.0975648447246MBYes
node:lts-bullseye-slim16.15.0975547446188MBYes
node:alpine18.2.01622000178MBYes
gcr.io/distroless/nodejs:1616.17.091100110112MBNo

我們來通過之前學(xué)習(xí)到的每個不同的Node.js鏡像tags的數(shù)據(jù)和見解,然后確定哪個是最理想的。

DEVELOPMENT-PARITY(開發(fā)環(huán)境平價)

如果你選擇使用的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)。

DOCKER鏡像大小

有時候,鏡像大小也很重要。更準(zhǔn)確地說,我們的目標(biāo)不是擁有最小的體積,而是擁有最小的整體軟件占用。在這種情況下,slim鏡像tags和alpine沒有太大的區(qū)別,而且它們對于一個容器鏡像來說平均大概是200MB。當(dāng)然,slim鏡像的軟件占用相對于alpine來說還是相當(dāng)高的(slim97個 VS alpine16個),因此,漏洞數(shù)量對于alipne來說也更高(slime56個 VS slpine2個)。

安全漏洞

漏洞是一個重要的問題,并且一直是很多文章的中心——關(guān)于你為什么應(yīng)該減少容器鏡像的大小。

忽略nodenode:bullseye這種由于較大的軟件占用而跟著增加安全漏洞的鏡像,我們可以更關(guān)注稍微小一點的鏡像類型。在slim、alpinedistroless之間對比,高危和關(guān)鍵安全漏洞的絕對數(shù)量并不高,范圍在0到4之間,這是一個可控的風(fēng)險,并不會影響到你的應(yīng)用程序。

本質(zhì)內(nèi)容?

最理想的Node.js Docker鏡像應(yīng)該是一個基于現(xiàn)代Debian OS的操作系統(tǒng)的精簡版本,它有一個穩(wěn)定且活躍的Node.js長期支持版本。

歸根結(jié)底就是選擇node:lts-bullseye-slimNode.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>

向AI問一下細節(jié)

免責(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)容。

AI