Dockerfile 本番アンチパターン集

はじめに

Dockerfile は、Docker を使い始めた頃は
「アプリが起動すればOK」 という感覚で書かれがちです。

しかし、Dockerfile は単なる起動設定ではありません。
本番環境においては、

  • どの OS・どのライブラリが含まれるか
  • どの権限でアプリケーションが動くか
  • 障害時に調査できるか
  • セキュリティ事故が起きたとき、被害を最小限に抑えられるか

といった 運用・セキュリティ・信頼性すべてに影響する設計書 です。

Dockerfile の怖い点は、
「今は動いている」「問題が起きていない」状態でも、
将来の事故要因を静かに抱え込んでしまう
ところにあります。

この記事では、実務現場で本当によく見かける
Dockerfile の本番アンチパターンを取り上げ、

  • なぜそれが危険なのか
  • 実際にどんな事故につながるのか
  • どう直せばよいのか
  • 手元で確認できるハンズオン

までを、できるだけ具体的に解説します。


アンチパターン①:latest タグを使い続ける

❌ 悪い例

FROM node:latest

なぜ問題になるのか?

latest は一見便利に見えますが、
本番運用では最も危険なタグのひとつです。

  • いつ Node.js のバージョンが変わるか分からない
  • ある日突然、ビルドが失敗する
  • 依存ライブラリの互換性が壊れる
  • 本番と検証環境で再現できなくなる

つまり、再現性が完全に失われます


実務で起きがちな事故

  • 昨日まで動いていた CI が突然失敗
  • 緊急リリース時に原因が分からない
  • 「Dockerfile は変えていないのに壊れた」

👉 原因は latest だった、というケースは非常に多いです。


✅ 改善例

FROM node:20.11-alpine
  • バージョンを固定する
  • 更新は「意図的な作業」として行う

ハンズオン

docker build -t app:latest .
docker build -t app:fixed .

数か月後、同じ Dockerfile を再ビルドすると
結果が変わる可能性があるのは latest の方です。


アンチパターン②:root ユーザーで本番実行する

❌ 悪い例

FROM node:20
WORKDIR /app
COPY . .
CMD ["node", "index.js"]

なぜ危険なのか?

Docker コンテナは仮想マシンではありません。
root 権限で動いているコンテナに侵入されると、

  • ファイル改ざん
  • 不正コマンド実行
  • 他コンテナへの横展開

といった被害につながる可能性があります。


ハンズオン(確認)

docker run -it image-name sh
whoami
root

👉 侵入=即 root 権限取得


✅ 改善例

FROM node:20-alpine
WORKDIR /app
COPY . .
USER node
CMD ["node", "index.js"]
whoami
node

非 root 実行にするだけで、
被害範囲をコンテナ内部に限定できます。


アンチパターン③:不要なツールを本番に入れる

❌ 悪い例

RUN apt update && apt install -y \
  vim \
  curl \
  git \
  net-tools

なぜやってしまうのか?

  • デバッグ用に入れたまま忘れる
  • 開発環境と本番を分けていない

なぜ危険か?

  • 攻撃者が使えるツールが増える
  • 脆弱性を含む可能性が高まる
  • イメージサイズが無駄に大きくなる

✅ 改善例

  • 開発用と本番用 Dockerfile を分ける
  • マルチステージビルドを使う
FROM node:20 AS build
RUN npm install

FROM node:20-alpine
COPY --from=build /app/dist ./dist

アンチパターン④:.env や secrets を COPY する

❌ 悪い例

COPY . .

.env が含まれていると、
その時点で情報漏洩が確定します。


ハンズオン(確認)

docker inspect image-name
  • APIキー
  • DBパスワード

が平文で見えることもあります。


✅ 改善例

.dockerignore

.env
.git
node_modules

実行時に注入:

docker run -e API_KEY=xxxxx app

アンチパターン⑤:単一ステージ Dockerfile を本番で使う

❌ 悪い例

FROM node:20
COPY . .
RUN npm install && npm run build
CMD ["node", "dist/index.js"]

問題点

  • ビルドツールが残る
  • 開発用ファイルが混入
  • 攻撃対象領域が広がる

✅ 改善例(マルチステージ)

FROM node:20 AS build
WORKDIR /app
COPY . .
RUN npm install && npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/index.js"]

アンチパターン⑥:COPY の順序を考えない

❌ 悪い例

COPY . .
RUN npm install

なぜ問題か?

  • ちょっとした変更でキャッシュ無効
  • CI ビルドが遅くなる
  • 無駄な再インストール

✅ 改善例

COPY package.json package-lock.json ./
RUN npm install
COPY . .

👉 ビルド時間短縮 = 開発体験向上


アンチパターン⑦:ログをファイルに出力する

❌ 悪い例

fs.appendFileSync("app.log", "log");

なぜ本番で困るのか?

  • コンテナ再起動でログ消失
  • Kubernetes で取得しづらい
  • 集約・監視が難しい

✅ 改善例

console.log("application started");
  • stdout / stderr に出力
  • Docker / Kubernetes と相性が良い

アンチパターン⑧:開発用設定を本番に流用する

よくある例

  • debug モード ON
  • hot reload 有効
  • テストコード混入

改善策

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
  • 本番・開発を明確に分離
  • 意図しない設定混入を防ぐ

本番向け Dockerfile チェックリスト

  • latest を使っていない
  • 非 root ユーザーで実行
  • secrets を含めていない
  • マルチステージを使用
  • .dockerignore を設定
  • ログは stdout

まとめ

Dockerfile のアンチパターンは、

  • 「知らなかった」より
  • 「後回しにした」ことで起きる

ケースがほとんどです。

Dockerfile は
早い段階で正しく設計すれば、後から楽になる技術でもあります。

「動く Dockerfile」から
「本番で安心して使える Dockerfile」へ

このアンチパターン集が、その一歩になれば幸いです。


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です