Docker Composeとは、複数のコンテナ(アプリ・DB・キャッシュなど)の構成を1つのファイルに書き、コマンド1つでまとめて起動・停止できるツールです。docker run を何度も打つ代わりに、compose.yaml に構成を書いておけば、docker compose up だけで開発環境が立ち上がります。

この記事では、Webアプリ・PostgreSQL・Redisの開発環境を例に、compose.yamlの書き方と、よく使うコマンドを解説します。特に、入門記事では省略されがちな「DBの準備ができるまでアプリの起動を待つ」書き方は、実際に動かして違いを確認しました。

Docker Composeの早見表

やりたいこと コマンド
まとめて起動(バックグラウンド) docker compose up -d
イメージを作り直して起動 docker compose up -d --build
状態を確認 docker compose ps
ログを見る(追いかける) docker compose logs -f web
コンテナの中でコマンドを実行 docker compose exec web sh
使い捨てのコンテナでコマンドを実行 docker compose run --rm web npm test
停止して削除 docker compose down
停止して、データ(ボリューム)も削除 docker compose down -v
設定ファイルの内容と文法を確認 docker compose config
コードの変更を自動で反映 docker compose watch

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Docker Composeの使い方|compose.yamlの書き方と開発環境の作り方」

compose.yamlの基本

Webアプリ・PostgreSQL・Redisの構成です。このファイルをプロジェクトのルートに compose.yaml という名前で置きます。

services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
      REDIS_URL: redis://redis:6379
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  db:
    image: postgres:17
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: app
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 10s

  redis:
    image: redis:8

volumes:
  db-data:
項目 意味
services 起動するコンテナの一覧。ここでは web・db・redis の3つ
build: . カレントディレクトリの Dockerfile からイメージを作る
image 既存のイメージを使う
ports "ホスト側:コンテナ側" でポートを公開する
environment 環境変数。${DB_PASSWORD} は .env などから読み込む
depends_on 起動の順番と、待つ条件
volumes データを保存する場所。db-data はコンテナを消しても残る
healthcheck コンテナが「使える状態か」を確認するコマンド

ファイル名と version の書き方

  • ファイル名は compose.yaml が推奨です(docker-compose.yml も引き続き読み込まれます)
  • 先頭の version: "3.8" のような記述は不要です。現在のDocker Composeでは使われておらず、書くと警告が表示されます
  • コマンドは docker compose(スペース区切り)です。古い docker-compose(ハイフン)は、Docker本体に統合された現在の形に置き換わっています

コンテナ同士はサービス名でつながる

Composeで起動したコンテナは、同じネットワークに入り、サービス名で互いにアクセスできます。

postgres://app:パスワード@db:5432/app
                          ^^
                          サービス名

webコンテナから見た localhost は webコンテナ自身です。DBに localhost:5432 で接続しようとして失敗するのは、よくあるつまずきの1つです。コンテナ同士は db・redis のようにサービス名を使います。

接続元 → 接続先 書き方
web コンテナ → db コンテナ db:5432
自分のPC(ホスト) → db コンテナ localhost:5432(ports で公開した場合)

DBの準備ができるまで待つ:healthcheckとdepends_on

depends_on は起動の順番を決めますが、書き方によって待ち方が変わります。

# 書き方1:起動の順番だけ
depends_on:
  - db

# 書き方2:DBが「使える状態」になるまで待つ
depends_on:
  db:
    condition: service_healthy

実際に、起動してから4秒後に準備が整うDBを用意し、2つの書き方を比べました。

書き方 アプリが起動したタイミング DBの状態
depends_on: [db] 0.4秒後 health: starting(まだ準備中)
condition: service_healthy 6.2秒後 healthy(準備完了)
 Container compose-db-1 Started
 Container compose-db-1 Waiting
 Container compose-db-1 Healthy
 Container compose-app-1 Started

depends_on にサービス名を並べるだけでは、DBのコンテナが「起動した」時点でアプリも起動します。DBの初期化が終わる前にアプリが接続しようとして失敗する、という問題の原因になります。healthcheck と condition: service_healthy を組み合わせると、DBが本当に使える状態になってからアプリを起動できます。

condition 待つもの
service_started コンテナが起動した(初期値)
service_healthy healthcheck が成功した
service_completed_successfully コンテナが正常終了した(マイグレーションなど一度だけ動かす処理に使う)

よく使うhealthcheckの例

サービス test の例
PostgreSQL ["CMD-SHELL", "pg_isready -U app -d app"]
MySQL ["CMD", "mysqladmin", "ping", "-h", "localhost"]
Redis ["CMD", "redis-cli", "ping"]
Webアプリ ["CMD", "curl", "-f", "http://localhost:3000/health"](イメージに curl が必要)

環境変数と.env

compose.yaml と同じ場所に .env を置くと、${変数名} の部分に値が入ります。

# .env
DB_PASSWORD=devpassword
environment:
  POSTGRES_PASSWORD: ${DB_PASSWORD}
