ホームページ  >  記事  >  ウェブフロントエンド  >  最適な Node.js Docker イメージを選択する方法について話しましょう。

最適な Node.js Docker イメージを選択する方法について話しましょう。

青灯夜游
青灯夜游転載
2022-12-13 20:00:092429ブラウズ

#Node Docker イメージの選択は小さな問題のように思えるかもしれませんが、イメージのサイズと潜在的な脆弱性は、CI/CD プロセスとセキュリティに大きな影響を与える可能性があります。では、最適な Node.js Docker イメージを選択するにはどうすればよいでしょうか?

最適な Node.js Docker イメージを選択する方法について話しましょう。

FROM ノード:最新 または単に FROM ノード を使用する場合、その潜在的なリスクを無視するのは簡単です。全体的なセキュリティ リスクを知らずに CI/CD プロセスに導入すると、間違いなくリスクが悪化します。 [関連チュートリアルの推奨事項: nodejs ビデオ チュートリアル プログラミング教育 ]

次の例は非常に典型的なもので、このノードは多くのチュートリアルやブログ投稿で見ることができます。 Dockerfileの設定。

ただし、この Dockerfile の構成には大きな問題があるため、次のように使用することは強くお勧めできません:

FROM node
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN npm install
CMD "npm" "start"

翻訳者注: をスキップする必要がある場合は、分析して結論を​​直接確認するには、記事の最後まで直接スライドしてください。

選択する Node.js Docker イメージ

Node.js イメージをビルドするとき、実際にはたくさんの選択肢があります。これらには、Node.js コア チームによって保守されている公式の Docker イメージと、特定のベース イメージから選択された特別な Node.js イメージ バージョンが含まれます。 Google が

distroless プロジェクトで構築した Node.js アプリケーションや、公式の Docker チームが提供する scratch というイメージなど、他のものを選択することもできます。

これらの Node.js Docker イメージの中で、あなたに最も適したものはどれですか?

それらを 1 つずつ分析して、その利点と潜在的なリスクについて詳しく見てみましょう。

著者注: この記事では、2022 年 6 月頃にリリースされるバージョン 18.2.0 の Node.js イメージを比較します。

#デフォルトの Node.js イメージ

まず、維持されているノード イメージから始めます。これは によって公式に管理されており、いくつかの基本的なイメージ タグが含まれています。これらのタグは、基盤となるさまざまなディストリビューション (Debian、Ubuntu、Alpine) および Node.js ランタイム自体のさまざまなバージョンに対応します。

amd64

arm64x8 (Apple の M1 の新しいバージョン) など、さまざまな CPU アーキテクチャに固有のバージョン タグもあります。 Debian ディストリビューションで最も一般的な

node

イメージ (bullseyebuster など) は、によって保守されている に基づいています。別のチーム##buildpack-depsこのデフォルトの node
イメージに基づいて Node.js Docker イメージを構築するとどうなりますか? <pre class="brush:js;toolbar:false;">FROM node</pre>Use

docker build --no-cache -f Dockerfile1 -t dockerfile1

イメージをビルドすると、次のように表示されます:

指定しませんでしたNode .js ランタイム バージョン。したがって、
    node
  • node:last のエイリアスであり、そのバージョンは、この 18.2.0 を指します。 Node.js Docker イメージのサイズは 952MB
  • この最新の Node.js イメージの依存関係とセキュリティ脆弱性の足跡は何ですか?
docker scan dockerfile1

を使用して Synk を利用した コンテナを実行すると、次の結果が得られます:

