Docker入門 - Node.jsアプリを1つコンテナで動かす

中級 | 20分 で読める | 2025.12.02

公式ドキュメント

今回やること

Dockerは、アプリと実行環境をイメージにまとめ、そのイメージから隔離されたプロセスをコンテナとして動かす道具です。

この記事では、Node.jsの小さなWebアプリを次の順で動かします。

  1. アプリとlockfileを作る
  2. 単一のDockerfileからイメージを作る
  3. コンテナを起動してHTTP応答とログを確認する
  4. コンテナを停止・削除する

Docker Composeやマルチステージビルドは、最初の1コンテナを理解した後に扱います。

source code、Dockerfile、.dockerignoreをdocker buildへ入力してimageを作り、secretはimageへ含めず実行時に渡してcontainerを起動する図

前提条件

  • Docker DesktopまたはDocker Engineが起動している
  • ターミナルの基本操作ができる
  • ポート3000を他のアプリが使っていない

2026年7月25日時点では、Node.js 24がLTSです。Node.js 26はCurrentであり、まだLTSではありません。この例ではLTSのメジャー版を示すnode:24-alpineを使います。

まずDockerへ接続できることを確認します。

docker version

ClientとServerの両方が表示されれば準備完了です。

1. 最小のNode.jsアプリを作る

mkdir docker-node-practice
cd docker-node-practice
npm init -y
npm pkg set scripts.start="node server.js"
npm install --package-lock-only

最後のコマンドでpackage-lock.jsonを作ります。Dockerfile内でnpm ciを使うには、このlockfileが必要です。

server.jsを作ります。外部パッケージは使いません。

const http = require("node:http");

const port = 3000;
const host = "0.0.0.0";

const server = http.createServer((request, response) => {
  console.log(`${request.method} request received`);

  response.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
  response.end(JSON.stringify({ message: "Hello from Docker" }));
});

server.listen(port, host, () => {
  console.log(`Server listening on http://${host}:${port}`);
});

コンテナの外から接続できるよう、待受アドレスはlocalhostではなく0.0.0.0にします。

2. Dockerfileを作る

プロジェクト直下に、拡張子なしのDockerfileを作ります。

FROM node:24-alpine

WORKDIR /app
ENV NODE_ENV=production

COPY --chown=node:node package.json package-lock.json ./
RUN npm ci --omit=dev

COPY --chown=node:node server.js ./

USER node
EXPOSE 3000

CMD ["node", "server.js"]

このDockerfileには3つの安全上のポイントがあります。

  • 依存関係はlockfileどおりにnpm ciで入れる
  • 実行時は管理者権限のrootではなく、ベースイメージのnodeユーザーを使う
  • COPY . .を使わず、必要な3ファイルだけをコピーする

3. .dockerignoreを作る

.dockerignoreは、docker buildへ送らないファイルを指定します。

node_modules
npm-debug.log*
.git
.gitignore
.env
.env.*
!.env.example

.env、秘密鍵、クラウド認証情報などをイメージへコピーしてはいけません。一度イメージのレイヤーへ入れた秘密情報は、後の命令で削除しても履歴に残る可能性があります。

この例は秘密情報を使いません。実サービスで秘密情報が必要な場合は、実行環境のsecret管理機能を使い、DockerfileのCOPYARGへ値を書かないでください。

4. イメージをbuildする

Dockerfileがあるフォルダーで実行します。

docker build --tag ada-node:1 .

作成された対象を確認します。

docker image ls ada-node

ada-nodeのタグ1が表示されれば、イメージ作成は成功です。

5. コンテナをrunする

docker run \
  --detach \
  --name ada-node \
  --publish 3000:3000 \
  ada-node:1

Windows PowerShellでは1行で実行できます。

docker run --detach --name ada-node --publish 3000:3000 ada-node:1

--publish 3000:3000は、PC側のポート3000をコンテナ側のポート3000へつなぎます。

成功確認

別のターミナルでHTTP応答を確認します。

curl http://localhost:3000

次のJSONが表示されれば成功です。

{"message":"Hello from Docker"}

Windows PowerShellでは、次でも確認できます。

Invoke-RestMethod http://localhost:3000

次にログを確認します。

docker logs ada-node

Server listeningGET request receivedが表示されることを確認してください。

後片付け

動いている対象名を確認します。

docker ps --filter name=ada-node

対象が今回作ったada-nodeであることを確認してから、停止して削除します。

docker stop ada-node
docker rm ada-node

イメージは再利用できるため、通常は残して構いません。ディスクから削除したい場合だけ、対象のrepositoryとtagを先に確認します。

docker image ls ada-node
docker image rm ada-node:1

docker system pruneのように広い範囲を一括削除するコマンドは、この練習では使いません。

よくあるつまずき

npm ciでlockfileのエラーになる

package.jsonpackage-lock.jsonの内容が一致していません。ホスト側で次を実行してlockfileを更新してから、もう一度buildします。

npm install --package-lock-only
docker build --tag ada-node:1 .

Cannot connect to the Docker daemonと表示される

Docker DesktopまたはDocker Engineが起動しているか確認します。権限設定が必要なLinux環境では、Docker公式の導入後手順を確認してください。

ポート3000を使用できない

PC側だけ別のポートへ変更できます。

docker run --detach --name ada-node --publish 3001:3000 ada-node:1
curl http://localhost:3001

コンテナがすぐ終了する

停止済みコンテナとログを確認します。

docker ps --all --filter name=ada-node
docker logs ada-node

server.jsの構文やCMDのファイル名を確認してください。

同じ名前のコンテナがある

前回のada-nodeが残っています。docker ps --all --filter name=ada-nodeで対象を確認し、不要なら停止・削除してから再実行します。

練習

  1. JSONのmessageを自分の文章へ変える
  2. タグをada-node:2にしてbuildする
  3. ada-node:1:2docker image ls ada-nodeで比較する
  4. :2のコンテナを起動し、新しい応答を確認する

タグを変えると、どのイメージからコンテナを作ったか区別できます。

次のステップ

次はDockerマルチステージビルドで、ビルド工程と実行工程を分ける方法を学びます。日常的なコマンド確認にはDockerチートシートを使ってください。

複数コンテナを連携させるDocker Compose、実行時secret、イメージの脆弱性検査は、それぞれ別の学習ゴールとして扱うと理解しやすくなります。

参考リソース

← 一覧に戻る
PR
PR
PR
PR