Contents
Docker Compose の基本と最新仕様
Docker Compose は 複数コンテナを 1 つの YAML ファイルで宣言的に管理 できるツールです。2026 年時点では CLI が Compose V2 に統合され、ファイル形式は Compose Specification(バージョン番号不要)を推奨しています。本セクションでは、最新仕様の全体像と従来との主な違いを整理し、実務で迷わないためのポイントを解説します。
Compose ファイルの基本構造
Compose ファイルはトップレベルに 4 つのキー を持ちます。以下はそれぞれの役割と最小構成例です(インデント・コメントは統一しています)。
|
1 2 3 4 5 6 7 8 9 10 11 |
# docker-compose.yml (バージョン省略が推奨) services: # コンテナ定義本体 app: image: node:20-alpine networks: # サービス間通信を司る論理ネットワーク default: volumes: # 永続化データ用のボリューム宣言 data: |
services:起動対象コンテナとその設定。networks:明示的に定義しなくてもdefaultが自動生成されますが、分離したい場合はここで名前を付けます。volumes:永続化領域を Docker が管理する named volume を宣言します。
ポイント:
version:フィールドは省略可能です。Docker はファイルを自動的に最新仕様として解釈し、非推奨構文の使用を防ぎます。
バージョン指定の変遷とベストプラクティス
| 時期 | 記述方法 | 主な特徴 |
|---|---|---|
| Compose V1(2020 以前) | version: "3.9" 必須 |
スキーマが固定、拡張性が低い |
| Compose V2(現在) | version: 省略可 |
プラグインで機能追加可能、CLI が統合 |
結論:新規プロジェクトは バージョン行を削除 した形で作成し、将来の互換性を確保してください。
Compose V2 と従来 v3.9 の比較
以下の表は、CLI の実装とファイル形式の違いをまとめたものです。表の前に簡単な説明文を入れています。
比較ポイント:主に「バージョン指定」「拡張性」「ネットワーク自動生成」の観点で差異があります。
| 項目 | Compose V2(CLI) | 従来 v3.9 形式 |
|---|---|---|
version フィールド |
任意・省略可 | 必須(非推奨) |
| プラグイン拡張 | docker compose plugin install <name> で追加可能 |
スキーマ固定 |
| デフォルトネットワーク | 自動作成 (bridge) が標準 |
明示的に default 必要 |
| シークレット管理 | BuildKit の --secret と組み合わせて利用可 |
Swarm 専用 secrets: キーのみ |
サービス構成パターン:シングル vs マルチ
プロジェクト規模や開発フェーズに応じて 単一サービス、または 複数サービス の構成を選択します。ここでは代表的な実装例と、依存関係・起動順序のベストプラクティスを示します。
最小構成のシングルサービス(Nginx)
単体コンテナで動作確認したい場合の最短例です。ports によるポートマッピングだけで完結します。
|
1 2 3 4 5 6 |
services: web: image: nginx:stable-alpine ports: - "8080:80" # ホスト 8080 → コンテナ 80 |
ポイント:この形はローカル開発やデモ環境での「すぐに起動」向けです。
Node.js + MySQL の典型スタック
アプリと DB を別サービスとして定義し、depends_on と healthcheck で安全な起動順序を実現します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
services: api: build: ./api # Dockerfile が存在するディレクトリ environment: - DB_HOST=mysql - DB_USER=${MYSQL_USER} - DB_PASSWORD=${MYSQL_PASSWORD} depends_on: mysql: condition: service_healthy ports: - "3000:3000" mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: appdb MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} volumes: - db_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 3 volumes: db_data: |
ポイント:
healthcheckが成功するまでapiは待機し、接続失敗を防げます。
Flask + Redis のバックエンド API パターン
環境変数は .env に外部化し、env_file で一括読み込みします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
services: web: build: ./flask_app env_file: ./.env ports: - "5000:5000" depends_on: redis: condition: service_started redis: image: redis:7-alpine volumes: - redis_data:/data command: ["redis-server", "--appendonly", "yes"] volumes: redis_data: |
ポイント:
env_fileに書かれた変数はコンテナ内部で自動的に展開されます。
Nginx リバースプロキシ+複数コンテナ構成
フロントエンド・バックエンドを統合し、外部ネットワーク public を経由してホストと通信させる例です。external: true の意味は公式ドキュメント(Docker Engine reference – network create)で確認できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
services: nginx: image: nginx:stable-alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - frontend - backend frontend: build: ./frontend networks: - internal backend: build: ./backend networks: - internal networks: internal: driver: bridge # プライベート通信専用 public: external: true # Docker Desktop のデフォルトブリッジ (bridge) を再利用 |
ポイント:
publicは既存のブリッジネットワークを共有するため、外部 API やホスト側ツールとの連携が容易です。
ビルド・イメージ管理・環境変数・ボリューム活用法
実務では ビルド方式の選択 と 機密情報の安全な取り扱い が鍵になります。この章でそれぞれのベストプラクティスを具体例と共に示します。
build と image の使い分け
| 用途 | 設定例 |
|---|---|
| ソースからイメージ生成(開発・CI) | build: に context と dockerfile を指定 |
| 既製イメージの利用(本番) | image: にレジストリタグを記述 |
|
1 2 3 4 5 6 7 8 9 10 |
services: custom-app: build: context: ./app dockerfile: Dockerfile.prod # ビルド時に自動生成されるタグは <project>_custom-app redis-cache: image: redis:7-alpine |
ポイント:ローカル開発では
build、本番環境では CI が作成したレジストリイメージをimage:で参照するのが管理しやすいです。
.env による環境変数の一元管理
機密情報は .gitignore に追加し、チームごとにローカルで保持します。以下はサンプルです。
|
1 2 3 4 5 6 |
# .env (Git 管理外) MYSQL_ROOT_PASSWORD=StrongP@ssw0rd MYSQL_DATABASE=myapp MYSQL_USER=appuser MYSQL_PASSWORD=UserP@ss |
Compose 側の記述はシンプルです。
|
1 2 3 4 5 |
services: db: image: mysql:8.0 env_file: ./.env # 全変数を自動ロード |
ポイント:
env_fileはファイル全体をインポートするので、個別にenvironment:を書く手間が省けます。
永続化ボリュームの種類と設定例
| 種類 | 特徴 | 推奨シーン |
|---|---|---|
| named volume | Docker が管理し、バックアップや移行が容易 | 本番データベース・永続ストレージ |
| bind mount | ホストディレクトリを直接マウント。コード変更が即時反映 | ローカル開発・ホットリロード |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
services: db: image: postgres:15-alpine volumes: - pg_data:/var/lib/postgresql/data # named volume web: build: ./web volumes: - ./src:/app/src # bind mount(開発向け) volumes: pg_data: |
ポイント:本番は named volume、ローカルは bind mount を組み合わせると安全かつ高速です。
実務で必須のオプションとネットワーク設計
コンテナ運用では 起動順序・ヘルスチェック・再起動ポリシー、そして ネットワーク分離 が重要です。以下に具体的な設定例を示します。
depends_on・healthcheck・restart の実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
services: api: build: ./api depends_on: db: condition: service_healthy restart: unless-stopped # 開発機の再起動時も自動復帰 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 15s timeout: 5s retries: 4 db: image: postgres:15-alpine restart: on-failure healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] interval: 10s timeout: 3s retries: 5 |
ポイント:
restart: unless-stoppedは開発マシンの再起動時にコンテナを自動で復帰させ、手作業を減らします。
ネットワーク分離と外部ネットワーク活用例
内部サービスはプライベート internal ネットワークに閉じ、外部 API と通信が必要なものだけ public に参加させます。public は Docker Desktop がデフォルトで提供するブリッジネットワークを再利用します(公式参照: https://docs.docker.com/engine/reference/commandline/network_create/#options)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
services: backend: build: ./backend networks: - internal frontend: build: ./frontend networks: - internal - public # 公開ポートは外部ネットワーク経由で提供 networks: internal: driver: bridge public: external: true |
ポイント:
internalは他サービスからのみアクセス可能。攻撃面を最小化しつつ、必要な通信だけpublicに露出させます。
シークレット管理の実践例(Swarm 非対応でも安全に)
Docker Desktop の GUI では Secrets 機能が Swarm 専用で利用できません。その代わりに BuildKit の --secret オプション を組み合わせると、ビルド時に機密情報をコンテナ内部へ安全に流し込めます。以下は実際の手順です。
1. シークレットファイルを用意
|
1 2 3 |
# .db_pass(Git 管理外) SuperSecretPassword123! |
.gitignore に .db_pass を追加してください。
2. Dockerfile 側でシークレットを参照
|
1 2 3 4 5 6 7 8 9 10 |
# syntax=docker/dockerfile:1.4 ← BuildKit が必要な宣言 FROM node:20-alpine AS builder ARG DB_PASSWORD # ビルド時に渡すシークレット名 RUN --mount=type=secret,id=db_password \ cat /run/secrets/db_password > /tmp/password.txt && \ echo "Using password from secret" # 実際の処理例 # 以降は通常通りビルドを続行 |
3. Compose で BuildKit ビルドを実行
|
1 2 3 4 5 6 7 8 9 10 11 12 |
services: app: build: context: ./app dockerfile: Dockerfile secrets: - db_password # secret 名とファイルパスは下記で紐付け secrets: db_password: file: .db_pass |
コマンド例:
|
1 2 |
DOCKER_BUILDKIT=1 docker compose build --ssh default --secret id=db_password,src=.db_pass |
ポイント:シークレットはビルドプロセスの中だけで利用され、最終イメージには残りません。実行時に環境変数として渡す場合は
docker compose up -d時に同様の--env-fileを併用してください。
Docker Desktop での基本操作とトラブルシューティング
Docker Desktop は GUI と CLI のハイブリッド環境です。以下は日常的に使用するコマンドと、よくあるエラーへの対処法です。
基本コマンド一覧
| コマンド | 説明 |
|---|---|
docker compose up -d |
定義されたサービスをバックグラウンド起動 |
docker compose down |
コンテナ・ネットワーク・ボリューム(オプション)を削除 |
docker compose logs -f |
リアルタイムで全コンテナのログを見る |
docker compose exec <svc> sh |
起動中コンテナにシェル接続 |
GUI でも同等操作が可能ですが、CI/CD や自動化では CLI が必須 です。
よくあるエラーと公式ドキュメントでの対処法
| エラーメッセージ | 原因例 | 推奨対策(公式リンク) |
|---|---|---|
Error starting userland proxy (ポート競合) |
ホスト側で同じポートが使用中 | docker compose ps で確認し、ports のマッピング先を変更。参照: https://docs.docker.com/compose/networking/ |
permission denied(ボリューム権限) |
macOS/Windows とコンテナ UID が不一致 | ボリュームオプションに cached / delegated を付与、または Docker Desktop の File Sharing 設定で対象ディレクトリを追加。参照: https://docs.docker.com/desktop/mac/#file-sharing |
healthcheck failed repeatedly |
起動待ち時間が短すぎる | interval, timeout, retries を長めに設定し、実際の起動ログで遅延を測定。参照: https://docs.docker.com/engine/reference/builder/#healthcheck |
ポイント:エラーメッセージはそのまま検索すると公式ドキュメントや GitHub Issue がヒットしやすいので、まずは Google / DuckDuckGo で検索しましょう。
設定ファイルの分割と CI/CD への組み込み
- 設定ファイル分割
docker-compose.yml… 共通ベースdocker-compose.override.yml… ローカル開発用上書き(IDE が自動適用)docker-compose.prod.yml… 本番環境向け設定
実行例:
bash
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
- シークレットの安全な取り扱い(上記 BuildKit 参照)
- CI/CD パイプライン
- GitHub Actions の
docker/compose-actionを使用し、docker compose build --push→ レジストリへプッシュ。 - デプロイステップは
docker compose pull && docker compose up -dで実行。
結論:ファイル分割と BuildKit によるシークレット管理を組み合わせれば、ローカル開発から本番デプロイまで同一の Compose 定義を安全に再利用できます。