- 技術 💻
Docker Composeの使い方|compose.yamlの書き方と開発環境の作り方
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期連続の黒字決算。