合計 409 個の依存関係があります -これらは、オペレーティング システムのパッケージ マネージャーによって検出されたオープン ソース ライブラリを使用します (
    curl/libcurl4
  • git/git-manimagemagick/imagemagick-6-common## など)。 #。 これらの依存関係では、バッファ オーバーフロー
  • use-after-free エラー境界外など、合計 289 件のセキュリティ問題が見つかりました。 などを書きます。 Node.js 18.2.0 ランタイム バージョンには 7 つのセキュリティ問題が発生する傾向があります。例: DNS 再バインド
  • HTTP リクエスト スマグリング構成ハイジャック
  • 翻訳者注:
  • Buffer Overflows - 缓冲区溢出
  • Use After Free - 一种内存破坏漏洞,通常存在于浏览器中
  • out-of-bounds write - 越界写入
  • DNS Rebinding - DNS重绑定攻击
  • HTTP Request Smugglin - HTTP请求夹带攻击技术
  • Configuration Hijacking - 配置劫持

你真的需要在Node.js镜像中给你的应用提供wgetgitcurl吗?在Node.js Docker镜像中,有成百上千个依赖和工具,而这些依赖又对应着成百上千个漏洞。Node.js运行时的特性对应着7个不同的安全漏洞,给潜在攻击留下了很大的空间。总的来说,情况并不是很乐观。

Node.js Docker Hub选项node:buster vs node:bullseye

如果你在Node.js Docker Hub仓库上浏览可用tags,你将会发现有两个Node.js镜像tags - node:busternode:bullseye

这两个Docker镜像tags都基于Debian发行版。buster镜像tag对应着Debian10,将会在2022年8月到2024年进入到他的End of Life日期,所以buster不是一个很好的选择。bullseye镜像tag对应着Debian11,被当做Debian的当前稳定版本,预计EOL日期为2026年6月。

译者注:

  • End of Life。特指产品寿命的结束,通常缩写为EOL。

因此,十分建议你将所有新的和现有的Node.js Docker镜像从node:buster迁移到node:bullseye或者其他合适的可替代版本。
我们先构建一个新的Node.js Docker镜像基于:

FROM node:bullseye复制代码

如果你构建了这个Node.js Docker镜像tag并且与之前使用node:latest的结果进行比较,将会得到完全相同的大小、依赖数量和发现的漏洞。原因是nodenode:latestnode:bullseye全部指向了同一个正在构建的Node.js镜像tag。

Node.js镜像tag瘦身

官方的Node.js团队还维护了一个显式地针对功能性Node.js环境所需工具的镜像tag并且不会存在其他的东西。

这个Node.js镜像tags是通过slim镜像tag变量来引用的,比如node:bullseye-slim,或者带有Node.js指定版本,像node:14.19.2 -slim

我们再来基于Debian的当前稳定版本的bullseye构建一个Node.jsslim镜像:

FROM node:bullseye-slim
  • 镜像的大小已经急剧下降,从接近1GB的容器镜像降到246MB的镜像大小
  • 扫描他的内容也显示了整体软件足迹的大幅下降,只有97个依赖项和56个漏洞。

就容器镜像大小和安全状况而言,node:bullseye-slim已经是一个比较好的起点了。

一个LTS的Node.js Docker镜像

到目前为止,我们的Node.js Docker镜像基于当前版本的Node.js,即Node.js18。但是根据Node.js的发布时间表,这个版本直到2022年10月才进入正式的Active LTS状态。

译者注:LTS - Long-term support,即长期支持版本。

如果我们总是依赖于我们正在构建的Node.js Docker镜像中的LTS版本的话会怎么样?我们先更新这个Docker镜像tag并构建一个新的Node.js镜像:

FROM node:lts-bullseye-slim

瘦身后的Node.js LTS版本(16.15.0)在镜像上带来了相似数量的依赖、安全漏洞和一个略小的体积(188MB)。

因此,尽管你可能需要在LTS和当前Node.js运行时版本中选择,但他们都不会对Node.js镜像的软件占用空间有大的影响。

node:alpine对于Node.js镜像来说是一个更好的选择吗?

Node.js Docker团队维护了一个node:alpine镜像tag以及他的变体,以便将Alpine Linux发行版的特定版本与Node.js运行时的特定版本进行匹配。

Alpine Linux项目经常因为其非常小的镜像体积而被引用,小体积意味着更新的软件占用空间和更少的漏洞,确实十分不错。
下面的命令会让Dockerfile去生成一个node环境,这个将会增加未压缩的镜像体积:

FROM node:alpine

这个将会产生一个178MB大小的docker镜像,和slimNode.js镜像大小差不多,但是在alpine镜像tag中,只检测到了16个系统依赖漏洞和2个安全安全漏洞。这就意味着alpine镜像tag对于小体积和漏洞数量来说是一个比较好的选择。

alpine对Node.js镜像可能提供了一个较小的镜像体积和更少的漏洞数量。但是,我们必须意识到Alpine项目使用musl作为C标准库的实现。而Debian的Node.js镜像tag依赖于glibc实现,比如bullseyeslim。这些差异可以解释性能问题、功能性的bug或者是潜在的应用程序崩溃,这些都是由于底层C库的差异造成的。

选择一个alpine的Node.js镜像tag意味着你实际上是在选择一个非官方的Node.js运行时。Node.js Docker团队并不会正式支持基于alpine的容器镜像构建。因此,他声明基于Alpine的镜像tag是实验性的,并且可能和官方的构建不一致。

如果你正在选一个一个基于Alpine的Node.js Docker镜像,需要记住一点,Docker安全工具(例如Trivy或Snyk)目前无法检测到Alpine镜像中与运行时相关的漏洞的。虽然这种情况未来可能会改变,但是目前还不能找到Node.js18.2.0alpine基础镜像tag的安全漏洞,而18.2.0运行时本身实际上是容易受到攻击的。这与安全工具本身有关,而不是与Alpine基础镜像有关,但是也应该考虑到这一点。

Node.js的distroless(无损)Docker镜像

我们的基准测试的最后一个比较项目是谷歌的Distroless容器镜像。

什么是distroless容器镜像?

这种镜像甚至比slim的Node.js镜像更加小,因为distroless镜像只针对这个应用和应用运行时的依赖性而已。因此,一个distroless的docker镜像没有容器包管理器、shell、或者其他通用工具的依赖性,这使得它们的体积更小,漏洞也更少。

幸运的是,Distroless项目为Node.js维护了一个特殊运行时的distrolessdocker镜像,通过其完整的命名空间识别为grc.io/distroless/nodejs-debian11,并且可以在谷歌的容器注册表中找到(这个是gcr.io的部分)。

因为Distroless容器镜像没有软件,我们可以使用一个docker的多阶段工作流来为我们的容器安装依赖项,并且把它们复制到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"]

构建这个distrolessdocker镜像将产生112MB的文件,而在slimalpine镜像tag来说,这已经减小了很多文件的体积了。
如果你正在考虑使用distrolessdocker镜像,有一些重要的事项需要注意:

  • 好的一点是,它们是基于当前稳定的Debian发行版本,这意味着它们是最新的,很久才会到EOL的日期。
  • 因为它们是基于Debian的,所以它们依赖glibc实现,并且不太可能在生产环境出现一些奇怪的问题。
  • 你很快就会发现Distroless团队没有维护细粒度的Node.js运行时版本。这意味着你需要依赖于通用的nodejs:16的标记(该标记经常更新),或者在一个特定时间点根据镜像的SHA256哈希值进行安装。

Node.js Docker镜像tags的比较

我们可以参考下面的表格来总结不同Node.js Docker镜像tags之间的比较:

イメージ タグ Node.js ランタイム バージョン OS の依存関係 OS セキュリティの脆弱性 高および重大な脆弱性 中程度の脆弱性 低レベルの脆弱性 Node.js ランタイムの脆弱性 画像サイズ 利用可能な糸
ノード 18.2.0 409 289 54 18 217 7 952MB はい
ノード:ブルズアイ 18.2.0 409 289 54 18 217 7 952MB はい
ノード:ブルズアイスリム 18.2.0 97 56 4 8 44 7 246MB はい
node:lts-bullseye-slim 16.15.0 97 55 4 7 44 6 188MB はい
ノード:アルパイン 18.2.0 16 2 2 0 0 0 178MB はい
gcr.io/distroless/nodejs:16 16.17.0 9 11 0 0 11 0 112MB No

さまざまな Node.js イメージ タグのそれぞれについて学んだデータと洞察を調べて、どれが理想的であるかを判断してみましょう。

DEVELOPMENT-PARITY (開発環境パリティ)

Node.js イメージ タグの使用を選択するかどうかは、開発の一貫性によって決まります (これは、開発と運用とまったく同じ環境に最適化することを意味します)、その場合、これはすでに負け戦である可能性があります。ほとんどの場合、3 つの主要なオペレーティング システムはすべて、異なる C ライブラリ実装を使用します。 Linux は glibc に依存し、Alpine は musl に依存し、macOS には独自の BSD libc 実装があります。

DOCKER イメージ サイズ

イメージ サイズも重要な場合があります。より正確に言うと、私たちの目標はサイズを最小にすることではなく、ソフトウェア全体のフットプリントを最小にすることです。この場合、slim イメージ タグと alpine の間に大きな違いはなく、コンテナー イメージあたり平均約 200MB です。もちろん、slim ミラーのソフトウェア使用率は、alpine と比較して依然としてかなり高くなります (slim97 VS alpine16)。 、脆弱性の数も alipne の方が高くなります (slime56 対 slpine2)。

セキュリティの脆弱性

脆弱性は重要な問題であり、コンテナ イメージのサイズを削減する必要がある理由に関する多くの記事の中心となっています。

nodenode:bullseye は、ソフトウェアの使用量が増えるとセキュリティの脆弱性が増大するイメージです。少し小さいイメージ タイプに注意を払うことができます。 slimalpinedistroless を比較すると、高リスクおよび重大なセキュリティ脆弱性の絶対数は 0 ~ 4 であり、それほど多くはありません。アプリケーションに影響を与えない、制御可能なリスク。

重要なコンテンツ?

理想的な Node.js Docker イメージは、最新の Debian OS をベースにしたオペレーティング システムの合理化されたバージョンである必要があります。は、Node.js の安定したアクティブな長期サポート バージョンです。

最後の分析は、node:lts-bullseye-slimNode.js ミラー タグを選択することです。私は決定論的なイメージ タグを使用することに賛成なので、少し変更するとすれば、lts エイリアスの代わりに実際の基礎となるバージョン番号を使用することです。

最も理想的な Node.js Docker イメージ タグは **node:16.17.0-bullseye-slim** です。

カスタム ベース イメージをサポートできる成熟した開発チームで作業している場合、次善の提案は、glibc# を維持する Google の distrolessimage タグを選択することです。 ## 公式 Node.js ランタイム バージョンとの互換性。このワークフローには多少のメンテナンスが必要になるため、私はこれを提案しているだけです。

ノード関連の知識の詳細については、

nodejs チュートリアル を参照してください。

以上が最適な Node.js Docker イメージを選択する方法について話しましょう。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。