Day11:本番用Dockerfile(後半)
テーマ:本番運用に耐える“最適化された Dockerfile”を作るための実践テクニックを深掘りする
後半では、前半・中盤で理解した
「マルチステージビルドの仕組みと効果」
をさらに実務レベルへ引き上げます。
ここでは、
キャッシュ最適化・alpine の注意点・セキュリティ強化・本番運用の落とし穴
といった、現場で必ず必要になる知識を丁寧に解説します。
マルチステージビルドを“さらに強くする”キャッシュ最適化
キャッシュを最大限活かす Dockerfile の書き方
Docker は 上から順にレイヤーをキャッシュ します。
そのため、キャッシュを効かせる書き方をするとビルドが爆速になります。
最適化された構造
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install --production=false
COPY . .
RUN npm run build
Dockerfileなぜこれが速いのか
package.jsonが変わらない限り、npm installのレイヤーがキャッシュされる- コード変更だけなら
COPY . .以降しか再ビルドされない - 大規模プロジェクトほど効果が大きい
実務では、
「package.json を先に COPY する」
は必須テクニックです。
node:18-slim と node:18-alpine の違いを深掘りする
slim は「軽量な Debian」
- 安定性が高い
- 互換性が高い
- ほとんどの Node.js ライブラリが問題なく動く
alpine は「超軽量(約5MB)」
- 速い
- 小さい
- しかし musl libc を使うため、
ネイティブモジュールが動かないことがある(bcrypt など)
実務での結論
- 迷ったら slim を使う
- ネイティブ依存がない場合のみ alpine を検討
- 本番で alpine を使う場合は必ず動作確認が必要
セキュリティ強化:本番イメージで root を使わない
コンテナ内で root のまま動かすのは危険
攻撃者が侵入した場合、
root 権限で OS にアクセスされる可能性があります。
対策:ユーザーを作って切り替える
FROM node:18-slim
WORKDIR /app
RUN useradd -m appuser
USER appuser
COPY --from=build /app /app
CMD ["node", "app.js"]
Dockerfileこれで何が変わるか
- コンテナ内の権限が最小化される
- 侵害された場合の被害が限定される
- セキュリティスキャンでも高評価になる
実務では 非 root 実行は必須 です。
本番運用での“落とし穴”とその回避方法
1. node_modules の扱い
ビルドステージで npm install を行う場合、
runtime ステージにコピーされるのは ビルド済みの node_modules です。
しかし、alpine と slim ではバイナリ互換性が違うため、
build ステージと runtime ステージの OS が違うと壊れる
ことがあります。
例:
build → node:18
runtime → node:18-alpine
→ ネイティブモジュールが壊れる
対策
- build と runtime は 同じ系統の OS を使う
(node:18 → node:18-slim は OK) - alpine を使うなら build も alpine にする
本番用 Dockerfile の“完成形”を示す
最適化された本番用 Dockerfile
# --- Build Stage ---
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install --production=false
COPY . .
RUN npm run build
# --- Runtime Stage ---
FROM node:18-slim
WORKDIR /app
RUN useradd -m appuser
USER appuser
COPY --from=build /app /app
CMD ["node", "app.js"]
Dockerfileこの構造が実務で強い理由
- build と runtime を分離
- slim で軽量化
- root を使わない
- キャッシュ最適化済み
- セキュリティリスク最小化
これが 本番運用に耐える Dockerfile の基本形 です。
後半まとめ
あなたがここまで理解できていれば、Day11 のゴールは完全達成です。
- キャッシュを最大限活かす Dockerfile の書き方が分かる
- slim と alpine の違いを理解して使い分けられる
- 本番では root を使わない理由が説明できる
- build と runtime の OS を揃える重要性を理解している
- 最適化された本番用 Dockerfile を自分で書ける

