Dockerは、アプリケーションのパッケージ化と実行を簡素化するコンテナー化プラットフォームです。コンテナは、独自のファイルシステムを備えた分離されたプロセスとして実行されますが、ホストのカーネルを共有します。 Dockerは、再現可能な開発環境と分散デプロイメントアーキテクチャを実装する方法として注目を集めています。
Node.jsは、バックエンド開発用の主要なJavaScriptランタイムです。 Node.js Webサービスを正常に起動するには、ランタイムがインストールされた環境、使用可能なアプリケーションコード、およびクラッシュが発生した場合の自動再起動を処理するメカニズムが必要です。
このガイドでは、Dockerを使用して、人気のあるExpressWebフレームワークで作成された単純なNode.jsアプリをコンテナー化します。 Dockerは、サービスの実行に必要なすべてのものを含む一貫した環境を生成するため、ノードベースのシステムをデプロイするための優れた方法です。 Dockerデーモンは、フォアグラウンドプロセスがクラッシュしたときに失敗したコンテナーを再起動するためのサポートを統合し、Node.jsデプロイメントの課題の1つを解決します。
アプリケーションの実装の詳細はスキップします。プロジェクトのディレクトリを作成し、その中にサーバーコードを追加します。これが基本的なapp.js
です ポート8080でリッスンし、ハードコードされた応答ですべての要求に応答します:
const express = require("express"); const app = express(); app.get("*", (req, res) => res.send("<p>It works!</p>")); app.listen(8080, () => console.log("Listening on 8080"));
npmを使用してプロジェクトにExpressを追加します:
npm init npm install --save express
アプリを起動して、動作をテストします:
node app.js
localhost:8080
にアクセスできるはずです ブラウザでサンプルの応答を確認してください。
次に、プロジェクトのDocker化を開始します。まず、アプリケーションの画像が必要です。イメージは、コードと依存関係を、コンテナーインスタンスの開始に使用する単一のパッケージとしてカプセル化します。 Dockerfileの手順は、コンテナの初期ファイルシステムの状態を定義します。
サンプルアプリケーションで機能するDockerfileは次のとおりです。
FROM node:16 WORKDIR /app COPY package.json . COPY package-lock.json . RUN npm ci COPY app.js . CMD ["app.js"]
このDockerfileは、 FROM
を介して公式のNode.jsDockerイメージをベースとして選択します 声明。画像はベース内のすべてを継承し、次の手順でコンテンツを追加します。
作業ディレクトリは/app
に設定されています WORKDIR
による ライン。次のCOPY
ステートメントはファイルを/app
に配置します コンテナイメージ内のディレクトリ。
次の段階は、npmの package.json
を追加することです npm ci
を実行します 。これにより、プロジェクトのnpm依存関係(この場合はExpress)がコンテナのファイルシステム内にインストールされます。
COPYnode_modules/を使用しないでください。
既存のnode_modules
をコピーします プロジェクトディレクトリ内のフォルダ–これにより、他のビルド環境でDockerfileを再利用できなくなります。 Dockerfilesを使用すると、ソース管理リポジトリのコンテンツだけで一貫したビルドを作成できます。 .gitignore
にファイルまたはフォルダがある場合 、Dockerfile COPY
で参照しないでください 指示。
npm ci
の後 が実行されると、アプリのコードが画像にコピーされます。このCOPY
の配置 RUN
の後の命令 、以前のコピーからそれを分離することは、意図的です。各命令は、画像に新しいレイヤーを作成します。 Dockerのビルドプロセスは、後続のビルドを高速化するために各レイヤーをキャッシュします。 1つのレイヤーのコンテンツが変更されると、後続のすべてのレイヤーのキャッシュが無効になります。
これが、アプリケーションコードを npm ci
の後にコピーする必要がある理由です。 実行されました。コードは通常、npmロックファイルの内容よりもはるかに頻繁に変更されます。コードの変更のみを伴うイメージの再構築は、 RUN npm ci
を効果的にスキップします ステージ(およびそれ以前のすべてのステージ)。依存関係が多い場合は、プロセスを大幅に加速します。
Dockerfileの最終段階では、 CMD
を使用します コンテナの起動時にアプリを自動的に実行するための指示。これは、Node.jsベースイメージが node
を使用するように構成されているために機能します そのエントリポイントとして処理します。 CMD
継承されたエントリポイントに追加され、 node app.js
になります 新しい画像のフォアグラウンドプロセスとして実行されます。
次に、イメージを作成する必要があります:
docker build -t node-app:latest .
DockerはDockerfile
を取得します 作業ディレクトリで、その中の手順を実行し、結果のイメージに node-app:latest
のタグを付けます。 。最後の。
(ピリオド)は、イメージビルドコンテキストとして作業ディレクトリを指定します。これにより、 COPY
が参照できるパスが決まります。 Dockerfileの手順。
ビルドの最適化
ビルドのパフォーマンスを向上させる1つの方法は、 .dockerignore
を追加することです。 プロジェクトのルートにファイルします。ファイルに次の内容を与えます:
node_modules/
このファイルは、作業ディレクトリ内でしないパスを定義します。 ビルドコンテキストに含まれます。 Dockerfile内でそれらを参照することはできません。 node_modules
の場合 、 RUN npm ci
を介して依存関係を新たにインストールするため、このディレクトリのコンテンツはビルドとは無関係です。 命令。特にnode_modules
を除外します 作業ディレクトリにすでに存在しているため、これらすべてのファイルをDockerの一時的なビルドコンテキストの場所にコピーする必要がありません。これにより、効率が向上し、ビルドの準備にかかる時間が短縮されます。
この時点で、Dockerを使用してアプリケーションを実行する準備が整いました:
docker run -d -p 8080:8080 --name my-app --restart on-failure node-app:latest
docker run
コマンドは、指定されたイメージから新しいコンテナインスタンスを開始するために使用されます。意図されたユースケースに合わせてコンテナを適切に構成するために、いくつかのフラグが追加されています。
-
-d
–シェルをコンテナのフォアグラウンドプロセスから切り離し、バックグラウンドサーバーとして効果的に実行します。 -
-p
–ホストのポート8080をコンテナー内のポート8080にバインドします(Expressサンプルアプリがリッスンするように構成されています)。これは、localhost:8080
へのトラフィックを意味します 対応するコンテナポートに渡されます。8100:8080
など、バインド定義の最初の部分を変更することで、ホスト投稿を別の値に変更できます。localhost:8100
でコンテナにアクセスするには 。 -名前コード> –他のDockerCLIコマンドで参照するために使用できるわかりやすい名前をコンテナーに割り当てます。
-再起動
–コンテナに適用する再起動ポリシーを選択します。on-failure
設定は、アプリケーションがクラッシュしたために失敗コードで終了した場合、Dockerがコンテナを自動的に再起動することを意味します。
前の手順で作成されたイメージは、 docker run
の最後の引数として参照されます。 指図。コンテナIDがターミナルウィンドウに出力されます。 localhost:8080
にアクセスすると、Node.jsアプリにアクセスできるはずです。 また。今回は、サーバーが node
を使用する代わりに、Dockerコンテナ内で実行されています ホストにインストールされているプロセス。
Dockerは、アプリケーション環境全体をコンテナー化することにより、Node.jsWebサービスのデプロイを支援します。 1回のdockerrun
でイメージからコンテナを開始できます Dockerがインストールされている任意のホストでコマンドを実行します。これにより、Node.jsのバージョンの維持、npmモジュールのインストール、アプリケーションプロセスの再起動が必要な状況の監視の複雑さが解消されます。
コードを変更して更新を開始する場合は、Dockerイメージを再構築し、 docker rm
を使用して古いコンテナーを削除します。 。その後、改訂されたイメージを使用する置換インスタンスを開始できます。
本番環境では、少し異なるルーチンが必要になる場合があります。 docker run
で通常のDockerインストールを使用できますが 、これは、最も単純なアプリケーションを除くすべてのアプリケーションにとって扱いにくい傾向があります。 Docker ComposeやKubernetesなどのツールを使用して、リポジトリ内でバージョン管理できるファイルにコンテナ構成を定義するのが一般的です。
これらのメカニズムにより、 docker run
を繰り返す必要がなくなります。 新しいコンテナを開始するたびにフラグが立てられます。また、コンテナのレプリケーションを容易にして、サービスを拡張し、冗長性を提供します。リモートホストにデプロイする場合は、イメージをDockerレジストリにプッシュして、本番マシンから「プル」できるようにする必要もあります。
プロダクション固有のもう1つの考慮事項は、トラフィックをコンテナにルーティングする方法です。最初はポートバインドで十分ですが、最終的には、それぞれが同じポートでリッスンする1つのホスト上に複数のコンテナが必要になる状況になります。この場合、リバースプロキシをデプロイして、ドメイン名やヘッダーなどのリクエスト特性に基づいてトラフィックを個々のコンテナポートにルーティングできます。