Use Cases (更新: 2026/6/1)

Claude Code Docker Compose実践ガイド: Postgres/Redis/worker付きローカル開発環境

Claude CodeでDocker Composeを使い、Postgres/Redis/worker付きローカル開発環境を安全に作る実践ガイド。

Claude Code Docker Compose実践ガイド: Postgres/Redis/worker付きローカル開発環境

Docker Compose は、アプリ、データベース、Redis、バックグラウンド worker をまとめて起動するための「ローカル開発の設計図」です。公式ドキュメントでも、Compose は複数コンテナのアプリケーションを定義して実行し、サービス、ネットワーク、ボリュームを1つの YAML で管理する道具として説明されています。まず全体像は Docker Compose 公式ドキュメント を確認しておくと安全です。

Claude Code と相性がよいのは、Compose が「ファイルで説明できる環境」だからです。口頭で「Postgres と Redis も立てて」と頼むより、compose.yamlDockerfile.env.exampleMakefile を置き、Claude Code にレビューさせるほうが再現性が出ます。

Masa が小さな Next.js + queue worker の検証環境で試したときも、差が出たのは魔法のプロンプトではありませんでした。DB の起動待ち、Redis の永続化、node_modules の扱い、CI で使う一回実行コマンドを先に決めたことが効きました。

この記事では、初心者でもそのまま試せる形で、app + PostgreSQL + Redis + worker の Docker Compose 構成を作ります。Compose はローカル開発、検証、テストには非常に強い一方、本番運用ではオーケストレーション、シークレット、監視、バックアップ、費用のレビューが別途必要です。ここを混ぜないことが、失敗を減らす最初の線引きです。

全体像

今回の構成は次の通りです。

flowchart LR
  Dev["Developer"] --> App["app: web server"]
  App --> Pg["postgres: database"]
  App --> Redis["redis: cache and queue"]
  Worker["worker: background jobs"] --> Pg
  Worker --> Redis
  App --> Volume["named volume: node_modules"]
  Pg --> PgVol["named volume: postgres_data"]
  Redis --> RedisVol["named volume: redis_data"]

app はブラウザからアクセスする Web アプリ、worker はメール送信やキュー処理を担当する常駐プロセスです。postgresredis には healthcheck を付けます。healthcheck は「コンテナが起動した」ではなく「接続できる状態になった」を見るための確認です。

サービス定義の細かい仕様は Compose file referenceservices reference が一次情報です。Claude Code に修正を頼むときも、この2つを前提にレビューさせると、古い docker-compose 時代の書き方に引っ張られにくくなります。

使いどころの比較

使いどころCompose が向いている理由注意点
ローカル開発app、DB、Redis、worker を1コマンドで再現できるbind mount の速度差や OS 差を確認する
E2E/統合テストテスト用 DB と Redis を短時間で立てられるCI ではポート衝突とキャッシュを明示する
新メンバーのオンボーディング.env.examplemake setup で手順を固定できる秘密情報を .env.example に入れない
本番運用小規模な社内ツールでは候補になる場合もある監視、復旧、スケール、権限、コストのレビューが必須

特に本番境界は重要です。Compose は「開発者の手元に同じ足場を作る」には強いですが、クラウド本番では ECS、Kubernetes、Cloud Run、Fly.io、Render などの運用単位と比較します。Claude Code にも「Compose を本番に持ち込む前提でなく、移行先の制約を列挙して」と頼むのが安全です。

コピペ用 compose.yaml

次の例は Node.js/Next.js 系のプロジェクトを想定しています。npm run devnpm run worker:devnpm run db:migrate などは、あなたの package.json に合わせて置き換えてください。

# compose.yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev
    command: npm run dev -- --hostname 0.0.0.0
    ports:
      - "3000:3000"
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
      REDIS_URL: redis://redis:6379
    volumes:
      - .:/workspace
      - node_modules:/workspace/node_modules
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 20s

  worker:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev
    command: npm run worker:dev
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
      REDIS_URL: redis://redis:6379
    volumes:
      - .:/workspace
      - node_modules:/workspace/node_modules
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  postgres:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    env_file:
      - .env
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./docker/postgres/init:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  node_modules:
  postgres_data:
  redis_data:

