今回やること
Dockerは、アプリと実行環境をイメージにまとめ、そのイメージから隔離されたプロセスをコンテナとして動かす道具です。
この記事では、Node.jsの小さなWebアプリを次の順で動かします。
- アプリとlockfileを作る
- 単一の
Dockerfileからイメージを作る - コンテナを起動してHTTP応答とログを確認する
- コンテナを停止・削除する
Docker Composeやマルチステージビルドは、最初の1コンテナを理解した後に扱います。

前提条件
- 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 package.json package-lock.json ./
RUN npm ci --omit=dev
COPY 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のCOPYやARGへ値を書かないでください。
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 listeningとGET 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.jsonとpackage-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で対象を確認し、不要なら停止・削除してから再実行します。
練習
- JSONの
messageを自分の文章へ変える - タグを
ada-node:2にしてbuildする ada-node:1と:2をdocker image ls ada-nodeで比較する:2のコンテナを起動し、新しい応答を確認する
タグを変えると、どのイメージからコンテナを作ったか区別できます。
次のステップ
次はDockerマルチステージビルドで、ビルド工程と実行工程を分ける方法を学びます。日常的なコマンド確認にはDockerチートシートを使ってください。
複数コンテナを連携させるDocker Compose、実行時secret、イメージの脆弱性検査は、それぞれ別の学習ゴールとして扱うと理解しやすくなります。
参考リソース
- Docker公式: Get started
- Docker公式: Node.js language guide
- Docker公式: Dockerfile best practices
- Node.js公式: Releases