Currently viewing the human version
Switch to AI version

Docker Composeとは何か

2025年9月19日現在、Docker Compose、最新のv2.39.4が出てる。Docker Inc.が開発してるから安心だ。複数のDockerコンテナで構成されるアプリケーションを、単一のdocker-compose.yml YAMLファイルで定義・実行できる。Compose Specificationに従って標準化されており、公式ドキュメントでは詳細な仕様が説明されている。

なんでこんなに神ツールなのか

手動でコンテナ管理とか、今思うと頭おかしかった。WebアプリとPostgreSQLとRedisとNginx、全部別々にdocker runで起動して、ポート番号とか覚えてられないし、IP変わったら全部設定し直しだし。5個のコンテナ立ち上げるのに毎回1時間とかかかってた。

Docker Compose使ったら:

  • docker-compose up一発で全部起動。終了。
  • 依存関係?勝手に順番守って起動してくれる
  • ネットワーク?コンテナ名で通信できる
  • データ?ボリューム設定で永続化
  • 設定?.envファイル一個で終わり

Docker Compose Architecture

実際の使用例

前の会社でもメルカリでも使ってたし、友達がいるサイバーエージェントでも普通に使ってる。特に開発環境やCI/CDパイプラインで威力を発揮する。GitHub ActionsGitLab CIでの自動化も簡単だ。

version: '3.8'
services:
  web:
    build: .
    ports:
      - \"3000:3000\"
    depends_on:
      - db
  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: password

手動コンテナ管理の地獄

あの頃の俺らは何やってたんだろうな:

  • ポート番号競合でEADDRINUSE、毎回lsof -ti:8080 | xargs kill
  • コンテナ間通信?IPアドレス手動で調べて書き換えて
  • 新人「環境構築できません」→俺「また?」の無限ループ
  • 本番「DBに接続できません」→あ、ポート番号typoしてた
  • docker run5回叩いてる間に他のコンテナ死んでる

Docker Composeならこの地獄が終わる。YAMLに書いてdocker-compose up。それだけ。

俺の黒歴史: 昔、5個のサービスを手動で起動してた。毎朝30分かけてdocker runコマンドを5回叩いて、ポート番号間違えて、DB接続URLタイポして、結局動かなくて1時間無駄にしてた。Docker Compose導入したら1コマンドで全部起動。あの苦労は何だったのか。

結論: 5個のサービスを手動で管理してたあの日々がウソみたいだ。今はYAMLファイル一個でWebアプリもDBもRedisもNginxも全部面倒見てくれる。

パフォーマンスとスケール

Docker ComposeはGoで書かれてて、起動がクソ速い。昔のPython版は重くて使い物にならなかった。

Kubernetesとかいう化け物と比較されがちだけど、正直99%の会社にK8sはオーバーキル。「将来Netflixレベルのスケールが」とか言ってK8s導入したプロジェクト、大体そのスケールに到達する前にチーム全員疲弊して転職してる。前の会社でも「k8s勉強会」とかやってたけど、結局Docker Composeで十分だった。

Docker Desktopでは、macOSやWindows上でもLinuxコンテナを動かせるので、日本のMacユーザーが多い開発現場でも問題なく使える。

なんで今さら学ぶ必要あるのか

コンテナは逃げられない。AWS ECS、Azure AKS、GCP GKE、どこもコンテナ前提。「俺はVMで十分」とか言ってたら、転職の時にポートフォリオ見せられない。

Docker Composeできれば、次にKubernetes触っても「あーこれComposeの複雑版ね」で理解できる。実際、Compose BridgeでComposeからK8sマニフェスト生成できるし。

要は、Docker Compose = コンテナ管理の基礎。これ分からずにK8s行くとか、ひらがな読めずに小説読むようなもん。

Docker Compose vs 代替ツール比較

機能/ツール

Docker Compose

Kubernetes

Docker Swarm

Podman

Vagrant

学習コストの低さ

楽勝

地獄

まあまあ

普通

面倒

設定の簡単さ

YAML 1ファイルで終わり

YAML地獄

Compose風だけどクセあり

まあまあ

Vagrantfileとかいう化石

本番運用の適性

小〜中規模なら充分

大規模じゃないと意味ない

中規模まで

小〜中規模

今更使わない

自動スケーリング

できない

これのためだけにK8s

一応できる

できない

できない

ロードバランシング

nginx併用が楽

過度に複雑

結構いける

nginx併用が楽

手動で死ぬ

開発環境での利用

最強

オーバースペック

普通

Docker Composeでいい

懐かしい

サービス間通信

自動DNS

完璧だけど複雑

いい感じ

自動DNS

手動設定で死ぬ

設定管理

.envで楽

ConfigMapとか覚えられない

Docker secrets

.envで楽

古い

リソース制御

そこそこ

完璧すぎて疲れる

結構いい

そこそこ

VM単位

日本での採用率

みんな使ってる

大企業だけ

あまり聞かない

一部の会社

レガシーのみ

始め方と実際の運用

