はじめに
Dockerfile を「Docker コンテナとして動かす」だけなら、
多くの場合はシンプルな構成でも問題ありません。
しかし Kubernetes(K8s)上で本番運用する Dockerfile には、
Docker 単体とはまったく異なる設計思想が求められます。
Kubernetes 環境では、
- コンテナは頻繁に再起動される
- Pod はいつでも破棄・再生成される
- スケールアウト・ローリングアップデートが前提
- 死活監視(Probe)が常に動いている
つまり、
「落ちてもすぐ復旧できる」「状態を持たない」コンテナ設計が必須です。
本記事では、
- Kubernetes 向け Dockerfile に必要な考え方
- Docker 単体用 Dockerfile との違い
- やりがちな失敗例
- Kubernetes を前提とした Dockerfile ハンズオン
- Deployment での動作確認ポイント
までを、実務視点で丁寧に解説します。
なぜ Kubernetes 向け Dockerfile 設計が重要なのか?
Kubernetes は コンテナを「管理・制御」する仕組みです。
そのため、Dockerfile 側の設計が Kubernetes の思想とズレていると、
- Pod が頻繁に CrashLoopBackOff になる
- ローリングアップデートが止まる
- readinessProbe に失敗し続ける
- ログが取れず障害調査できない
といった問題が発生します。
👉 Kubernetes は Dockerfile の「甘え」を許してくれない
これが現場でよく言われる理由です。
Kubernetes 向け Dockerfile 設計の基本原則
原則①:1コンテナ = 1プロセス
Kubernetes では、
1つのコンテナで1つの役割だけを持つのが基本です。
❌ nginx + app + cron を同一コンテナ
✅ アプリはアプリ、バッチは別コンテナ
原則②:コンテナは「いつでも死ぬ前提」
- 再起動される
- Pod が削除される
- ノードが落ちる
👉 状態をコンテナ内に保存しない
原則③:標準出力にログを出す
Kubernetes は stdout / stderr を前提にログを収集します。
console.log("server started");
原則④:起動・停止が明確であること
- 起動が遅すぎない
- SIGTERM を正しく受け取れる
- graceful shutdown ができる
Kubernetes で問題になりやすい Dockerfile 例
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
CMD ["npm", "start"]
一見問題なさそうだが…
- root 実行
- マルチステージなし
- SIGTERM ハンドリング不明
- readiness/liveness を意識していない
Docker 単体なら動くが、
Kubernetes ではトラブルの元になります。
Kubernetes 向け Dockerfile の改善設計
# ===== Build Stage =====
FROM node:20 AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build
# ===== Runtime Stage =====
FROM node:20-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]
Kubernetes 視点でのポイント
- マルチステージで軽量化
- 非 root ユーザー
- 実行に必要なものだけを残す
- 起動が速い
ハンズオン①:Kubernetes 向け Node.js アプリを作る
アプリ構成
k8s-app/
├─ Dockerfile
├─ package.json
├─ src/
│ └─ index.js
src/index.js(SIGTERM 対応)
const http = require("http");
const server = http.createServer((req, res) => {
res.end("Hello Kubernetes!");
});
server.listen(3000);
process.on("SIGTERM", () => {
console.log("SIGTERM received. shutting down...");
server.close(() => {
process.exit(0);
});
});
👉 Kubernetes が Pod を停止するときに SIGTERM を送る
ハンズオン②:Dockerfile(Kubernetes 対応)
FROM node:20 AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]
ハンズオン③:Docker イメージをビルド
docker build -t k8s-app:1.0 .
ハンズオン④:Kubernetes Deployment を作成
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-app
spec:
replicas: 2
selector:
matchLabels:
app: k8s-app
template:
metadata:
labels:
app: k8s-app
spec:
containers:
- name: app
image: k8s-app:1.0
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
ハンズオン⑤:Kubernetes にデプロイ
kubectl apply -f deployment.yaml
kubectl get pods
Pod が Running になれば成功です。
Kubernetes 向け Dockerfile で重要な設計ポイント
① 軽量イメージは必須
- 起動が速い
- スケールアウトが速い
- ノード負荷が低い
② コンテナ内で状態を持たない
- ファイル保存しない
- セッションは外部(Redis 等)
③ ENTRYPOINT / CMD はシンプルに
CMD ["node", "dist/index.js"]
Kubernetes 側で制御しやすくなる。
④ 停止処理を意識する
- SIGTERM 対応
- 処理中リクエストを落とさない
Kubernetes × Dockerfile よくある失敗
- 起動が遅く readinessProbe 失敗
- SIGTERM 無視で強制 kill
- 巨大イメージでスケールが遅い
- root 実行でセキュリティ指摘
👉 Dockerfile の設計段階でほぼ決まる
Kubernetes 向け Dockerfile チェックリスト
- マルチステージビルド
- 非 root ユーザー
- 軽量ベースイメージ
- stdout ログ出力
- SIGTERM 対応
- readiness / liveness を想定
まとめ
Kubernetes 向け Dockerfile 設計は、
- Docker 単体とは考え方が違う
- 「壊れやすさ」を前提にする
- 運用・自動化・復旧を意識する
ことが重要です。
コメントを残す