「Docker Composeを立ち上げて、コーヒーを淹れて戻ってきてもまだ終わっていない」。そんな惨状に絶望したことはないか?
半年ほど前、俺はまさにその地獄にいた。本番環境の巨大なイメージをそのまま開発環境に流用するという「思考停止」の代償は高く、ビルドに10分かかるのが日常茶飯事。チームメンバーからは「お前の環境だけ時間が歪んでるのか?」と冷ややかな視線を浴びた。だが、結局のところ、遅いのは環境のせいではなく、俺の設計が甘かっただけだ。
泥臭い試行錯誤の末にたどり着いた、開発環境を「爆速」にするための最適化術を共有する。
1. マルチステージビルド:依存関係の「レイヤー」をハックする
「とりあえず動く」だけのDockerfileは、開発者の時間を食いつぶす癌だ。特に`npm install`を適当に書くと、コードを1行変えるたびに全依存関係が再インストールされる。
ここで重要なのは、`package-lock.json`(または`yarn.lock`)をソースコードより先にコピーすることだ。これにより、依存関係に変更がない限り、重いインストール処理はキャッシュされる。
# Dockerfile
FROM node:18-alpine AS base
WORKDIR /app
# ここでロックファイルだけ先にコピーする
COPY package*.json ./
# 開発用ステージ:ここが肝
FROM base AS development
RUN npm install
# ソースコードは後からコピー
COPY . .
CMD ["npm", "run", "dev"]
# 本番用ステージ
FROM base AS production
RUN npm install --production
COPY . .
RUN npm run build
CMD ["npm", "start"]
この構成なら、`src/`の中身を変えても`npm install`のレイヤーは再利用される。ビルド時間が数分から数秒に短縮される瞬間、脳内で何かが弾けるはずだ。
2. ファイル同期の「見えない壁」を突破する
MacでDockerを使っていると、ファイル同期のオーバーヘッドに殺される。特にNode.jsのホットリロードは、`chokidar`等のライブラリがファイルシステムを監視するが、Dockerの`bind mount`越しだと`inotify`イベントが遅延し、更新が検知されないという「詰み」が発生する。
#### Docker Desktopの設定を疑え
まず、設定の「Resources > File sharing」を見直せ。最新のMacならVirtioFS一択だ。従来のgRPC FUSEは大規模プロジェクトでは致命的に遅い。VirtioFSに切り替えるだけで、ファイル同期のレスポンスが劇的に改善する。
#### .dockerignore は「聖域」にせよ
同期対象から外すべきは`node_modules`だけじゃない。IDEの設定ファイルやキャッシュも泥棒だ。
# .dockerignore
node_modules
dist
.git
.env
*.log
.vscode/
.idea/
.cache/
coverage/
これを怠ると、IDEがバックグラウンドで吐き出す一時ファイルをDockerが必死に監視し続け、CPU使用率が100%に張り付く。PCが離陸しそうなファン音を立てているなら、まずはここを確認しろ。
3. DBのI/Oボトルネックを「Named Volume」で消し去る
コンテナを`down`するたびにDBが初期化される?そんな苦行は即刻やめろ。かといって、ホストOSのフォルダを直接マウントするのは、特にMacやWindowsではI/Oレイテンシが跳ね上がる原因になる。
Named Volumeを使え。これはDockerエンジンが直接管理する領域であり、ホストOSのファイルシステムを介さないため、圧倒的に高速だ。
# docker-compose.yml
services:
db:
image: postgres:15-alpine
volumes:
- db-data:/var/lib/postgresql/data # ホストパスではなく名前を指定
volumes:
db-data: # これだけでDockerが最適化された領域を確保してくれる
大規模なテストスイートを回す際、この変更だけでテスト実行時間が半分になった。I/O待ちでCPUが暇をしているような環境は、エンジニアの恥だと思え。
4. 計測こそが最適化の第一歩
「なんとなく速くなった気がする」で終わらせるな。エンジニアなら数字で語れ。
#### ビルド時間を計測する
# timeコマンドでビルド時間を計測
time docker compose build --no-cache
#### 不要なゴミを掃除する
環境が重いと感じたら、まずは不要なキャッシュを捨てろ。
# 停止中のコンテナ、未使用のネットワーク、キャッシュを全削除
docker system prune -a --volumes
結び:環境は「投資」だ
最適化をサボることは、自分の寿命を削ってPCのファンを回しているのと同じだ。今回紹介した手法は、特別なツールを入れる必要すらない。DockerfileとComposeファイルの書き方を変えるだけで、明日からの開発体験は劇的に変わる。
エンジニアの時間は、環境構築の待ち時間に費やすにはあまりにも高価だ。さあ、今すぐコンテナを再構築して、浮いた時間で美味いコーヒーでも淹れてこい。