ポイントは3つです。1つ目は postgresredis というサービス名をホスト名として使うことです。コンテナ内から localhost:5432 に接続すると、自分自身を見に行くため失敗します。2つ目は node_modules を named volume に逃がすことです。ソースは bind mount しつつ、コンテナ内の依存関係をホスト側の空ディレクトリで上書きしないためです。3つ目は pg_isready -U $$POSTGRES_USER のようにドル記号を2つ書くことです。これは Compose の変数展開ではなく、コンテナ内の環境変数として読むための書き方です。

Dockerfile

ローカル開発では target: dev を使い、本番用ビルドは別ステージに分けます。初学者ほど1つの Dockerfile にまとめたほうが管理しやすいです。

# Dockerfile
# syntax=docker/dockerfile:1

FROM node:22-alpine AS base
WORKDIR /workspace
ENV NEXT_TELEMETRY_DISABLED=1
COPY package*.json ./
RUN npm ci

FROM base AS dev
EXPOSE 3000
CMD ["npm", "run", "dev", "--", "--hostname", "0.0.0.0"]

FROM base AS build
COPY . .
RUN npm run build

FROM node:22-alpine AS production
WORKDIR /workspace
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /workspace/.next ./.next
COPY --from=build /workspace/public ./public
USER node
EXPOSE 3000
CMD ["npm", "start"]

dev ステージではソースコードをコピーしません。Compose の volume でホストのファイルを見せるためです。逆に build ステージでは COPY . . して、CI や本番イメージで再現できるビルドにします。

.env.example

.env はコミットしません。代わりに .env.example をコミットし、全員が同じ変数名で起動できるようにします。

# .env.example
POSTGRES_USER=app
POSTGRES_PASSWORD=app_password
POSTGRES_DB=app_development

DATABASE_URL=postgresql://app:app_password@postgres:5432/app_development?schema=public
REDIS_URL=redis://redis:6379
NODE_ENV=development
PORT=3000

Docker Compose の env_file はコンテナへ渡す環境変数です。一方、Compose ファイル内の変数展開はプロジェクト直下の .env も参照します。この違いで混乱しやすいので、.env.example の値と compose.yaml の値をずらさないことが大切です。

Makefile と一回実行コマンド

よく使うコマンドは Makefile にまとめます。Windows で make を使わないチームなら、同じ中身を package.json の scripts に移しても構いません。

COMPOSE = docker compose --env-file .env -f compose.yaml

.PHONY: setup up up-d down restart logs ps app-shell db-shell redis-cli migrate seed test lint clean

setup:
	cp .env.example .env
	$(COMPOSE) build

up:
	$(COMPOSE) up --build

up-d:
	$(COMPOSE) up -d --build

down:
	$(COMPOSE) down

restart:
	$(COMPOSE) restart app worker

logs:
	$(COMPOSE) logs -f app worker postgres redis

ps:
	$(COMPOSE) ps

app-shell:
	$(COMPOSE) exec app sh

db-shell:
	$(COMPOSE) exec postgres psql -U app -d app_development

redis-cli:
	$(COMPOSE) exec redis redis-cli

migrate:
	$(COMPOSE) run --rm app npm run db:migrate

seed:
	$(COMPOSE) run --rm app npm run db:seed

test:
	$(COMPOSE) run --rm app npm test

lint:
	$(COMPOSE) run --rm app npm run lint

clean:
	$(COMPOSE) down --volumes --remove-orphans

docker compose run --rm app npm run lint のような一回実行コマンドは、CI とローカルの差を小さくします。exec は起動済みコンテナに入る操作、run --rm は新しい一時コンテナでコマンドだけを実行する操作、と覚えると迷いません。

Claude Code にレビューさせるプロンプト

Claude Code common workflows では、コードベースの理解、テスト、リファクタリングなどの日常作業を小さな依頼に分ける考え方が紹介されています。Compose でも同じで、「作って」より「観点を指定してレビューして」のほうが成果が安定します。

このリポジトリの Docker Compose 構成をレビューしてください。

対象:
- compose.yaml
- Dockerfile
- .env.example
- package.json
- .github/workflows があれば CI 設定

