Dockerの「遅い」を撲滅する—開発現場で即効性のある5つの最適化術

Dockerの「遅い」を撲滅する—開発現場で即効性のある5つの最適化術

「Dockerは重い」「ビルドが終わるまでにコーヒーが冷める」。そんな愚痴をSNSで見るたび、画面の向こうで溜息が出る。はっきり言おう。遅いのはDockerのせいじゃない。お前たちの設定が雑なだけだ。

泥臭い現場で何年もコードを書いてきたが、非効率なDockerfileは「ここに時間を捨てています」と看板を掲げているようなもの。AIに最適解を求める前に、まずは自分の足元にある「ゴミ」を掃除するところから始めよう。


1. マルチステージビルドは「軽量化」のためだけのものじゃない

「ビルドが遅い」と嘆く奴に限って、`COPY . .` を適当にやっている。ビルドコンテキストを全部放り込み、コードの数行の変更で全レイヤーを再構築するなんて、時間の浪費もいいところだ。

マルチステージビルドは、単にイメージを軽くする魔法じゃない。「ビルド環境」と「実行環境」を物理的に断絶させるための防壁だ。

# ビルドステージ:キャッシュを最大限活かす構成
FROM node:18-alpine AS builder
WORKDIR /app

# package.jsonだけ先にコピーして依存関係をキャッシュ
COPY package*.json package-lock.json ./
RUN npm ci 

# ソースコードをコピーしてビルド
COPY . .
RUN npm run build

# ランタイムステージ:実行に必要な最小限のファイルだけを抽出
FROM node:18-alpine
WORKDIR /app
# ビルダーから成果物のみを抽出(node_modulesの不要なビルドツールは排除)
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 3000
CMD ["node", "dist/index.js"]

依存関係の解決とビルド生成物を分けるだけで、CIの待ち時間は劇的に変わる。本番環境で「なぜか動かない」という悲劇の9割は、このステージ分離をサボった結果だ。


2. ホットリロードの「罠」:諸刃の剣を使いこなせ

Docker Composeでホットリロードが効かないと騒ぐエンジニアも多い。大抵はボリュームマウントの設定ミスか、OSのファイル監視イベントがコンテナまで届いていないことが原因だ。

macOSなら `delegated` オプションを忘れずにつけろ。そして、どうしてもイベントが拾えない時の最終手段がこれだ。

services:
  web:
    build: .
    volumes:
      - .:/app:delegated
    environment:
      # ファイル監視にポーリングを使用する
      - CHOKIDAR_USEPOLLING=true

ただし、警告しておく。 `CHOKIDAR_USEPOLLING=true` はCPUリソースを食いつぶす「諸刃の剣」だ。コンテナ内の全ファイルを定期的にスキャンするため、大規模なプロジェクトで有効にすると、逆にPCが悲鳴を上げる。まずは `watchOptions` で特定のディレクトリだけ監視対象にするなど、適材適所で使うのがシニアの流儀だ。


3. 「とりあえず動く」で作った環境が、お前の首を絞める

かつて俺も、`Dockerfile` で `apt-get update && apt-get install -y ...` を連発し、イメージサイズを1GB近くまで肥大化させた痛い過去がある。

当時の俺は、CI環境でのプルに毎回3分かかり、開発のモチベーションが完全に死んでいた。「とりあえず動く」で作った環境は、後から必ず負債となって返ってくる。

  • パッケージ管理の鉄則: `--no-install-recommends` を必ず付ける。
  • レイヤーの削減: `RUN` コマンドは `&&` で繋ぎ、不要なキャッシュをその場で削除する。
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    git \
    && rm -rf /var/lib/apt/lists/* # キャッシュを消してイメージをスリム化

この一行があるかないかで、数ヶ月後の自分に感謝されるか、呪われるかが決まる。


4. リソース配分は「エンジンのチューニング」だ

「Dockerが重い」の正体は、CPUとメモリのリソース配分不足であることが多い。Docker DesktopのGUI設定をいじっている奴も多いが、設定が反映されない場合は `.wslconfig` を直接叩くのが確実だ。

# C:\Users\<ユーザー名>\.wslconfig
[wsl2]
memory=8GB   # 物理メモリの半分程度を目安に
processors=4 # コア数を割り当てる
swap=0       # スワップを無効にして高速化

GUI設定とCLI設定が衝突した場合は、基本的にWSL2環境下ではこの `.wslconfig` が優先される。リソース制限を甘く見ているのは、エンジンを吹かさずにレースに出るようなものだ。自分のマシンのスペックを把握し、Dockerに適切な「燃料」を与えてやれ。


5. DXは「妥協」から生まれる

最後に一つ言っておく。Docker環境を完璧にしようと頑張りすぎるな。「本番と全く同じ環境をローカルに再現したい」という欲求は、エンジニアの悪い癖だ。

俺の経験上、開発環境は「本番に近いこと」よりも「再起動の速さ」と「コマンド一発でクリーンな状態に戻せること」の方が遥かに重要だ。

コンテナが汚れたら、迷わず以下のコマンドで全てを焼き払え。

docker-compose down -v --remove-orphans

スクラップ&ビルドを恐れるな。使い捨てできる環境こそが、最高の開発体験(DX)への近道だ。

お前たちが無駄な待ち時間に費やしているその数分間、どれだけのコードが書けるか考えたことがあるか? Dockerの最適化は、楽をするための「最高に贅沢な努力」だ。さっさと設定を見直して、本来書くべきコードに向き合え。