ドッカーコン

Docker Rocks in Node.js, 2023 エディション

Bret Fisher 氏 (Docker キャプテン、DevOps Dude)

2023年11月17日収録
Bret Fisher が、Docker ツールに関するすべての最良のNode.jsのヒントと戦略に関する 2023 アップデートを提供します。 今年は、Node.js Wolfi イメージを基本イメージの推奨リストに追加したり、Docker Scout でNode.js画像分析を行ったり、超高速開発のための Compose Sync セットアップを追加したりと、新たに追加されました。

写し

こんにちは。 よし、これが観客参加型だ。 できるだけ退屈にならないようにしたいです。 だから、私の名前はブレットです。 DockerでNode.js講演を行うのは今回で3回目です。 だから、これはリフレッシュです。 そして、私はいつも、5枚のスライドをやろうと思っています。 5 つのスライドが変更されます。 この中のすべてが異なります。 なぜなら、Dockerには新しいものがたくさんあるからです。 ノードにいくつかの変更が加えられました。 いくつかのコマンド、いくつかの変更が加えられました。

だから、一緒に冒険するんだから、叫んでほしい。 繰り返しになりますが、観客の参加です。 そして、質問の時間をたっぷりと残しておこうと思います。 だって、3時間で話せるでしょ? YouTubeでNode.js for Dockerのコース全体を持っていますが、 45 分ではありません。 この講演で取り上げない質問がある場合は、前年にさかのぼって、すべて YouTube でオンラインになっていることを確認したいと思います。 そして、それを見て、その特定の質問に答えてください。 なぜなら、私は新しいものを追加し続けていて、それをすべてここに収めることができないからです。