観点:
1. app + postgres + redis + worker がローカルで再現できるか
2. healthcheck と depends_on の使い方が妥当か
3. named volume と bind mount の使い分けが安全か
4. .env.example に秘密情報が混ざっていないか
5. migrate、seed、test、lint の一回実行コマンドが足りているか
6. CI で失敗しそうなポート、キャッシュ、権限、起動待ちがないか
7. 本番運用に持ち込む前に別途レビューすべき項目は何か

制約:
- 既存のフレームワークと package manager に合わせる
- 大きなリファクタリングは提案に止める
- 修正する場合は理由と確認コマンドも書く

このプロンプトを CLAUDE.md に近い形で残すと、チームのレビュー基準になります。CLAUDE.md の整え方は Claude Code Dev ContainerガイドCI/CDセットアップガイド と合わせて読むと実務に落とし込みやすいです。

実用ユースケース

1つ目は、新メンバーの初日セットアップです。git clone.env.example のコピー、make up だけでアプリ、DB、Redis、worker が起動すれば、README の手順が短くなります。質問も「Postgres はどこで入れますか」ではなく「migration が失敗しています」に絞れます。

2つ目は、キュー処理のローカル検証です。メール送信、画像変換、課金 webhook 後の非同期処理は、Web アプリだけ起動しても確認できません。worker を Compose に入れておくと、Redis queue に積まれた job を手元で再現できます。

3つ目は、統合テストの安定化です。SQLite の代替テストでは通るのに Postgres で落ちる問題は珍しくありません。Compose で本番に近い DB を立て、docker compose run --rm app npm test を CI と同じ形に寄せると、型や SQL 方言の差に早く気づけます。

4つ目は、Claude Code によるインフラ差分レビューです。人間が YAML を眺めるだけでは、localhost 接続、.env 漏れ、volume の上書き、healthcheck 不足を見落としがちです。レビュー観点をテンプレート化して渡すと、毎回同じ粒度で確認できます。

よくある落とし穴

一番多い失敗は、アプリコンテナから localhost で DB に接続することです。Compose 内ではサービス名が DNS 名になります。postgres:5432redis:6379 と書きます。

次に多いのは、depends_on を「完全な起動保証」と誤解することです。condition: service_healthy は強力ですが、アプリ側にもリトライ処理が必要です。DB migration の直後に worker が先に走るような構成では、起動順だけでは解決しません。

named volume の消し忘れも危険です。スキーマを変えたのに古い postgres_data が残ると、「自分の環境だけ壊れる」状態になります。検証をやり直すときは make clean で volume も削除します。ただし、手元のデータは消えるので実行前に確認してください。

.env.example に本物の API キーを入れるのも避けます。サンプル値は app_passwordreplace_me にし、本番秘密情報は Docker secrets、クラウドの secret manager、CI の secret store で扱います。

最後に、Compose ファイルをそのまま本番設計書にしないことです。開発環境ではポートを公開して便利にしますが、本番では公開範囲、TLS、DB バックアップ、Redis persistence、監視、脆弱性スキャン、イメージ署名、権限境界、費用を見ます。ここは Claude Code に任せきりにせず、人間のレビューを入れるべき領域です。

ClaudeCodeLab の教材と相談

この構成を自分のリポジトリに合わせて固めるなら、まず ClaudeCodeLabの教材・テンプレートCLAUDE.md、レビュー用プロンプト、セットアップ手順の型を作ると早いです。チーム導入、Docker Desktop の設定差、CI/CD、権限境界、本番移行の判断まで一緒に設計したい場合は Claude Code研修・導入相談 を使ってください。

Compose の一次情報は Docker ComposeCompose file referenceservices reference にあります。Claude Code 側の作業分解は Common workflows が参考になります。

この記事で紹介した内容を実際に試した結果、Masa の検証環境では make up から app、Postgres、Redis、worker までまとめて起動でき、DB が準備できる前にアプリが落ちる問題も healthcheck とリトライで減りました。一方で、古い named volume が残ると migration の検証結果が変わることも確認しました。結論として、Compose はローカル開発の再現性を上げる強力な足場ですが、本番判断はセキュリティ、監視、復旧、費用を別枠でレビューするのが安全です。

#Claude Code #Docker #Docker Compose #ローカル開発 #PostgreSQL #Redis
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。