FROM ノード:最新または単に
FROM ノードを使用する場合、その潜在的なリスクを無視するのは簡単です。全体的なセキュリティ リスクを知らずに CI/CD プロセスに導入すると、間違いなくリスクが悪化します。 [関連チュートリアルの推奨事項:
nodejs ビデオ チュートリアル、プログラミング教育]
ただし、この Dockerfile の構成には大きな問題があるため、次のように使用することは強くお勧めできません:
FROM node WORKDIR /usr/src/app COPY . /usr/src/app RUN npm install CMD "npm" "start"
翻訳者注: をスキップする必要がある場合は、分析して結論を直接確認するには、記事の最後まで直接スライドしてください。
distrolessプロジェクトで構築した Node.js アプリケーションや、公式の Docker チームが提供する
scratchというイメージなど、他のものを選択することもできます。
著者注: この記事では、2022 年 6 月頃にリリースされるバージョン 18.2.0 の Node.js イメージを比較します。#デフォルトの Node.js イメージ
やarm64x8
(Apple の M1 の新しいバージョン) など、さまざまな CPU アーキテクチャに固有のバージョン タグもあります。Debian ディストリビューションで最も一般的な
イメージ (bullseye
やbuster
など) は、によって保守されているに基づいています。別のチーム##buildpack-deps
。このデフォルトの
node
イメージに基づいて Node.js Docker イメージを構築するとどうなりますか?
UseFROM node
イメージをビルドすると、次のように表示されます:
node:last
のエイリアスであり、そのバージョンは、この18.2.0
を指します。 Node.js Docker イメージのサイズは 952MBを使用してSynk を利用した
コンテナを実行すると、次の結果が得られます:
git/git-man
、imagemagick/imagemagick-6-common## など)。 #。
これらの依存関係では、
バッファ オーバーフロー、
境界外など、合計 289 件のセキュリティ問題が見つかりました。などを書きます。
Node.js 18.2.0 ランタイム バージョンには 7 つのセキュリティ問題が発生する傾向があります。例:
DNS 再バインド、
構成ハイジャック
你真的需要在Node.js镜像中给你的应用提供wget
、git
、curl
吗?在Node.js Docker镜像中,有成百上千个依赖和工具,而这些依赖又对应着成百上千个漏洞。Node.js运行时的特性对应着7个不同的安全漏洞,给潜在攻击留下了很大的空间。总的来说,情况并不是很乐观。
如果你在Node.js Docker Hub仓库上浏览可用tags,你将会发现有两个Node.js镜像tags -node:buster
和node: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
的结果进行比较,将会得到完全相同的大小、依赖数量和发现的漏洞。原因是node
、node:latest
、node:bullseye
全部指向了同一个正在构建的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
就容器镜像大小和安全状况而言,node:bullseye-slim
已经是一个比较好的起点了。
到目前为止,我们的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.js Docker团队维护了一个node:alpine
镜像tag以及他的变体,以便将Alpine Linux发行版的特定版本与Node.js运行时的特定版本进行匹配。
Alpine Linux项目经常因为其非常小的镜像体积而被引用,小体积意味着更新的软件占用空间和更少的漏洞,确实十分不错。
下面的命令会让Dockerfile去生成一个node环境,这个将会增加未压缩的镜像体积:
FROM node:alpine
这个将会产生一个178MB大小的docker镜像,和slim
Node.js镜像大小差不多,但是在alpine
镜像tag中,只检测到了16个系统依赖漏洞和2个安全安全漏洞。这就意味着alpine
镜像tag对于小体积和漏洞数量来说是一个比较好的选择。
alpine
对Node.js镜像可能提供了一个较小的镜像体积和更少的漏洞数量。但是,我们必须意识到Alpine项目使用musl
作为C标准库的实现。而Debian的Node.js镜像tag依赖于glibc
实现,比如bullseye
和slim
。这些差异可以解释性能问题、功能性的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基础镜像有关,但是也应该考虑到这一点。
distroless
(无损)Docker镜像我们的基准测试的最后一个比较项目是谷歌的Distroless容器镜像。
distroless
容器镜像?这种镜像甚至比slim
的Node.js镜像更加小,因为distroless
镜像只针对这个应用和应用运行时的依赖性而已。因此,一个distroless
的docker镜像没有容器包管理器、shell、或者其他通用工具的依赖性,这使得它们的体积更小,漏洞也更少。
幸运的是,Distroless项目为Node.js维护了一个特殊运行时的distroless
docker镜像,通过其完整的命名空间识别为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"]
构建这个distroless
docker镜像将产生112MB的文件,而在slim
和alpine
镜像tag来说,这已经减小了很多文件的体积了。
如果你正在考虑使用distroless
docker镜像,有一些重要的事项需要注意:
glibc
实现,并且不太可能在生产环境出现一些奇怪的问题。nodejs:16
的标记(该标记经常更新),或者在一个特定时间点根据镜像的SHA256哈希值进行安装。我们可以参考下面的表格来总结不同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 イメージ タグのそれぞれについて学んだデータと洞察を調べて、どれが理想的であるかを判断してみましょう。
Node.js イメージ タグの使用を選択するかどうかは、開発の一貫性によって決まります (これは、開発と運用とまったく同じ環境に最適化することを意味します)、その場合、これはすでに負け戦である可能性があります。ほとんどの場合、3 つの主要なオペレーティング システムはすべて、異なる C ライブラリ実装を使用します。 Linux は glibc に依存し、Alpine は musl に依存し、macOS には独自の BSD libc 実装があります。
イメージ サイズも重要な場合があります。より正確に言うと、私たちの目標はサイズを最小にすることではなく、ソフトウェア全体のフットプリントを最小にすることです。この場合、slim
イメージ タグとalpine
の間に大きな違いはなく、コンテナー イメージあたり平均約 200MB です。もちろん、slim
ミラーのソフトウェア使用率は、alpine
と比較して依然としてかなり高くなります (slim
97 VSalpine
16)。 、脆弱性の数もalipne
の方が高くなります (slime
56 対slpine
2)。
脆弱性は重要な問題であり、コンテナ イメージのサイズを削減する必要がある理由に関する多くの記事の中心となっています。
node
とnode:bullseye
は、ソフトウェアの使用量が増えるとセキュリティの脆弱性が増大するイメージです。少し小さいイメージ タイプに注意を払うことができます。slim
、alpine
、distroless
を比較すると、高リスクおよび重大なセキュリティ脆弱性の絶対数は 0 ~ 4 であり、それほど多くはありません。アプリケーションに影響を与えない、制御可能なリスク。
理想的な Node.js Docker イメージは、最新の Debian OS をベースにしたオペレーティング システムの合理化されたバージョンである必要があります。は、Node.js の安定したアクティブな長期サポート バージョンです。
最後の分析は、node:lts-bullseye-slim
Node.js ミラー タグを選択することです。私は決定論的なイメージ タグを使用することに賛成なので、少し変更するとすれば、lts
エイリアスの代わりに実際の基礎となるバージョン番号を使用することです。
最も理想的な Node.js Docker イメージ タグは**node:16.17.0-bullseye-slim**
です。
カスタム ベース イメージをサポートできる成熟した開発チームで作業している場合、次善の提案は、glibc# を維持する Google の
distrolessimage タグを選択することです。 ## 公式 Node.js ランタイム バージョンとの互換性。このワークフローには多少のメンテナンスが必要になるため、私はこれを提案しているだけです。
nodejs チュートリアルを参照してください。
以上が最適な Node.js Docker イメージを選択する方法について話しましょう。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。