Docker

Dockerfile

Docker

ベストプラクティスとマルチステージビルド

Dockerfileの命令

FROM、RUN、COPY、CMD、ENTRYPOINT など

Dockerfile dockerfile
# ベースイメージ
FROM node:20-alpine

# メタデータ
LABEL maintainer="you@example.com" version="1.0"

# 環境変数
ENV NODE_ENV=production \
    PORT=3000

# 作業ディレクトリ
WORKDIR /app

# ファイルコピー(.dockerignore が適用される)
COPY package*.json ./

# コマンド実行(レイヤーをキャッシュ活用)
RUN npm ci --only=production

# アプリコードをコピー(依存関係の後)
COPY . .

# ポート公開(ドキュメント目的、実際はrunで指定)
EXPOSE 3000

# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD wget -qO- http://localhost:3000/health || exit 1

# 実行ユーザー(rootを避ける)
USER node

# コンテナ起動コマンド
CMD ["node", "server.js"]
# ENTRYPOINT と CMD の違い:
# ENTRYPOINT: 固定コマンド(上書き不可)
# CMD: デフォルト引数(docker run で上書き可)

マルチステージビルド

ビルドと実行イメージを分離してサイズ削減

Dockerfile.prod dockerfile
# ===== ステージ1: ビルド =====
FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# ===== ステージ2: 本番 =====
FROM node:20-alpine AS production

# セキュリティアップデート
RUN apk update && apk upgrade && apk add --no-cache dumb-init

WORKDIR /app

# ビルド成果物だけをコピー
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

USER node
EXPOSE 3000

# dumb-init: シグナル処理を正しく行う
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]

# ===== ステージ3: テスト(オプション)=====
FROM builder AS test
RUN npm test

ベストプラクティスと .dockerignore

レイヤーキャッシュの最適化とセキュリティ

.dockerignore

.dockerignore bash
# バージョン管理
.git
.gitignore

# 依存関係(コンテナ内でインストール)
node_modules
npm-debug.log
yarn-error.log

# ビルド成果物
dist
build
.next

# 環境設定(機密情報を含む)
.env
.env.local
.env.*.local

# ドキュメント
README.md
docs

# テスト
coverage
__tests__
*.test.ts

# IDE
.vscode
.idea
*.swp

レイヤーキャッシュの最適化

Dockerfile.optimized dockerfile
FROM node:20-alpine
WORKDIR /app

# ✅ 変更頻度の低いものを先に
# package.json だけコピー → npm install → その後ソースコード
# → package.json が変わらなければ npm install はキャッシュ利用
COPY package*.json ./
RUN npm ci --only=production

# ✅ ここでソースをコピー(npm install と分離)
COPY . .

# ✅ RUN は可能な限り連結してレイヤー数を減らす
RUN apt-get update && apt-get install -y \
    curl \
    jq \
  && rm -rf /var/lib/apt/lists/*  # キャッシュ削除を同じレイヤーで

# ❌ これは3レイヤー生まれて無駄
# RUN apt-get update
# RUN apt-get install -y curl
# RUN rm -rf /var/lib/apt/lists/*