Docker Compose とは?
Docker Composeは、複数のDockerコンテナをまとめて定義・管理するためのツールです。docker-compose.yml(または compose.yml)というYAMLファイルに設定を書くだけで、Webサーバー・DB・キャッシュなどをワンコマンドで起動できます。
なぜ Docker Compose を使うのか?
| 課題 | Docker Compose の解決策 |
|---|---|
docker run のオプションが長くなる | YAMLファイルに設定をまとめる |
| 複数コンテナの起動順序が面倒 | depends_on で依存関係を定義 |
| 開発環境のセットアップが人によって違う | compose.yml で統一 |
| チームメンバーへの共有が大変 | ファイルをリポジトリにコミットするだけ |
インストール
Docker Desktop をインストールすると Docker Compose も含まれています。
# バージョン確認
docker compose version
# Docker Compose version v2.24.0
# 旧コマンド(ハイフンあり)も動くがv2推奨
docker-compose version
v1 と v2 の違い
# v1(非推奨)
docker-compose up
# v2(推奨)
docker compose up
v2 は Docker CLI のプラグインとして動作し、パフォーマンスが向上しています。
基本的な compose.yml の書き方
最小構成
services:
web:
image: nginx:latest
ports:
- "8080:80"
# 起動
docker compose up
# バックグラウンドで起動
docker compose up -d
# 停止
docker compose down
よくある開発環境構成
services:
app:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
ports:
- "5432:5432"
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: myapp
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
db-data:
主要なキーワード解説
services
コンテナの定義を記述するトップレベルのキーです。
services:
サービス名:
# コンテナの設定
image vs build
services:
# 既存のイメージを使う場合
nginx:
image: nginx:latest
# Dockerfile からビルドする場合
app:
build: .
# ビルドオプションを細かく指定する場合
app-custom:
build:
context: .
dockerfile: Dockerfile.dev
args:
NODE_VERSION: 20
ports
services:
app:
ports:
# ホスト:コンテナ
- "3000:3000"
# ホストのポートをランダムに割り当て
- "3000"
# 特定のIPにバインド
- "127.0.0.1:3000:3000"
volumes
services:
app:
volumes:
# バインドマウント(ホストのディレクトリをマウント)
- ./src:/app/src
# 名前付きボリューム
- node-modules:/app/node_modules
# 読み取り専用
- ./config:/app/config:ro
volumes:
node-modules:
environment と env_file
services:
app:
# 直接指定
environment:
- NODE_ENV=development
- API_KEY=my-secret-key
# ファイルから読み込み
env_file:
- .env
- .env.local
depends_on
services:
app:
depends_on:
# 単純な起動順序
- db
- redis
app-v2:
depends_on:
# ヘルスチェックを条件にする(推奨)
db:
condition: service_healthy
redis:
condition: service_started
networks
services:
frontend:
networks:
- frontend-net
backend:
networks:
- frontend-net
- backend-net
db:
networks:
- backend-net
networks:
frontend-net:
backend-net:
よく使うコマンド一覧
| コマンド | 説明 |
|---|---|
docker compose up -d | バックグラウンドで起動 |
docker compose down | 停止してコンテナを削除 |
docker compose down -v | ボリュームも含めて削除 |
docker compose ps | 実行中のコンテナ一覧 |
docker compose logs -f | ログをリアルタイム表示 |
docker compose logs app | 特定サービスのログ |
docker compose exec app bash | コンテナ内でコマンド実行 |
docker compose build | イメージを再ビルド |
docker compose build --no-cache | キャッシュなしでビルド |
docker compose pull | イメージを最新に更新 |
docker compose restart | 再起動 |
docker compose stop | 停止(コンテナは残る) |
実践的な構成例
Node.js + PostgreSQL + Redis
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
DATABASE_URL: postgresql://dev:dev@db:5432/myapp
REDIS_URL: redis://redis:6379
depends_on:
db:
condition: service_healthy
command: npm run dev
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: myapp
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dev"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
adminer:
image: adminer
ports:
- "8080:8080"
depends_on:
- db
volumes:
pgdata:
Dockerfile.dev の例
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
ホットリロードを有効にする
開発環境ではソースコードの変更を即座に反映させたいものです。
services:
app:
volumes:
# ソースコードをマウント
- .:/app
# node_modules はコンテナ内のものを使う
- /app/node_modules
command: npm run dev
Docker Compose Watch(v2.22+)
services:
app:
build: .
develop:
watch:
# ソースコードの変更を同期
- action: sync
path: ./src
target: /app/src
# package.json が変わったらリビルド
- action: rebuild
path: ./package.json
docker compose watch
複数の Compose ファイルを使い分ける
# 開発用
docker compose -f compose.yml -f compose.dev.yml up
# テスト用
docker compose -f compose.yml -f compose.test.yml up
# 本番用
docker compose -f compose.yml -f compose.prod.yml up
compose.dev.yml(開発用オーバーライド)
services:
app:
volumes:
- .:/app
environment:
- DEBUG=true
command: npm run dev
compose.test.yml(テスト用オーバーライド)
services:
app:
environment:
- NODE_ENV=test
command: npm test
トラブルシューティング
ポートが競合する
# エラー: Bind for 0.0.0.0:5432 failed: port is already allocated
# 解決: ホスト側のポートを変更
ports:
- "5433:5432"
ボリュームのパーミッション問題
services:
app:
user: "${UID:-1000}:${GID:-1000}"
volumes:
- .:/app
コンテナが起動直後に終了する
# ログを確認
docker compose logs app
# コンテナ内でデバッグ
docker compose run app sh
ビルドキャッシュが効かない
# キャッシュなしで再ビルド
docker compose build --no-cache
# すべてをクリーンアップ
docker compose down -v --rmi all
ベストプラクティス
- compose.yml はリポジトリにコミットする — チーム全員が同じ環境を再現できる
- シークレットは .env ファイルに書く —
.envは.gitignoreに追加 - ヘルスチェックを設定する —
depends_onのcondition: service_healthyが使える - 名前付きボリュームを使う — データの永続化に必須
- 不要なイメージは Alpine 版を使う — イメージサイズが小さくなる
まとめ
Docker Compose を使えば、複雑な開発環境もYAMLファイル1つで管理できます。チーム全員が同じ環境を簡単に再現でき、「自分の環境では動く」問題から解放されます。
YAML ファイルのフォーマットが崩れた時は、AssistyのYAMLフォーマッターで整形できます。インデントの統一やバリデーションをブラウザ上で実行できます。