目次

    新着と最新

    新しいものや最新のものに焦点を当てて、今年の新しいものをすべて手に入れられるようにしたいと思います。 そして、ここでのデザインは、誰のためのものなのかということです。 右。 つまり、あなたはいくつかのノードとDockerを知っていて、それを素晴らしくしたいと思っているのです。 そして、私はアドバイザーとして多くのチームと仕事をしています。 単なる実装者ではなく、私は彼らのものを見て、それを改善する方法についてアドバイスしています。 物事を合理化することで、よりシンプルになり、より安全になります。 だから、今日は素晴らしいソースモードに行きます。 そして、主に4つのことを説明し、最後に生産チェックリストを紹介します。

    そこで、Node ファイル、Node Dockerfile のベスト プラクティスから始めます。 これは、インターネットで入手できる基本的な 101 ではありません。 これはそれだけではありません。 それから、ベースイメージについて少しお話ししますが、新しいエキサイティングなことについて話したいのですが、それから「絶望の谷」というような、難しいですね。 初日から真の本番環境、エンタープライズグレードのノードイメージに移行するのは、思ったよりも難しいことです。 皆さんの中には、あなたが試したすべてのことについて、素晴らしい経験や素晴らしい物語を持っている人もいるでしょう。

    ノードプロセスの起動とシャットダウンについて説明します。 そのほとんどは、実際には私が前年を参照することになるでしょうが、私はあなたにすべての核心を与えるためにそれについて 15 分ほど続けたので、私たちはその基本をカバーします。 次に、私は Compose が大好きなので、新しい Compose についてお話しします。 今でも、Kubernetesで一緒に仕事をしているすべてのチームや、あらゆる派手なツールを使っても、Composeは、ローカル開発の最適化と開発セットアップの簡素化のために何度も足を運んでくれる場所です。 私は根っからの運用者ですが、開発はできるだけシンプルにしたいと思っていますよね? ですから、私たちは皆、本番環境とまったく同じように見えるが、非常に使いやすく高速な魔法のような開発スタックという美しいアイデアを望んでいます。 それは難しいですよね? ですから、Compose はローカルで、迅速で、シンプルなので、今でも気に入っています。 ファイルは理解しやすく、ここ数年で多くの新しい更新があり、特に昨年の私の講演や 2019の講演を見ていない場合はなおさらです。

    ドッカーファイル

    Dockerfileは、人々が無分別な決定を下し始める最初の場所であり、インターネットは多くのことを間違える傾向があるため、すぐにDockerfileに飛び込みましょう。 実際、私がよく言っていたのは、インターネットでこの 101 を見た人はいるだろうか、というものでした。 手を挙げますよね? 過去 10 年間のすべてのブログ投稿は、これがNodeのやり方です。

    誰かが彼らが見たもの、彼らがこのファイルで間違っていると思うことを叫ぶことができますか? おそらく、12のことが間違っています。 すべてにおいてコピー。 ええ、ええ、あそこの一番下。 コピー コマンドは 2 つありますが、これは技術的には正しいです。 他には。他に何か見てくれる人はいますか? ベースイメージですよね? そこには間違いなく改善の余地がありますよね? これはすべてのDocker 101 例ですが、おそらくインターネット上の誰もが使用すべきイメージではありません。 私は意見を持っています。 WORKDIRは実際には過去3年間でいくつかの変更が加えられており、WORKDIRは実際には権限を正しく割り当てていませんが、ノードイメージはすべてのDockerイメージと同様にデフォルトでeasyモードであり、最も安全なベストモードを意味するわけではないため、まだrootを使用していることに気付くでしょう。

    2013年当時、彼らがこれらの画像を作ったとき、彼らは単純化と使いやすさを求めていましたが、私たちはそれと、なぜそれをすべて変更したいのかについて説明します。それを刷新して、これが初日だったらどうしますか? これは必ずしも本番環境の準備ができているわけではありませんが、初日のイメージです。 Tier 1 でサポートされているビルドがあるので、Nodeland で知らなかった方のために説明すると、Node プロジェクトは、基本的に Node 用にさまざまなコンパイルとさまざまなプラットフォームをサポートしており、Tier 1とは何かという階層ランキングがあり、これは最高です。 Tier 1のサポート契約などを取得できます。 ティア 2 は、私たちが最善を尽くすことを意味します。 それほど重要ではありませんが、試してみたところ、実験的はベータ版になります。 うまくいく場合もあれば、うまくいかない場合もありますが、何も保証しません。 奇妙なことに、あるいは皮肉なことに、Dockerでさえ時々Alpineイメージを推奨していますが、今日はそれについて良い意味ではなくお話しします。 アルパイン、このプロジェクトは素晴らしいプロジェクトです。 Node、Alpine、およびproductionはお勧めしません。

    私はNodeで 15 年、Dockerで 10 年働いてきましたが、最終的には、私が携わっているすべてのプロジェクトで、大規模なNodeのことを本番環境で行っている場合、最終的にはAlpine固有の問題が発生し、主にAlpineでコンパイルされる方法であるMuslが原因です。 また、BusyBoxが問題になることもあります。 だから、今日は私がアルパインをお勧めするのを見ることはありませんが、心配しないでください、私はあなたのためにさらに良い推奨事項をたくさん持っています。 1 つは、Node の Tier 1 でサポートされているビルドにあるイメージが必要であり、Alpine は実験的に設定されているイメージです。

    次は、画像をピン留めします。 したがって、画像のピン留めについて知らなかった場合は、しばらく経ちますが、タグは再利用できるため、まったく同じ基本画像を取得できることを保証できますよね? この場合、Node 20を使用しているため、パッチレベルのバージョンに固定していませんが、SHAハッシュしています。 さて、技術的には、このようなイメージをSHAハッシュする場合、Dockerイメージコマンドを実行するだけで取得できるハッシュを入れると、実際には「–ダイジェストを表示」などになります。 コマンドを忘れてしまいましたが、それらのハッシュを取得できます。 技術的には、タグは無視されますが、タグは、ファイルにピン留めした内容を人間が知るためのものです。 そのため、SHAハッシュを固定すると、タグは無視され、それが一体何から来たのかを知るためのわかりやすいラベルとして使用しています。

    つまり、Node 20 bookworm は、これがベースになっている Debian のバージョン、つまり最新の Debian であり、次に Slim であることを意味します — 常に Slim Images を使用してください。 また、Docker Hubのすべてのプログラミング言語は、公式イメージを入手できる場合は、常にSlimを使用してください。 Debian の Slim 以外の変種は決して欲しくありませんが、その理由はすぐにわかるでしょう。 非rootとして実行しています。 さて、過去3年間で何かが変わったので、公式のノードイメージにデフォルトで組み込まれているユーザーノードをそこに配置できるようになりました。 ユーザーは既に存在します。 私はそれをそこに置いて、非rootとして実行することができます。 これが鍵です。 多くのKubernetesクラスタ、特に政府や金融などの分野では、コンテナをrootとして実行することはできません。 だから、あなたはそれをしなければなりません。 そして、今、WORKDIRの前にそれを行うと、実際には今年の初めに、おそらく2〜3年前であることを知りましたが、WORKDIRを更新して、その上のユーザーに基づいて適切な権限を割り当てるようにしました。

    したがって、最初にユーザーを配置し、それを非rootにし、そのWORKDIRを作成すると、ノードユーザーに権限が適切に付与されるため、それらを手動で割り当てる必要はありません。 もしあなたが私のノードコースを受講している人なら、私があなたに言っていた方法は、MAKEDIRと入力して、これらすべてのことを実行コマンドで行わなければならないということです。 しかし、もうそれをする必要はありません。 その方が簡単です。 次に、コピーがあります。 そのため、ルートユーザーではなく通常のユーザーとして、適切な権限でコピーしています。 そのため、コピーを行うときはいつでもchownを使用する必要があります。 そして、そこに複数のレベルがあり、パッケージと残りのソースコードの実際のコピーがあります。

    npmのci

    そして、次は何でしょうか? 「npm ci」をやっています。 これは実際には正しくありません、なぜなら私は今日、私たち「npm ci」が3回、または2回変更されたことを知ったからです。 今回で3回目の演出です。 したがって、今後のスライドでは、技術的には「npm ci omit dev」が望ましいことがわかります。 dev をダッシュで省略します。 スライドに表示され、このリポジトリにもあります。 ご覧になっていない方のために、スライドの最後にもう一度置いておきます。 これらすべてのものを含むリポジトリ全体、たとえばDockerファイルがあり、そのリポジトリを毎年更新し続けています。 したがって、これらすべてのメモをより詳細に取得できます。 本当に情報の墓場です。

    したがって、開発の依存関係を削除したり、開発の依存関係を防止したりする「npm ci」を実行していて、コマンドでNPMやその他のプロセスマネージャーをまだ実行していません。 私たちは、NPMを本番環境で使用して、長期にわたるプロセスを開始することは望ましくありませんが、その理由については、後ほど説明します。 それで、私は実際に業界のツールが変わるにつれていくつかのことについて私の意見を変えましたが、そのうちの1つは、これがNPM監査、Trivyスキャン、履歴書セキュリティスキャンを行うのに最適な方法かもしれないことを人々に教えていたことです。 もしかしたら、ステージとマルチステージのDockerファイルを作ることができるかもしれませんが、私は今、いや、もうそれはやらないと言っています。

    業界での私の希望の1つは、CIツールがビルドステージとDockerコマンド、または本質的にDockerの各ステップをCIソリューションで照らすことができるものとして検討し始め、基本的にDockerファイルを使用して多くのCIを実行できるようにすることでした。 そして、多くの自動化、テスト、その他私たちがやらなければならないすべてのこと。 業界ではそうではなかったので、そのための方法としてDockerビルドを提唱し続けましたが、もうお勧めしません。 最新のCI、GitHub Actions、GitLabなどは、NPM監査やCVEスキャンなどを行うためのネイティブサポートが充実しています。 ですから、これらのステージはもうお勧めしませんが、これは素晴らしいことです。 これにより、Dockerファイルが簡素化されます。 私たちはそれをする必要はありません。

    Docker init

    Docker initについて話します。ですから、これは新しいことです。 基調講演でお聞きになりましたね。 Docker init を使用すると、プロジェクトをゼロから開始できるため、独自の Dockerfile が付属しています。 そして、これはそのコマンドを実行した場合のように見えるようなものなので、Dockerを初めて使用する場合、Dockerには、世界中の他のすべてのパッケージマネージャーと同様に、少なくともこのinitオプションがあります。 だから、それは素晴らしいことです。 初めての人には最適です。 私は意見を持っています。 それは、誰にとっても完璧で普遍的なものはありませんよね? そして、たくさんの質問を出し、たくさんの答えを与えて、それから3つのファイルを作成します。 Docker ignore で始まり、Dockerfile で始まり、Compose ファイルを提供します。 ちなみに、今のComposeファイルでは、標準は「compose.yaml」ですが、 Docker compose.ymlではなく、 これは、 10 年間これをやってきた私たち全員が入力してきたものです。 すべてのファイル名は引き続きサポートされますが、これは新しい規則である 'compose.yaml' です。 そのため、これらのファイルを作成し、Dockerの「作成」を行うことを推奨します。

    それでは、時間があるうちに簡単に見てみましょう。 ですから、ここでDockerfileを見ると、実際にはかなり派手です。 ご存じない方のために説明すると、Buildkit がデフォルトのビルダーになったため、フロントエンドと呼ばれるものがあり、Buildkit が動的に更新され、多くの新機能をサポートできるようになりました。 そのため、Dockerfileには多くの新しいことが起こっていますが、必ずしもOCI仕様に含まれているわけではありません。 これは Buildkit で行われ、フロントエンドと呼ばれるものを介して行われます。 したがって、その構文行を入れると、基本的に保証されるのは、すべてのチームメンバーがイメージまたはCIビルドイメージをビルドするときに、全員がBuildkitを本来あるべきように使用していると仮定すると、それが依然として最高のコンテナビルダーであるため、イメージのビルド内で同じ機能セットに対して同じサポートを受けることです。 高度な機能を使い始める場合は、どちらが重要です。 そのうちのいくつかについては、いずれ説明します。 実際、そのうちの1つについて今お話しします。

    これは非常に文書化されたファイルであり、これはすべてDockerによって生成され、ビルド時にファイルをマウントするようなことが見られますよね? つまり、これは何年も前からある Buildkit のフロントエンド機能です。 私はいつもこれを使用したり推奨したりするわけではありません。 私はチームを見て、200メガのノードモジュールをインストールしているのか、それとも0001メガのノードモジュールをインストールしているのかを判断する必要があります。また、ノードモジュールが大きければ大きいほど、これはノードモジュールをキャッシュしているのではなく、それらのノードモジュールのインストールをキャッシュしているため、ノードモジュールを展開する前にこれらのzipをダウンロードする可能性が高くなります。 そのため、構築時のインターネット旅行を節約できます。 これはBuildkit用のDockerビルダーにとって非常に特殊なことであると私は信じているので、Buildkitを使用する必要があります。 繰り返しになりますが、それが最高のものなので、それは問題ありません。

    それで、彼らはあなたにこの素晴らしい小さなファイルを与え、それはあなたがそれを最適化するのを助けます、そしてそれはファイルをコピーするたくさんの段階を持っています。 そして、これはすべて問題ありません。 私が一緒に仕事をしているチームでは、Dockerのノードを初めて使用する場合、これは多くのことを取り入れる必要があると感じています。 私は、チームが歩く前にハイハイをし、走る前に歩くことを教え、助けるようにしています。 これは少し早歩きに近いので、初日のDockerfileではないかもしれませんが、まあ、それは素晴らしいことです。 Dockerはそれを提供します。 私が同意できないことの1つは、彼らがデフォルトでAlpineになっていることですが、これもまた、カンファレンスで何人かの人と話していたのですが、 10 年間、Alpineを本番環境で使用しているチームを支援しようとしてきたが、私はあきらめて推奨していない。

    他に何をしますか? これにより、作成ファイルが提供されますが、これについては後で説明します。 しかし、Dockerfileにはかなり魅力的な新機能がいくつか備わっています。 そのため、熱心な Compose ユーザーであれば、Compose バージョンはもうありません。 このファイルでは、バージョン 2 とバージョン 3のすべての機能をサポートするようになりました。 基調講演でも、誰かがv3でファイルするつもりはありません。4 、それはレガシーと見なされます。 バージョンは必要ありません。 すべての機能は、Compose バージョンを削除する限り、compose コマンドラインで使用できます。 健康診断などについては後ほどお話ししますので、これ以上は触れません。

    適切なベースイメージ

    だから、完璧なベースイメージです。 この話題は、5分でも 50 分でも話せるので、この話で一番好きな部分です。 しかし、私が一緒に仕事をしているほとんどのチームでは、必要なものがすべて揃っていて、望ましくない脆弱性がない適切な基本イメージを見つけるのに多くの時間が費やされています。それは小さいです。これら 3 つまたは 4 つの異なるメトリックをすべて満たしています。 右。 そして、それは存在しませんよね? これはあなたのチームに特有のものであり、私が一緒に仕事をするほとんどすべてのチームは、文化、要件、セキュリティチームの関与に基づいて、異なるパスを選択します。 そして、それはバランスの取れた行為です。 より安全で小さくすればするほど、それを使用するためにより高度になる必要があります。 つまり、チームに何が必要かによります。 また、一部のチームは、デフォルトの公式イメージの1つでまったく問題ありません。

    最初の 3 つから始めましょう。 あなたの人生で決してそれを使わないでください。 それを使用する理由はありません。 その上、大きなネガティブなことの1つは、これらすべてのCVEを見ることができます。 というわけで、これは私が業界で複数のスキャナー、2つのオープンソース、2つのコマーシャルを使用しています。 コマーシャルは誤検知が少ない傾向があることに気づくでしょう。 これは実は最近発見されたことです。 そして、彼らは今週、オープンソースのスキャナーと、誤検知の可能性のある問題を具体的に適用している商用のスキャナーとの間には、間違いなくいくつかの画像に大きな違いがあるということについて、複数の会話をしました。 彼らはそれらをより速く修正する傾向があります。 バックグラウンドで何が起こっているのかよくわかりません。 オープンソースのスキャナーが使えないというわけではありませんが、私にとっては、Docker Scoutはうまく機能していて、本当に新しいものです。 まだ完璧ではありませんが、チームは多くのフィードバックを受け取っています。

    ここでは、Docker Scout が完璧ではないイメージが実際にいくつかあることがわかります。 正しくスキャンされません。 でも、私はいつも2番目のスリムから始めます。 右。 スリムはずっと小さいです。 右。 サイズは4分の1以下で、CVE数では大きな違いがあります。 また、Nodeを実行するために必要なものがすべて揃っています。 ベースイメージ、つまりオリジナルとトップイメージの問題は、特にオープンソースを必要とするチームに見られることです。 OS パッケージ マネージャーの依存関係が必要なため、apt と yum が必要です。 そして、これがどうなるかというと、最初のものは、たくさんのものが含まれているということです。 そして、最初の画像が機能するようになれば、それはうまくいくでしょう。 しかし、Slimを使おうとすると、指定していない依存関係が欠落しているため、ビルドが失敗し、Dockerの初日の経験で、デフォルトのNodeイメージにMercurialが含まれていることに気づかなかったため、ImageMagickがあります。 通常、Nodeイメージには必要のないものがたくさんあります。 ですから、これらがそこにあるとき、それはすべてのビルドツールを持っています。 したがって、バイナリビルドを実行できます。 時にはそれも必要です。 しかし、通常は、独自の実行行を配置して、これらのことを指定します。 右。 だから、あなたはそこに要点を理解します。 ですから、私はそれをお勧めしません。 Alpine のものには素晴らしい CVE のものがありますが、さまざまな理由により、長年にわたる私の講演で聞くことができ、リポジトリだけに行くと、長所と短所について多くの詳細が記載されました。 アルパインは小さくて素敵ですが、一般的にはお勧めしません。 muslとBusyBoxの悪影響なしにAlpineよりも小さくすることができます。

    次は、比較のために Debian をお見せします。 Docker Hubから公式に提供されているこれらのノードイメージはDebianに基づいているため、これに焦点を当てると、多くの脆弱性がベースイメージに起因します。 ノードはそれらについて何もできません。 たとえば、 12 Slim には、より少なく、数が少なくなっていますが、それでもいくつかの脆弱性があります。 そして、あなたはUbuntuを見ることができます。

    ウブンツ

    したがって、Ubuntuは私の推奨イメージの1つになります。 すぐに3つの推奨事項をお伝えしますが、そこにたどり着くには旅をしなければなりません。 したがって、伝統的に、システム管理者である私たちにとって、Ubuntuについて考えるとき、私たちは次のようなLTSについて考えます 20。04 と 22.04、これらはUbuntuの長期安定版リリースです。 コンテナー イメージでは、 22.04 23.04、それはたった1行の変更です。 そして理論的には、新しい依存関係が得られます。 そしてこの場合、あなたは実際に 23の脆弱性が少ないことがわかります。04.

    パッケージマネージャーの長期的な可用性を少し犠牲にしますが、それは少し雑草に埋もれています。 今日はそれについては話しません。 ですから、あなたの会社では、Ubuntu LTSイメージしか使っていないと言っている会社があるかもしれません。 また、AWSやAzureの複数の企業では、すべてのベースイメージに対するアプローチとして、Ubuntuから始めて、そこから独自のイメージを構築していることを知っています。 そのための方法をいくつかご紹介します。

    あなたがそれを行うことができる1つの方法、特にノードは、非常に小さなイメージであるUbuntuを作ることができますよね? Ubuntuの 22.04 は他のすべてのものよりも小さいです、 69 メガ。 また、従来のUbuntuエンタープライズサポートが組み込まれているため、優れています。 長期的なアプリパッケージマネージャーのものが組み込まれています。 インターネット上で十分にサポートされており、十分に文書化されています。 また、Nodeソースを使用して公式のNodeバイナリを追加できます。 ですから、Nodeソースに精通している人なら誰でも、Nodeソースについて聞いたことがあるでしょうし、Nodeをインストールまたは構築したことがある人なら、Nodeソースについて知っているでしょう。 そのため、このリポジトリにあるDockerfileを作成できます。 これを構築する方法を示します。 そして、あなたは彼らのノードソースをインストールするだけです。 この方法の欠点の1つは、私が文句を言ったにもかかわらず、NodeソースチームがNodeをインストールするためにPythonを必要とすることです。 したがって、この場合のNodeイメージにはPythonとそのすべての依存関係が含まれるようになり、Nodeパッケージに脆弱性がもたらされます。 私はそれが気に入らない。 そのため、PythonではなくNodeを使用しています。 だから、私はその選択肢が好きではありません。

    次のオプションは、Dockerfileでcopyコマンドを使用して、NodeイメージからUbuntuイメージにすべてのバイナリをコピーするだけのサイドロードのようなものです。 そして今、あなたはaptを必要としません、あなたはそのような余分なものをすべて必要としません。 あなたはあなたが望むものだけを手に入れます。 小さい画像です。 あなたはここで 225言うことができます。 そのため、他のものよりもスリムです。 また、脆弱性の数も少ないです。 どのスキャナーにも高値や臨界値はありません。 ただし、このアプローチの欠点の 1 つは、バイナリが Snyk を除いて CVE スキャナーによって取得されない可能性があることを意味します。 ええ、Snykはこれらのバイナリを検出しますが、それらはaptによってインストールされておらず、ご存知のとおり、脆弱性はなかったと報告されています。 私は、Docker Scoutがいつの日かそれを行うことを望んでいますし、そうすべきだと彼らに知らせるつもりです。 次に、Ubuntuを 23 または 4に移動するというアイデアがあります 、そしてあなたはそこでスキャンで結果を見ることができます。 23または4はUbuntuの依存関係が22よりも新しいため、CVEは数個少なくなります。

    ディストリビューションレス

    そして最後に、最後の2つはDistrolessですが、ここにいるあなたは誰ですか、Distrolesstを使用している人はいますか? 前もって1つ手に入れた。 したがって、Distrolessはクールなアイデアです。 私には問題があり、小さな点、小さな3つ、4つが見えます。 これらは、これがすべてであるGitHubリポジトリを参照しています。 最後のスライドで、最初のスライドにありました。 しかし、Distrolessには副作用があります。 多くのものをピン留めすることはできません。 それは私が望むように時間の経過とともにバージョンを保持しません。 また、設計方法により、aptなどはインストールされていません。 つまり、これは最終段階であり、本質的に高度な Dockerfile が必要であり、ビルド イメージと、この Distroless イメージにすべてをコピーする運用イメージが必要であることを知っておく必要があります。

    そこで、高度なソリューションを検討しましたが、まだ脆弱性があります。 実際、場合によっては、Ubuntuよりも多くの脆弱性がある可能性があります。 では、Distrolessのポイントは、Distrolessを小さくして安全に保つことだったので、なぜそれを使用するのでしょうか。 そして、それが常に最良の選択であるとは限りません。

    チェーンガード

    そこにある新しいものはチェーンガードです。 チェーンガードについて聞いたことがある人はいますか? 誰でも。 さて、私たちはカップルを手に入れました。 つまり、Chainguardはソフトウェアサプライチェーンセキュリティ会社です。 ご存じない方のために説明すると、私は毎週、このことについてYouTubeのライブストリームをやっています。 YouTubeにゲストに来てもらい、そこで参加してもらいます。 私たちは毎週木曜日にライブをしていて、去年はチェーンガードをやっていて、とても気に入りました。 私の意見では、彼らは基本的に、Wolfiで何をしているかを説明すると、Dockerの公式イメージを取得し、それらをゼロから再設計し、それらを自分たちで保守して、全面的にCVEをゼロにしています。 そして、彼らはそれについて非常に公にしています。 これらはフリー画像です。 有料プランがあり、これらの画像でさらにいくつかのことができますが、箱から出してすぐに多くのことを無料で入手できます。 彼らは独自のレジストリを持っています。 先発するチームには強くお勧めします。

    これは、ナンバーワンではないにしても、私が彼らに使おうとしている私のトップ3の画像の1つです。 少し上級者です。 これらの画像がこのように非常に小さくなると、シェルがないので、少し理解する必要がありますよね? 必要なパッケージがすべて揃っているとは限りません。 だから、あなた、あなた、それは少し難しくなります。 それで、このスライドにたどり着きます。 これらは主な推奨事項です。 順不同です。 彼らはあなたのチームと彼らが必要とするかもしれないものに依存しています。

    ですから、箱から出してすぐに使える簡単な公式イメージを使いたいなら、それはNode-slimですよね? SnykとDocker Scoutによると、現在、重大な脆弱性や高い脆弱性はありません。 したがって、低と中のみです。 最初に定義しておくべきでした。 すみません。 ウェブサイトで定義されています。 申し訳ないです。 そして、2番目の画像は、サイドロードした画像です。 そして、それがどのように見えるかを確認したい場合は、非常に簡単です。 それが正しい用語かどうかはわかりませんが、私はその用語のサイドロードを作り上げています。 だから、コピーを見れば。 したがって、このファイルでは、これがノードをこれに入れる方法です。 これは通常のUbuntuイメージです。 そして、私がその中にノードを取得する方法は、コピーを使用することです。 そして、これは、複数のチームが他のタイプの画像に対してこれを行っているのを目にする正当な方法です。

    そこで、両方の画像を一番上に定義します。 これが私のNodeイメージです。 そして、これが私が行く予定のUbuntuイメージです、ご存知のとおり、後でノードを使用しますが、バージョンを追跡できるように、上部でそれらすべてを見つけたかったのです。 私はこれらをSHAハッシュして、毎回その正確な画像を取得することを保証するハッシュを持つ必要があります。 そして、私は彼らにエイリアスを与えています。 そして、ここで「tini」について少しお話しします。 しかし、ここでは、ある画像から別の画像にノードをコピーしてサイドローディングしています。 正しいNodeバージョンを構築するための公式のNodeイメージを信頼しているからです。 また、Docker Hubから取得したNodeのバージョンを指定できるため、取得しているバイナリを正確に把握できます。 ノードソースやPythonがロードされたり、実際には必要のないaptパッケージの依存関係の副作用なしに、ここにそれらを入れる必要があります。 そして、私はこれを本番環境でテストしました。 これは4年ほど前から出している例ですが、今のところ悪影響はありません。 というわけです。

    したがって、これら3つのオプションはあなたのためです。 そして、一番下にチェーンガードが入ってますよね? そのため、Node-latest イメージです。 Chainguardにバージョンを固定したい場合は、成功率が高まったため、最近ポリシーを変更しました。 また、タグに固定されたバージョンが必要な場合は、有料プランの1つに送信する必要があります。 しかし、私が推奨しているように、いつでもSHAハッシュを固定できます。 そして、彼らは常にそれらのSHAハッシュを利用可能にし、あなたはそれらに頼ることができるので、それは本質的にあなたに同じものを与えています。

    プロセス管理

    次に進みましょう。 よし、プロセス管理だ。 ここにいる何人の人がinitプロセスについて知っているか、tiniまたはNodeでこれらのものを使用していますか? 何人かいますか? まぁ、半分くらいの人だね。 すごい。 だからあなたはこの問題について知っています。 そして、私も意見を持っています。 そのため、DockerとSwarm、そしてKubernetesのNodeプロセスを管理するために、チームと何年も一緒に働きました。 そして、initの問題を理解しようとし、プロセスをシャットダウンします。 そして、基本的にダウンタイムはゼロでデプロイされ、接続を見逃すことはなく、基本的にHTTP pingを見逃すこともないため、シグナルのウサギの穴に落ち、initプロセスが実際に何をしているのか、ゾンビの刈り取りが実際に野生でどのように見えるのか、Nodeにはこれらの問題さえあるのでしょうか。

    そこで、スライドを思いつきました — 今日は、この非常に複雑な決定木を作ることになり、2つの質問でお役に立てることに気づきました。 これが必要かどうかは教えてあげることができました。 そして1つ目は、ほとんどの場合、コンテナでNodeを起動するものとしてtiniを追加することです。 だからnpmではありません。 tiniはDockerに組み込まれているため、私はtiniを好みます。 アプリではサブプロセスが作成されませんが、多くのノード アプリでは作成されません。 ファイルシステムへの呼び出しを行う場合もありますが、必ずしもマシン上で curl やその他のバイナリを生成するとは限りません。 または、本番環境のKubernetesを使用している場合、このオプションについて知らなかった場合は、残念ながらデフォルトではオンになっていませんが、共有プロセス名前空間をオンにできます。 そうすれば、Kubernetesには一時停止コンテナという巧妙なトリックがあります — 一時停止コンテナについて誰が知っていますか?

    コンテナの一時停止

    そのため、一時停止コンテナは、すべてのKubernetesポッドで最初に使用されます。 それは常にそこにあります。 超小型です。 100行とか 50 行とかのコードとか。 そして、それはあなたが必要とするゾンビの刈り取りと保護と信号処理を行います。 それはあなたのためにそれを行いますが、それはポッド内の残りのコンテナとしてプロセスと名前空間を共有している場合に限ります(残念ながら、Kubernetes 112 か何かのように、デフォルトでは行わないことに決めました。 したがって、Kubernetesでこれをtrueに設定すると、ポッド内のすべてのコンテナが同じ名前空間になり、基本的にKubernetesはpauseと呼ばれる無料のinitマネージャーを提供します。 したがって、その場合はtiniは必要ありません。 あなたはそれを避けることができます。

    もう 1 つのケースは、アプリがコード内のシグナルをリッスンする場合で、その方法について質問がある場合は、コード例と HTTP での接続のカウントについて説明した以前の講演へのリンクがあります。 ですから、もしあなたがネットワーキングやオタク的なものに興味を持つなら、そのビデオを探しに行くためのリンクを最後にお渡しします。 しかし、今日はそのすべてを経験することはできません。 しかし、これらの両方が本当なら、tiniは必要ありません。 そして、あなたは自分自身を救うことができます、本当に面倒ではありませんが、あなたは不必要なカプセル化を避けることができます。

    ですから、他のみんなのために、私たちはtiniを持っているべきです。 そこにティーニを入れるべきです。 そして、あなたはそれをここに置いておくべきではありません。 また、exec プローブやヘルスチェックでも使用する必要があります。 実際にファイルシステムを呼び出す場合は、そこでもそれを使用する必要があります。 これは実際に 2019 からの話です。 プロセス管理や信号処理に関しては、今でもすべて関連しています。 個人的には、これらすべてをNodeアプリに書き込むのが好きです。

    そのため、Nodeアプリにはシャットダウン信号が表示されます。 これが機能するかどうかを知る方法は、Dockerではこの値が10でKubernetesが30秒であるため、Nodeコンテナを停止しようとして10秒かかる場合です。ただし、 10 秒以上かかる場合は、initに問題があります。 そして、何が起こっているかというと、NodeはLinuxからの信号を認識しておらず、カーネルは今すぐシャットダウンする必要があると言っています。 そして、Nodeはデフォルトで、これはPythonや他の多くのプログラミング言語にも当てはまるため、デフォルトではこれらのシグナルをトラップしません。 そのため、彼らはそれを無視し、Dockerはそれを強制終了する必要があります。 これが 10秒の待ち時間です。 ですから、Nodeアプリのサンプルのオンラインデモをたくさんやっていると、CやDockerの停止などを制御しても、 10 秒間だけそこにあることに気付くでしょう。 それは、信号を聞いていないからです。 これらはすべてinitで修正できます。

    Compose の更新

    更新を作成します。 私のお気に入りの開発者ツールである compose について話しましょう。 ここ3、4年で変化がありました。 そのため、以前の仮想 DockerCon に参加したことがない場合は、これらの変更すべてに気づいていない可能性があります。

    そこで、変更点の簡単な例をいくつか紹介します。 バージョンはありません。 とおっしゃいました。 わーい、Swarmでない限り。 あなたがまだSwarmにいるなら、それは素晴らしいことです。 Swarmファンのコミュニティは増え続けており、明日、廊下のトラックで実際に会う予定です。 Swarmでは、 v3、まだ古いバージョンのCompose仕様上にあるか、技術的には使用されていないため、vが必要です。 しかし、それ以外の人にとっては、それを取り除くことができ、過去 10 年間の Compose で一緒に使用できなかった多くの機能を手に入れることができました。 しばらくお付き合いいただいている方なら、v2の機能がv3に入らなかったため、v2 と v3を決定しなければならない日があったことをご存知でしょう。それで、道に分岐点がありました。 少し複雑でした。

    今、私たちがv2 で持っていたすべての機能と、v3 で持っていたすべての機能がすべて、幸せな家族として再び一緒になりました。 そして、私が一緒に仕事をしている多くのチームが使用しておらず、知らなかった私のお気に入りの1つは、...人々は「depends_on」について聞いたことがありますが、それが本当に彼らが思っていたことをしていないことに気づきます。 Nodeアプリが起動する前に、データベースのスキーマが読み込まれるのを待ちたかったのです。 まあ、あなたはそれを行うことができます。 あなたはそれを行うためにこの特定の方法を使用する必要があります。 「depends_on」を入力し、データベースなど、依存するサービスを定義します。 そして、あなたは健康なサービスの状態を言います。

    そして、その本当のクイックのYAMLファイルをお見せします。 だから、あなたは私が何を見ているのか知っています。 そして、これが私のNodeアプリのために私が行うことです。 私はDBを「depends_」と言います。 条件は正常である必要があります。 だからあなたはこれを行うことができます。 30つの異なるマイクロサービスを含む Compose ファイルを見てきました。また、新しいプロファイル機能を使用して、実際にそれらをチャンクに格納し、別々の時間に読み込むことができます。 そして、それらはRedisとPostgres、そしてバックエンドワーカーに依存しています。 そして、これらすべてが最初に実行されなければなりません。 そのため、他の何かに依存するすべてのサービスにそれを追加します。 次に、依存サービスで、正常性チェックを追加します。

    また、データベースでは、Postgresのヘルスチェックを行うだけで、これは実際には非常に簡単なものです。 私は実際にここに入ることができます。 また、SQL クエリを実行し、特定のレコードを検索します。 そのため、データベースをシードしたことがわかります。 つまり、これは単純なDockerヘルスチェックです。 ご存じのとおり、Kubernetesで行うのと同じ種類のヘルスチェックです。 そして、データベースやRedisなど、バックエンドにそれがある限り、Dockerを構成すると、そこに座って、ヘルスチェックが緑色になるまで待ってからサービスを開始します。 そして、これらを連鎖させることができます。 そのため、バックエンド API がデータベースを待機し、フロントエンドが API を待機するようにすることができます。 これらを上まで連鎖させることができます。 そして、それをすべて入れるのはYAMLの 10 行です。 そのため、最新バージョンでそれを取得しています。

    次は、拡張とCLIのオーバーライドです。 皆さんが作成作業をスケールアップしたかどうかはわかりませんが、includesは、作成ファイルの先頭やどこにでも表示できるまったく新しい機能です。 作成ファイルのルートに配置します。 他にも持ち込んでほしいファイルがあります。 Extendsはもう少し柔軟で、私はそれが好きです。これは、私たちが長い間持っていた非常によく似た機能です。 そして、CLIオーバーライドは、チーム全体に作成ファイルを提供できるため、正直なところ、私が最もよく使用するものです。 そして、それらはすべて、compose override.yaml という別のファイルを作成できます。 そして、そのファイルは、開発セットアップの環境変数を含むすべての設定を変更します。 したがって、異なるポートが必要な場合や、異なる環境変数または異なるパスワードが必要な場合。 そして、そのファイルを無視して無視し、別の合成ファイルを必要とせずに、誰もが独自のカスタムセットアップを持つようにします。

    また、CI テストなどのオーバーライドを行うこともできます。 そのため、すべての CI テスト値を入力するオーバーライドを使用できます。 また、単純な基本の通常の Compose ファイルを作成し、カスタマイズをオーバーライドすることもできます (オーバーライドと呼ばれます)。 したがって、ドキュメントでそれらをすべて調べることができます。 実際、私は1つをクリックしてそれを表示するつもりでしたが、あなたは要点を理解しています。 最近、ブログ記事がありました。 Nicholas氏は、 Docker Composeの改善に関する素晴らしいブログ記事を投稿した。 1 つの作成セットアップに組み込まれるさまざまな YAML ファイルを作成するさまざまな方法をすべて説明します。 そして、それはすべての方法、そしてそれぞれの長所と短所、そしてなぜあなたが他のものよりも一方を使いたいのかの非常に素晴らしいウォークスルーです。

    次は。 開発、彼らは基調講演でこれを示しましたか? 思い出せません。 つまり、開発は時計にとってまったく新しいものなのです。 時計については後ほど説明します。 時計は今年の私のお気に入りの新機能です。 また、ほとんどの人が知らない新機能も入手でき、Nodeとは関係ありませんが、「docker compose ls」が得られます。 そのため、複数のプロジェクトがすべて実行されている場合、実際には 1 つのコマンドですべてを確認できます。 かなり便利です。 実行中のものや、忘れていた他のディレクトリがあるかどうかを確認できます。

    そして、先月「docker compose alpha publish」がローンチされたばかりです。 そして、これは私が約5年前から求めていたことです。 次に、そのコマンドで作成ファイルを配置します。 基本的にはイメージに自動的に配置され、レジストリにプッシュされるため、コードなしで作成ファイルをデプロイ可能なオブジェクトまたはアーティファクトとして共有できます。 そして、これはKubernetes用です。 Helm には Kubernetes マニフェストのカスタマイズなどがありますが、Compose には先月までありませんでした。 だから、それはそこにあります。

    したがって、compose watchは一番上にこのように見えます。 「docker compose watch」と入力しています。 そして、それには追加のyamlが必要ですが、これについては後ほど説明します。 しかし、その余分なyamlを追加すると、ほとんどの場合、開発用のバインドマウントを行う必要がなくなります。 NPMのインストールパフォーマンスや、バインドマウントを使用したローカルマシンでのビルドパフォーマンスに苦労している人はいますか? Mutagenを試し、docker syncを試しました。 ハードコアな場合は、rsyncを試してみてください。 いろんなクレイジーなことをするかもしれない。

    さて、今、多くのケースで compose ウォッチがあります — 私が話したり、一緒に作業したり、例を見せたりしている人たちは、ソースコードの束縛を回避できるようになったと言っています。 そのため、ホスト上のファイルの変更を監視し、バックグラウンドでコンテナにコピーするか、構成に基づいてイメージを再構築します。 そのため、特にMac、Windows側で対処しなければならないOS境界間のバインドマウントを回避できます。

    ここで最後に、このセクションです。 もしあなたが以前に冷徹な目だったら、これを見て、一体何だと思ったかもしれません。 だからこれは私のNodeアプリであり、これを使用して、パッケージロックファイルのパッケージを変更した場合に、「docker compose watch」を実行するたびにイメージを自動的に再構築することを通知しています。 そして、ディレクトリに何かがないか監視し、変更された場合は、実行中にそのファイルをコンテナに同期します。

    node monはコンテナ内にあり、コンテナ内の変更を確認し、コンテナ内のアプリを再起動するため、コンテナを完全に再起動するよりも少し高速であるため、おそらくnode monのようにこれを実行する必要があります。 したがって、Nodeアプリ用にそれを追加すると、Node固有ではありませんが、Node開発者にとっては非常に便利です。 その後、これを実行するたびに、実際に何をしているかを確認できます。 これは、イメージをプルし、イメージを構築し、それらをすべてサービスとしてスピンアップし、非常に下部の小さなテキストまで表示するため、「docker compose up」に取って代わります。 それは見守ると言っており、それは私のホストが変化を監視している場所へのパスを私に与えます。 つまり、node mon や他のファイル監視ユーティリティの 1 つに似ていますが、バインドマウントなしでコンテナの境界を越えて発生します。 かなりクールです。

    生産チェックリスト

    大丈夫です。 最後に、ご質問があれば、数分お時間をいただきますが、これは制作を開始するための簡単なチェックリストです。 これらは私が精神的に考えていることであり、Nodeでのステータスに関係なく、チームと一緒に仕事をしています。 生産に入る前に、彼らはこれらのことをしていますか? それは非常に焦点を絞っているわけではありませんが、明らかに「docker無視」ファイルです。 私が一緒に仕事をしているチームの中には、コンテナの最初の1年か2年で、Dockerの無視が必要であることに気づいていない人がたくさんいるのは驚くべきことです。 git ignoreファイルのコピーを作成し、それにノードモジュールを追加すると、通常、ノードまたはroot以外のユーザーとして実行されているという問題が解決されます。 右。

    彼らはtiniまたは別のinitプロセスを使用しています。 彼らは、本番環境で mon をノード化するために PM を使用せずに Node を直接呼び出しています。 ご存知のように、PMやyarn、その他のツールでは、ノードを直接呼び出したい — 少なくとも、tini に Node を直接呼び出してもらいたいのです。 健康診断を受けたい。 これらのプローブは Kubernetes で必要になります。 ただし、Dockerでは、ヘルスチェックとDockerファイルを入力するだけです。 あなたがそれを持っているなら、あなたはデータベースを待つために「depends_on」を使うことができると思いますよね? しかし、そのために、ノードにAPIが戻ったと想像してください。 Dockerfile にヘルスチェックを追加した場合、他の開発者は、手動ヘルスチェックの追加作業を行うことなく、依存関係を簡単に設定できます。

    したがって、Dockerfileに入れると、作成ファイルでそれを回避できます。 omit dev コマンドと npm ci コマンドを使用します。 それが、私たちが常に制作の進め方です。

    あなたのソースコードでは、これらは私があなたにやってもらいたいことです。 あなたのチームがNodeのソースコードを制御していると仮定して、SIGTERMとSIGINTのプロセスをキャプチャし、適切なシャットダウンを処理するようにお願いします。 Webサイト、Webシステム、ダウンタイムゼロのデプロイを探している場合、基本的には、おそらくシステムのあるレイヤーで、HTTP接続を監視し、FINパケットをフロントエンドブラウザに送信し、クライアントが何であれ、それらを別の正常なコンテナに自動的にルーティングする必要があります。 このコンテナはシャットダウン中だからです。 そして、stoppableのようなプロジェクトを調べることができますが、これはnode.js、 npmプロジェクトは、接続を適切にカウントし、基本的に人々を切断してハード接続をリセットすることなく、ノードコンテナの正常なシャットダウンを行う方法であるFINパケットを提供します。

    ファイルI/Oをやっている場合、画像をアップロードしてファイルシステム上の何らかのシステムに保存するなど、まだ多くのファイルI/Oを行っているチームと仕事をして学んだことは、ある時点で権限が本番環境でお尻を噛むことになるということです。 特に、ネットワーク上でNFSなどを使用している場合はなおさらです。 そのため、ノードの起動時に適切な権限を探すコードを配置してもらい、期待する場所に適切な権限が表示されない場合、アプリがクラッシュします。 というのも、多くの場合、本番環境に進み、数日後には誰かがPDFレポートやアプリなどをアップロードするなど、ユニークなことをするからです。 そして、誰かがAWS EC2 を変更し、突然停止したり、少なくともユーザーが本当に悪い経験をしたりするために、権限の問題があります。

    そのため、ノードの起動中にディスクに書き込む場合は、ファイルのアクセス許可の確認を開始することを学びました。 HTTP でリッスンしている場合は、Docker、Compose、Swarm、Kubernetes など、あらゆるものがアプリを監視できるように、共通の標準正常性、正常性エンドポイントを提供します。 HTTP アプリを使用せず、リッスン ポートがない場合、通常は 30 秒ごとに書き込み、ディスク上のファイルに正常性状態を書き込み、プローブまたは正常性チェックでそのファイルの日付タイムスタンプを探します。 または、そのファイルの内部を見て、私たちが与えたデータを探してください。 これが、非上場サービスへの対処方法です。

    そして最後に、Kubernetesポッドについては、Dockerだけでなく、すべてのコンサルティングクライアント、すべての学生に使用している推奨ポッド仕様があります。 そして、それをつかんでください。 30秒をもらったので、私はそれを通過させるつもりはありません。しかし、この例は、すべてのセキュリティ機能と、ポッド仕様に必要なすべてのものを提供し、現在は持っていない可能性があるものを準備しておく必要があります。 プローブ、リスナー、terminationGracePeriodSeconds の設定、特権とエスカレーションの無効化、非特権ユーザーとして実行していることを確認すること、およびセキュリティ チームが満足できるようにそれを適用することについて説明します。 そして最後に、Dockerがデフォルトで持っているsetcompProfilesを有効にしますが、すべてのポッドまたはクラスターのレベルで行わない限り、Kubernetesはデフォルトで無効にします。

    それでおしまい。 時間がなくなってしまったので、質問を受け付けておきます。 ありがとうございます。

    さらに詳しく

    ドッカーは初めてですか?始めましょう

    この記事には、DockerCon 2023のプレゼンテーションの YouTube トランスクリプトが含まれています。 「Docker rocks in Node.js, 2023 Ed」は、Docker Captain で DevOps Dude の Bret Fisher 氏によって発表されました。

    自分に合ったサブスクリプションを見つける

    今すぐ専門家に連絡して、Dockerサブスクリプションのコラボレーション、セキュリティ、サポートの完璧なバランスを見つけてください。