書き方 用途
${DB_PASSWORD} .env やシェルの環境変数から値を入れる
${DB_PASSWORD:-devpassword} 値がないときの既定値を指定する
${DB_PASSWORD:?DB_PASSWORDを設定してください} 値がないときにエラーで止める
env_file: .env.web ファイルの中身を、そのままコンテナの環境変数として渡す

.env はGitにコミットしないのが基本です。代わりに、値を空にした .env.example をコミットしておくと、チームのメンバーが迷わず準備できます。

docker compose config を実行すると、変数が展開された後の最終的な設定を確認できます。「環境変数が効いていない」ときに便利です。

ボリューム:データを残す

services:
  db:
    volumes:
      - db-data:/var/lib/postgresql/data   # 名前付きボリューム
  web:
    volumes:
      - ./src:/app/src                      # バインドマウント(PCのフォルダを共有)
volumes:
  db-data:
種類 書き方 用途
名前付きボリューム db-data:/var/lib/... DBのデータなど、残したいデータ
バインドマウント ./src:/app/src 開発中のソースコードをコンテナと共有

docker compose down ではデータは残りますが、docker compose down -v を実行すると名前付きボリュームも削除されます。DBを初期状態に戻したいとき以外は、-v を付けないように注意します。

profiles:必要なときだけ起動するサービス

管理画面ツールやテスト用のサービスなど、普段は起動しなくていいものには profiles を付けます。

services:
  adminer:
    image: adminer
    ports:
      - "8081:8080"
    profiles: ["tools"]
docker compose up -d                   # adminer は起動しない
docker compose --profile tools up -d   # adminer も起動する

実際に確認すると、docker compose config --services の一覧にも、--profile を付けたときだけ表示されました。

watch:コードの変更を自動で反映する

docker compose watch を使うと、ファイルの変更を検知して、コンテナに自動で反映できます。

services:
  web:
    build: .
    develop:
      watch:
        - action: sync
          path: ./src
          target: /app/src
        - action: rebuild
          path: package.json
docker compose watch
action 動き 向いている変更
sync 変更したファイルをコンテナにコピーする ソースコード(ホットリロードに対応したアプリ)
rebuild イメージを作り直して入れ替える package.json など依存関係の変更
sync+restart コピーしてからコンテナを再起動する 設定ファイルの変更

バインドマウントと違い、必要なファイルだけを同期するため、node_modules のようなOSごとに中身が違うフォルダで問題が起きにくいのが利点です。

開発用と本番用で設定を分ける

compose.override.yaml を置くと、compose.yaml の設定に自動で上書き・追加されます。

# compose.override.yaml(開発用・自動で読み込まれる)
services:
  web:
    environment:
      LOG_LEVEL: debug
docker compose up -d                                     # compose.yaml + compose.override.yaml
docker compose -f compose.yaml -f compose.prod.yaml up -d # 本番用の設定を明示的に指定

よくあるトラブルと対処法

症状 主な原因 対処
port is already allocated ホストのポートがほかで使われている ports のホスト側を変える("3001:3000")か、使っているプロセスを止める
アプリがDBに接続できない 接続先を localhost にしている サービス名(db)を使う
起動直後だけDB接続に失敗する DBの準備前にアプリが起動している healthcheck + condition: service_healthy
環境変数が反映されない .env の場所や変数名の違い docker compose config で展開後の値を確認
コードを変えても反映されない イメージを作り直していない docker compose up -d --build、または watch を使う
DBのデータが消えた down -v でボリュームを削除した ボリュームを消すのは初期化したいときだけにする
version is obsolete の警告 古い書き方の version: が残っている version: の行を削除する

よくある質問

Q. docker-compose.yml と compose.yaml はどちらを使えばいいですか? A. 新しく作るなら compose.yaml がおすすめです。どちらの名前でも読み込まれますが、両方ある場合は compose.yaml が優先されます。

Q. 本番環境でもDocker Composeを使えますか? A. 小規模なサービスや、1台のサーバーで動かす構成では使われています。複数台での運用や自動復旧が必要な場合は、KubernetesやAmazon ECSなどのオーケストレーションの仕組みを検討します。

Q. Dockerfileとの違いは何ですか? A. Dockerfileは1つのイメージの作り方、compose.yamlは複数のコンテナの組み合わせと起動の方法を書くファイルです。compose.yamlの build から、Dockerfileを呼び出して使います。

まとめ

  • Docker Composeは、複数のコンテナを1ファイルで定義し、まとめて起動するツール
  • ファイル名は compose.yaml、version: の記述は不要
  • コンテナ同士は サービス名でつながる。localhost は自分自身
  • DBを待つなら healthcheck + condition: service_healthy。並べるだけでは待たない
  • 秘密の値は .env に書き、Gitにはコミットしない
  • down -v はデータも消える。普段は down だけ
  • 必要なときだけ起動するものは profiles、変更の自動反映は watch

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Docker Composeの使い方|compose.yamlの書き方と開発環境の作り方」

株式会社RJCでは、開発環境を整える技術も、実際に手を動かしながら仲間と学んでいます。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?