2026年5月24日

2026年5月24日

docker-compose.ymlの書き方を解説|基本構造・よく使うキー・つまずきやすい点

docker-compose.yml(現在の推奨名は compose.yaml)は、複数のコンテナの起動条件を1つのファイルにまとめる設定ファイルです。書き方の要点は「トップレベルに services・volumes・networks を置き、各サービスに image か build、ports、environment、volumes を書く」の一点に集約できます。この記事では、WordPress と MariaDB の構成を例に、各キーの意味、YAML 特有のつまずき、書いた内容を検証する手順までを順に説明します。

ファイル名とバージョン指定の現状

Compose の書式は現在「Compose Specification」という仕様にまとめられ、Docker Compose V2(docker compose コマンド)がそれを実装しています。(2026年10月現在)押さえておきたい点は次の3つです。

  • ファイル名は compose.yaml が推奨ですが、docker-compose.yml も引き続き読み込まれます。両方あると compose.yaml が優先されるため、どちらか一方に統一してください。
  • 先頭の version: "3.8" のような行は不要になりました。書いても動きますが、Compose V2 では「obsolete(廃止)」という警告が出ます。古い記事のサンプルをコピーしたときに残りやすい行です。
  • 旧来の Python 製 docker-compose(V1)は更新が終了しています。コマンドはハイフンなしの docker compose を使います。

最小構成から全体像をつかむ

まずはサービスが1つだけの形を見て、階層の考え方をつかみます。

services:
  web:
    image: nginx:1.27
    ports:
      - "8080:80"

services の下にサービス名(ここでは web)を置き、その下にコンテナの設定を書きます。サービス名は Compose が作るネットワーク内でそのままホスト名として使えるため、別のコンテナから http://web で到達できます。この「サービス名=接続先ホスト名」という性質は、データベースの接続設定でよく使います。

YAML はインデントで階層を表します。インデントにタブは使えず、スペースで揃える必要があります。2スペースで統一しておくと、エディタ間で崩れにくくなります。

WordPress と MariaDB の構成例

実用的な例として、WordPress とデータベースを組み合わせた構成を示します。パスワードなどの値は直接書かず、同じフォルダの .env から読み込む形にしています。

services:
  db:
    image: mariadb:11.4
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: ${DB_NAME}
      MARIADB_USER: ${DB_USER}
      MARIADB_PASSWORD: ${DB_PASSWORD}
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  wordpress:
    image: wordpress:php8.3-apache
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: ${DB_NAME}
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
    volumes:
      - wp_data:/var/www/html
      - ./wp-content/themes/my-theme:/var/www/html/wp-content/themes/my-theme

volumes:
  db_data:
  wp_data:
# .env(Git にはコミットしない。値はダミーです)
DB_NAME=wordpress
DB_USER=wp_user
DB_PASSWORD=change-me-local-only
DB_ROOT_PASSWORD=change-me-root-local-only

イメージのタグ(mariadb:11.4、wordpress:php8.3-apache)は執筆時点の例です。実際に使うタグは Docker Hub の各公式イメージのページで、提供中のものを確認してください。

よく使うキーの意味と書き方

image と build

image は既存のイメージを使う指定、build は Dockerfile からイメージを作る指定です。自作の Dockerfile を使う場合は次のように書きます。

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev

latest タグだけに頼ると、ある日 pull した時点で中身が変わり、動作が変わることがあります。少なくともメジャー・マイナーバージョンまでは固定しておくと、再現性が上がります。

ports

"ホスト側:コンテナ側" の順です。逆に書くと、意図しないポートで待ち受けてしまいます。ポート指定はダブルクォートで囲むのが安全です。コンテナ側が60未満のポート(22:22 など)は、YAML の解釈で xx:yy が60進数の数値として扱われることがあり、Docker の公式ドキュメントでも文字列で書くことが勧められています。

外部に公開する必要のないサービス(データベースなど)には ports を書かないのが基本です。同じ Compose プロジェクト内のコンテナ同士は、ポートを公開しなくても内部ネットワークで通信できます。ローカルからだけ接続したいときは "127.0.0.1:3306:3306" のように待ち受けアドレスを限定します。

environment と env_file

environment はコンテナに渡す環境変数です。マップ形式(KEY: value)とリスト形式(- KEY=value)のどちらでも書けますが、1つのファイル内ではどちらかに揃えます。マップ形式で true・false・yes・no のような値を書くと YAML の真偽値と解釈されるため、"true" のようにクォートしてください。