インストールと基本操作

Docker ComposeはDocker Desktopに標準で含まれている。Linuxの場合は個別にインストールが必要だ。詳しいインストール手順は公式ガイドを参照。

macOS/Windows(Docker Desktop):

## 確認
docker-compose --version
## または新しい構文
docker compose version

Linux(スタンドアロン):

sudo curl -L "https://github.com/docker/compose/releases/download/v2.39.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Docker Development Workflow

実際にやってるワークフロー

俺らが毎日やってることは:

  1. プロジェクト構造を作る
my-app/
├── docker-compose.yml
├── .env
├── app/
│   └── Dockerfile
└── db/
    └── init.sql
  1. docker-compose.ymlを書く
version: '3.8'
services:
  app:
    build: ./app
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
      - NODE_ENV=production
    depends_on:
      db:
        condition: service_healthy
    volumes:
      - ./app:/code
    deploy:
      resources:
        limits:
          memory: 512M
      
  db:
    image: postgres:13
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
      interval: 5s
      timeout: 5s
      retries: 5
    command: postgres -c log_statement=all

volumes:
  postgres_data:

運用で学んだハマりポイント

バージョン固定しろ、絶対に

latestタグとかいう悪魔を使うな。去年、node:latestで本番デプロイしたら、翌朝「サイト見れません」の連絡。Node 20になってて、ES modulesの扱いが変わってた。金曜夜にnode:18に戻して逃げたけど、2時間のダウンタイム。バージョン固定は宗教。

## ダメな例(本番で死ぬ)
image: node:latest
image: postgres

## まともな例
image: node:18
image: postgres:15

新人が.envファイルをcommitしちゃった話

新人が.envファイルcommitしちゃって、パスワードとかAPI keyが見えちゃってた。急いで履歴から消したけど冷や汗もの。GitHubにDB接続情報とかが普通に見える状態で2日くらい放置されてた。以降、新人には「.gitignore確認しろ」って口酸っぱく言ってる。

## .env
DB_PASSWORD=super_secret_password
REDIS_URL=redis://localhost:6379
API_KEY=your-api-key-here

ボリュームで3時間溶かした話

  • Named volumeとbind mount?最初分からず適当に設定
  • Linux権限地獄でpermission deniedchown 1000:1000で解決
  • macOSで異常に遅い→cached指定で改善

ネットワークは自動でやってくれる

同じComposeの中なら、サービス名でアクセスできる。db:5432とかredis:6379とか。IPアドレス調べる必要なし。

ネットワークの理解:

networks:
  frontend:
  backend:
    internal: true

本番環境での考慮事項

Docker Composeを本番で使う場合の注意点:

セキュリティ:

監視とログ:

logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

バックアップ戦略:

## データベースバックアップの自動化
docker-compose exec db pg_dump -U user mydb > backup.sql

日本特有の問題

文字エンコーディングで死んだ話:
ユーザー名に日本語が入ってて、ログに文字化けが出てた。1週間気づかずに「なんで検索ヒットしないんだ?」って悩んでた。

environment:
  - LANG=ja_JP.UTF-8
  - LC_ALL=ja_JP.UTF-8

タイムゾーン:

environment:
  - TZ=Asia/Tokyo
volumes:
  - /etc/localtime:/etc/localtime:ro

CI/CDパイプラインでの活用:

Docker Composeは開発からテスト、本番デプロイまで一貫した環境を提供する。GitHubアクションやGitLab CIとの統合も簡単だ。

Docker Compose v2の新機能

2025年現在、v2系が主流で、いくつかの便利な機能が追加された:

services:
  ml-service:
    profiles: ["gpu"]
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

レジストリとの統合:

Docker HubやプライベートレジストリからのイメージPullや、ビルドしたイメージのPushもdocker-composeコマンドで管理できる。

このレベルの機能があれば、中小企業の開発・本番環境は十分回る。Kubernetesに移行する前に、まずDocker Composeを完全に理解することが重要だ。

Docker Compose設定の基本:

Q

`docker-compose up`してもコンテナが死ぬ

A

症状: 起動した瞬間にexit code 1で落ちる大体この3つのどれか:

  • ポート競合:他で8080使ってる → lsof -ti:8080 | xargs killで解決
  • buildで死んでる:キャッシュが腐ってる → docker-compose build --no-cache
  • 起動順序:DBが立ち上がる前にアプリが接続しようとして死ぬ → healthcheckつけろ
Q

WebアプリがDBに繋がらない

A

症状: ECONNREFUSED 127.0.0.1:5432新人がよくやるミス:yaml# ダメ:localhostを使ってるDATABASE_URL=postgres://user:pass@localhost:5432/mydb# 正解:サービス名を使うDATABASE_URL=postgres://user:pass@db:5432/mydbコンテナの中でlocalhostは自分自身。他のコンテナはdbみたいなサービス名で呼ぶ。

Q

データが消えた、死にたい

A

