Docker & Kubernetes完全攻略 第4編:Docker Composeでマルチコンテナ管理
Docker & Kubernetes Complete Guide Part 4: Multi-Container Management with Docker Compose
序論:Docker Composeの必要性
実際のアプリケーションはほとんどが複数のサービスで構成されています。Webサーバー、データベース、キャッシュ、メッセージキューなど、様々なコンポーネントが連携して動作する必要があります。このようなマルチコンテナ環境を個別のdocker runコマンドで管理するのは手間がかかり、エラーが発生しやすくなります。
Docker Composeはこの問題を解決するツールで、1つのYAMLファイルで複数のコンテナを定義し、1回のコマンドでアプリケーションスタック全体を管理できるようにしてくれます。
1. Docker Composeとは?
1.1 Docker Composeの定義
Docker Composeはマルチコンテナ Dockerアプリケーションを定義し実行するためのツールです。docker-compose.ymlファイルにアプリケーションのサービス、ネットワーク、ボリュームを宣言的に定義します。
Docker Composeの主な特徴:
- 宣言的定義:YAMLファイルでアプリケーションスタック全体を定義
- 単一コマンド管理:
docker compose upですべてのサービスを開始 - 環境分離:プロジェクトごとに独立したネットワークを作成
- 変数サポート:環境変数と
.envファイルで柔軟な設定 - 開発の利便性:ローカル開発環境の構築に特に便利
1.2 Docker Compose V2
Docker Desktopと最新のDocker EngineにはCompose V2がデフォルトで含まれています。V2はGoで書き直され、docker compose(ハイフンなし)の形式で使用します。
# V1(レガシー)
docker-compose up
# V2(推奨)
docker compose up
2. docker-compose.ymlの構造
2.1 基本構造
# docker-compose.yml
version: "3.9" # Composeファイルバージョン(オプション)
services: # サービス(コンテナ)定義
web:
image: nginx:alpine
ports:
- "80:80"
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
volumes: # ボリューム定義(オプション)
db-data:
networks: # ネットワーク定義(オプション)
backend:
2.2 最小構成の例
# 最もシンプルなdocker-compose.yml
services:
web:
image: nginx:alpine
ports:
- "8080:80"
3. サービス定義の詳細
3.1 image - イメージの指定
services:
web:
# Docker Hubイメージ
image: nginx:alpine
db:
# レジストリイメージ
image: registry.example.com/mydb:1.0
app:
# 特定のダイジェスト
image: myapp@sha256:abc123...
3.2 build - イメージのビルド
services:
app:
# シンプルなビルド
build: .
api:
# 詳細なビルドオプション
build:
context: ./api
dockerfile: Dockerfile.prod
args:
VERSION: "2.0"
BUILD_ENV: production
target: production # マルチステージビルドのターゲット
frontend:
# ビルド後にイメージタグを指定
build: ./frontend
image: myapp/frontend:latest
3.3 ports - ポートマッピング
services:
web:
image: nginx
ports:
# ホスト:コンテナ
- "80:80"
- "443:443"
# ホストポート自動割り当て
- "80"
# 特定IPのみにバインド
- "127.0.0.1:3000:3000"
# UDPポート
- "53:53/udp"
# 長い形式
- target: 80
published: 8080
protocol: tcp
mode: host
3.4 volumes - ボリュームマウント
services:
db:
image: postgres:15
volumes:
# 名前付きボリューム(Named Volume)
- db-data:/var/lib/postgresql/data
# バインドマウント(ホストパス)
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
# 読み取り専用マウント
- ./config:/etc/app/config:ro
# 長い形式
- type: volume
source: db-data
target: /var/lib/postgresql/data
volume:
nocopy: true
volumes:
db-data: # ボリューム宣言
cache-data:
driver: local
3.5 environment - 環境変数
services:
app:
image: myapp
environment:
# Map形式
NODE_ENV: production
DEBUG: "false"
DATABASE_URL: postgres://user:pass@db:5432/mydb
db:
image: postgres
environment:
# Array形式
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=myapp
worker:
image: myworker
# ファイルから環境変数を読み込み
env_file:
- .env
- .env.local
3.6 commandとentrypoint
services:
app:
image: node:20
# デフォルトコマンドを上書き
command: npm run dev
worker:
image: python:3.11
# 配列形式
command: ["python", "-m", "celery", "worker"]
custom:
image: alpine
# エントリーポイントを上書き
entrypoint: /custom-entrypoint.sh
command: ["--config", "/etc/app/config.yml"]
4. 依存関係管理(depends_on)
4.1 基本的な依存関係
services:
web:
image: nginx
depends_on:
- api
- db
api:
image: myapi
depends_on:
- db
- redis
db:
image: postgres:15
redis:
image: redis:alpine
4.2 条件付き依存関係(service_healthy)
services:
web:
image: nginx
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
redis:
image: redis:alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
重要:depends_onは起動順序のみを保証し、サービスが「準備完了」状態であることは保証しません。本番環境ではhealthcheckと一緒にcondition: service_healthyを使用してください。
5. ネットワーク設定
5.1 デフォルトのネットワーク動作
Docker Composeはプロジェクトに対してデフォルトのネットワークを自動的に作成します。同じネットワークのサービスはサービス名で互いに通信できます。
services:
web:
image: nginx
# dbサービスに"db"ホスト名でアクセス可能
db:
image: postgres
# webサービスに"web"ホスト名でアクセス可能
5.2 カスタムネットワーク
services:
frontend:
image: nginx
networks:
- frontend-net
api:
image: myapi
networks:
- frontend-net
- backend-net
db:
image: postgres
networks:
- backend-net
networks:
frontend-net:
driver: bridge
backend-net:
driver: bridge
internal: true # 外部アクセス遮断
5.3 ネットワークエイリアスと固定IP
services:
db:
image: postgres
networks:
backend:
aliases:
- database
- postgres-primary
ipv4_address: 172.28.0.10
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
6. 実践例:WordPress + MySQL
# wordpress/docker-compose.yml
services:
wordpress:
image: wordpress:latest
restart: unless-stopped
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress_password
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress-data:/var/www/html
depends_on:
db:
condition: service_healthy
networks:
- wordpress-net
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress_password
MYSQL_ROOT_PASSWORD: root_password
volumes:
- db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- wordpress-net
volumes:
wordpress-data:
db-data:
networks:
wordpress-net:
driver: bridge
7. 実践例:Node.js + MongoDB + Redis
# nodejs-stack/docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
ports:
- "3000:3000"
environment:
NODE_ENV: development
MONGODB_URI: mongodb://mongo:27017/myapp
REDIS_URL: redis://redis:6379
volumes:
- .:/app
- /app/node_modules
depends_on:
mongo:
condition: service_healthy
redis:
condition: service_healthy
networks:
- app-net
command: npm run dev
mongo:
image: mongo:7
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: secret
MONGO_INITDB_DATABASE: myapp
volumes:
- mongo-data:/data/db
- ./mongo-init.js:/docker-entrypoint-initdb.d/init.js:ro
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- app-net
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
networks:
- app-net
mongo-express:
image: mongo-express
restart: unless-stopped
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: admin
ME_CONFIG_MONGODB_ADMINPASSWORD: secret
ME_CONFIG_MONGODB_URL: mongodb://admin:secret@mongo:27017/
ME_CONFIG_BASICAUTH: "false"
depends_on:
- mongo
networks:
- app-net
volumes:
mongo-data:
redis-data:
networks:
app-net:
driver: bridge
8. Docker Composeコマンド
8.1 基本コマンド
# サービス起動(バックグラウンド)
docker compose up -d
# サービス起動(フォアグラウンド、ログ出力)
docker compose up
# イメージビルド後に起動
docker compose up --build
# 特定のサービスのみ起動
docker compose up -d web db
# サービス停止と削除
docker compose down
# ボリュームも一緒に削除
docker compose down -v
# イメージも一緒に削除
docker compose down --rmi all
8.2 状態確認コマンド
# 実行中のサービス一覧
docker compose ps
# すべてのサービス(停止中も含む)
docker compose ps -a
# サービスログ確認
docker compose logs
# 特定のサービスのログ
docker compose logs web
# リアルタイムでログを追跡
docker compose logs -f
# 最新100行のみ
docker compose logs --tail=100
# タイムスタンプを含む
docker compose logs -t
8.3 サービス管理コマンド
# サービス再起動
docker compose restart
docker compose restart web
# サービス停止(コンテナは維持)
docker compose stop
# 停止したサービスを起動
docker compose start
# サービスのスケーリング
docker compose up -d --scale web=3
# 設定変更を適用
docker compose up -d --force-recreate
8.4 コンテナ内でコマンド実行(exec)
# コンテナでコマンド実行
docker compose exec web sh
docker compose exec db psql -U postgres
# 特定のユーザーで実行
docker compose exec --user root web sh
# 環境変数を設定
docker compose exec -e DEBUG=true app npm test
# 新しいコンテナで実行(run)
docker compose run --rm app npm test
docker compose run --rm db psql -U postgres
9. 環境別設定の分離
9.1 .envファイルの使用
# .envファイル
POSTGRES_USER=admin
POSTGRES_PASSWORD=secret123
APP_PORT=3000
NODE_ENV=development
# docker-compose.yml
services:
app:
ports:
- "${APP_PORT}:3000"
environment:
NODE_ENV: ${NODE_ENV}
db:
image: postgres:15
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
9.2 複数のComposeファイルの使用
# docker-compose.yml(基本設定)
services:
app:
build: .
environment:
NODE_ENV: production
db:
image: postgres:15
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
# docker-compose.override.yml(開発環境、自動適用)
services:
app:
build:
context: .
target: development
volumes:
- .:/app
environment:
NODE_ENV: development
ports:
- "3000:3000"
db:
ports:
- "5432:5432"
# docker-compose.prod.yml(本番環境)
services:
app:
restart: always
deploy:
replicas: 3
environment:
NODE_ENV: production
db:
restart: always
# 開発環境(基本 + overrideが自動マージ)
docker compose up
# 本番環境
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 複数ファイルを明示的に指定
docker compose -f docker-compose.yml -f docker-compose.override.yml up
9.3 プロファイルの使用(オプショナルサービス)
services:
app:
image: myapp
db:
image: postgres:15
# 開発環境でのみ使用
adminer:
image: adminer
profiles:
- debug
ports:
- "8080:8080"
# テスト環境でのみ使用
test-runner:
image: myapp-test
profiles:
- test
# 基本サービスのみ起動
docker compose up
# debugプロファイルを含む
docker compose --profile debug up
# 複数のプロファイル
docker compose --profile debug --profile test up
10. 便利な設定オプション
10.1 restartポリシー
services:
app:
image: myapp
restart: "no" # 再起動しない(デフォルト)
# restart: always # 常に再起動
# restart: on-failure # 失敗時のみ再起動
# restart: unless-stopped # 手動停止するまで再起動
10.2 リソース制限
services:
app:
image: myapp
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
cpus: "0.25"
memory: 256M
10.3 ロギング設定
services:
app:
image: myapp
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
まとめ
Docker Composeはマルチコンテナアプリケーション管理のための必須ツールです。この記事で扱った内容をまとめると:
- docker-compose.ymlの構造:services、volumes、networksの役割と定義方法
- サービス定義:image、build、ports、volumes、environmentなどの主要設定
- 依存関係管理:depends_onとhealthcheckを活用した安定した起動順序
- ネットワーク:サービス間通信とネットワーク分離
- 実践例:WordPress、Node.jsスタックなどの実際の使用例
- コマンド:up、down、ps、logs、execなどの主要コマンド
- 環境別設定:.envファイル、overrideファイル、プロファイルの活用
次回はDockerネットワークとボリュームについて詳しく解説し、コンテナ間の通信とデータの永続化について学びます。