${DB_NAME} の部分は「変数展開」で、Compose ファイルと同じ場所にある .env や、シェルの環境変数から値が入ります。${DB_NAME:-wordpress} と書けば未設定時の既定値を、${DB_PASSWORD:?未設定です} と書けば未設定時にエラーで止める指定ができます。値に $ そのものを含めたい場合は $$ と書きます。

なお、.env は「Compose ファイルの変数展開用」、env_file: は「コンテナに渡す環境変数ファイルの指定」で、役割が異なります。混同すると「値が渡っていない」という状況になりやすい部分です。

volumes

データを残す方法は2種類あります。db_data:/var/lib/mysql のように名前で指定するのが名前付きボリュームで、Docker が管理する領域に保存されます。./wp-content/themes/my-theme:... のように ./ から始まるパスはバインドマウントで、ホスト側のフォルダをそのまま見せます。

データベースのように消えては困るデータは名前付きボリューム、編集しながら確認したいテーマのソースはバインドマウント、という使い分けが一般的です。名前付きボリュームはファイル末尾のトップレベル volumes: にも名前を書いておく必要があります。

depends_on と healthcheck

depends_on に名前を並べるだけでは「先にコンテナを起動する」順番しか保証されず、データベースが接続を受け付ける状態になったかまでは待ちません。WordPress が先に接続を試みて失敗するのはこのためです。

例のように condition: service_healthy を付け、依存先に healthcheck を設定すると、ヘルスチェックが成功してから次のサービスが起動します。MariaDB の公式イメージには healthcheck.sh が同梱されていますが、イメージのバージョンによって使えるオプションが異なる可能性があるため、公式イメージの説明で確認してください。

restart

restart: unless-stopped は、手動で止めた場合を除き、異常終了や Docker の再起動時にコンテナを自動で起動し直す設定です。開発用途なら指定しない(既定は no)選択もあります。

書いたファイルを検証する

書き終えたら、起動する前に docker compose config で解釈結果を確認します。

# 構文と変数展開の結果を表示(エラーがあればここで止まる)
docker compose config

# バックグラウンドで起動し、状態とログを確認
docker compose up -d
docker compose ps
docker compose logs -f wordpress

config は変数展開後の完全な設定を出力するため、.env の値が入っているか、インデントのずれでキーが別の階層に入っていないかを目で確かめられます。出力にはパスワードも展開されて表示されるので、画面共有やログへの貼り付けには注意してください。

停止は docker compose down です。docker compose down -v は名前付きボリュームも削除し、データベースの中身が消えます。データを残したい環境では -v を付けないでください。本番に近いデータを扱う前には、mysqldump(MariaDB では mariadb-dump)などでバックアップを取っておきます。

環境ごとの差分を分ける

開発と本番で設定を変えたい場合は、ファイルを分けて重ねる方法が使えます。compose.yaml と同じ場所に compose.override.yaml があると自動で重ねて読み込まれるため、開発用のバインドマウントやデバッグ設定はそちらに書きます。本番では docker compose -f compose.yaml -f compose.prod.yaml up -d のように、読み込むファイルを明示します。

profiles: を付けたサービスは、docker compose --profile tools up のように指定したときだけ起動します。phpMyAdmin のような補助ツールを普段は起動しない構成にするのに便利です。

よくあるつまずき

  • mapping values are not allowed here などのエラーは、インデントのずれやコロン後のスペース抜けが原因であることが多いです。エラーに出る行番号の前後を確認します。
  • .env を変更しても反映されない場合は、docker compose up -d で再作成されたかを docker compose ps の起動時刻で確認します。
  • .env を Git にコミットしてしまう事故を防ぐため、.gitignore に追加し、値を空にした .env.example だけを共有します。
  • バインドマウントしたファイルの所有者が合わず書き込めない場合は、コンテナ内のユーザー(WordPress 公式イメージなら www-data)とホスト側の UID の関係を確認します。

まとめ

  • ファイル名は compose.yaml が推奨で、docker-compose.yml も使えます。version: 行は不要です。
  • サービス名は内部ネットワークでそのままホスト名になります。外部公開が不要なサービスには ports を書きません。
  • ポートはクォートで囲み、真偽値に見える環境変数の値もクォートします。
  • 秘密の値は .env で渡し、Git には含めません。
  • 起動順は depends_on の condition: service_healthy と healthcheck で制御します。
  • 起動前に docker compose config で解釈結果を確かめ、down -v はデータが消えることを理解したうえで使います。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