症状: コンテナ消したら1週間分のデータが蒸発俺がやった:yaml# こう書いてたつもりが...volumes: postgres_data:/var/lib/postgresql/data# 実際は書いてなかったNamed volumeの設定忘れてて、コンテナ削除でデータごと消失。金曜夜のdocker-compose down -vは自殺行為。

Q

Macでクソ遅い問題

A

症状: ファイル保存してから反映まで30秒、npm installが20分Macユーザーの宿命:```yaml# cached付けないと死ぬvolumes:

  • ./src:/code:cached```それでも遅い時は:
  • .dockerignorenode_modules追加
  • Docker DesktopのCPU/Memory上げる
  • 最終手段:新しいMac買う
Q

環境変数が効かない、なぜ

A

症状: .envに書いたのにundefinedになる大体この理由:

  • .envファイルの場所間違えてる(docker-compose.ymlと同じディレクトリに置け)
  • ファイル名:.env.localとか.environmentじゃダメ、.env
  • 優先順位知らない:CLI引数 > compose file > .env の順
Q

`docker-compose`コマンドがない

A

症状: zsh: command not found: docker-compose2025年なのに古い構文使ってる?:bash# v2の構文に移行しろdocker compose up# どうしても古いの使いたいならpip install docker-composeハイフンあり/なしで混乱するが、スペース区切りが新しい方式。

Q

コンテナのログが文字化けする

A

症状: 日本語が表示されない解決策:```yamlenvironment:

  • LANG=ja_JP.UTF-8
  • LC_ALL=ja_JP.UTF-8```
Q

本番環境での設定ファイル管理

A

解決策:```bash# 環境別ファイルdocker-compose -f docker-compose.yml -f docker-compose.prod.yml up``````yaml# docker-compose.prod.ymlversion: '3.8'services: app: environment:

  • NODE_ENV=production restart: unless-stopped```
Q

デプロイとCI/CD統合

A

解決策:```yaml# .github/workflows/deploy.yml

  • name:

Deploy with Docker Compose run: | docker-compose pull docker-compose up -d docker system prune -f```

Q

CPU・メモリ制限設定

A

解決策:yamlservices: app: deploy: resources: limits: memory: 512M cpus: '0.5' reservations: memory: 256M

Q

Kubernetesへの移行時期

A

判断基準:

  • サービス数が20+になった
  • 自動スケーリングが必要
  • 複数ホストで分散させたい
  • チーム規模が大きい(10+人)移行前にDocker Composeを完全に理解することが重要。
Q

セキュリティの基本対策

A

対策:```yaml# 最小権限の原則user: "1000:1000"cap_drop:

  • ALLcap_add:

  • NET_BIND_SERVICE# ネットワーク分離networks: frontend: backend: internal: true```

Q

バックアップ戦略

A

解決策:bash# データベースバックアップdocker-compose exec db pg_dump -U user mydb > backup.sql# ボリューム全体のバックアップdocker run --rm -v myapp_postgres_data:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz /data

Q

本番で`docker-compose down -v`を実行してしまった

A

症状: 全データが消失、サービス停止俺の実体験: 金曜の夜、疲れてて -v オプションに気づかなかった。PostgreSQLの1週間分のデータが消えた。教訓:

  • 本番では alias を設定: alias dcd='docker-compose down' (vオプション除外)
  • バックアップがあって助かったが、3時間のダウンタイム
  • 二度とやらないためにプロダクション環境でのエイリアス強制
Q

メモリリーク地獄で本番が落ちた

A

症状:

Node.jsアプリで12時間でコンテナが8GBメモリ使ってOOMKilled原因: nodemonの設定ミスでhot reloadが本番で動いてた解決策:```yaml# 本番用設定で learning したservices: app: deploy: resources: limits: memory: 512M # 制限は絶対つける environment:

  • NODE_ENV=production # この1行忘れてた```教訓: --max_old_space_size=4096で対応したけど、根本解決は環境変数だった
Q

ネットワーク設定で3時間潰した話

A

症状: depends_onでDB起動を待ってるつもりが、アプリがDB接続エラーで落ちる実際の問題: depends_onはコンテナ起動しか待たない。DBの初期化完了まで待ってくれない解決策:yaml# healthcheckと wait-for-it.sh の組み合わせで解決db: healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"] interval: 5s timeout: 5s retries: 5app: depends_on: db: condition: service_healthy

Q

BuildKitキャッシュ破損で謎エラー

A

症状: Docker Desktop 4.25.0に更新したら、急にdocker-compose buildで死ぬエラー: failed to solve with frontend dockerfile.v0: failed to read dockerfile解決策: docker builder pruneで復活。原因不明。現実的対策: 月一でdocker system prune -aをcronに仕込んだ

Q

M1 MacでPostgreSQLイメージが動かない

A

症状: postgres:13でコンテナ起動せず、exec format error原因: x86イメージをARM64で実行しようとしてる解決:yaml# arm64対応イメージ指定image: postgres:13platform: linux/amd64 # または linux/arm64

Docker Composeツールとリソース