docker-compose.ymlの書き方サンプル(複数コンテナ連携)完全ガイド

DevOps

はじめに

Docker環境を使って複数のコンテナを同時に動かそうとしたとき、コンテナ同士の連携方法に困った経験はないでしょうか。
複数のコンテナが必要なシステム構成を一つひとつ手動で立ち上げるのは大変ですし、設定ミスが起きやすいという問題もあります。
そこで活躍してくれるのがdocker-compose.ymlというファイルを使った構成管理です。
複数のコンテナをまとめて起動したり停止したりできるため、プロジェクトごとに環境を素早く再現できます。
この記事では、初心者の方にも理解しやすい言葉を使って、 docker-compose.yml の書き方サンプル (複数コンテナ連携) を徹底的に解説します。

この記事を読むとわかること

  • docker-compose.yml とは何か、具体的にどんな役割を果たすのか
  • 複数コンテナを連携させるときの基本的な構成と設定の流れ
  • 実際の業務や学習プロジェクトで役立つ活用シーン
  • コンテナ間通信や永続化、ネットワーク設定などの具体的な書き方
  • トラブルシュートの考え方やよくあるエラーの原因

docker-compose.ymlとは何か

Dockerで複数コンテナを扱う場面では、一つひとつのコンテナをコマンドで起動して設定する方法もあります。
しかし、コンテナの数が増えると管理が煩雑になりやすいです。
そこで、コンテナの起動や設定を一括管理するためのファイルがdocker-compose.ymlです。

使用するメリット

複数コンテナの設定を一元管理できる

設定や起動などを個別に入力せずに済み、設定ファイルを編集するだけで済みます。

複数コンテナを同時に起動・停止できる

コマンド一つで関連するコンテナをまとめて制御できるため、手間が大きく減ります。

プロジェクトごとに環境を再現しやすい

同じdocker-compose.ymlファイルを共有すれば、チーム全員が同じ開発環境をすぐに立ち上げられます。

docker-composeコマンドの流れ

docker-compose.ymlを使うときは、一般的に以下のような流れでプロジェクトを動かします。

  1. docker-compose.ymlファイルを作成し、必要なサービス(コンテナ)の設定を書く
  2. ターミナルでdocker-composeが使える状態にする
  3. docker-compose up などのコマンドでコンテナを起動する
  4. 必要に応じて docker-compose down で停止・破棄する

このように、docker-compose.ymlとdocker-composeコマンドをセットで扱うイメージです。

複数コンテナ連携の全体像

ここからは、複数コンテナをどのように連携させるかをイメージしやすいように解説します。
複雑に考えすぎず、まずは「Webアプリケーション用のコンテナ」と「データベース用のコンテナ」を一緒に起動する例をイメージすると理解しやすいです。

実務でのイメージ

たとえばWebアプリを開発する際、アプリ本体は1つのコンテナで動かし、データを保存するためのデータベースは別のコンテナで動かします。
この2つのコンテナ間をネットワークで連携させることで、アプリからデータベースにアクセスできる構成にするわけです。
この構成をdocker-compose.ymlでまとめて定義することで、手動でコンテナ間の設定を行わなくても、コマンド一発で環境を再現できるようになります。

ネットワークの考え方

Dockerはコンテナ同士の通信を行うために、ネットワークという仕組みを使います。
docker-compose.ymlでは、デフォルトで同じdocker-composeプロジェクト下にあるコンテナは同一のネットワークに配置されます。
そのため、<サービス名>:<ポート> のように記述して通信できるようになるのが特徴です。
コンテナ間通信を成立させるうえで、あえて追加のネットワーク設定を行う場合もありますが、初心者の方はまずデフォルトの設定で十分かもしれません。

docker-compose.ymlの基本構成

ここでは、docker-compose.ymlをどのように書けばよいか、その基本的な項目を見てみましょう。
複数コンテナ連携の例として、Webアプリコンテナデータベースコンテナを連携させるための記述を解説します。

version(現行フォーマットでは省略が多い)

古い形式ではファイルの先頭にバージョンを明示することがありました。
しかし、現在の形式では省略されるケースも多いです。
学習の初期段階ではversionの指定が登場する例を見かけるかもしれませんが、最近のドキュメントでは記載しないことが増えています。

servicesセクション

docker-compose.ymlで最も重要なのが、servicesというセクションです。
ここに、起動したいサービス(コンテナ)を並べて定義します。
たとえば、Webアプリ用のコンテナをapp、データベース用のコンテナをdbなどの名前で書きます。

volumesセクション

コンテナ内のデータを永続化したいときには、volumesを使います。
これにより、コンテナを再起動してもデータが消えずに保持されます。
大事なデータを扱うときはここをきちんと設定すると良いでしょう。

networksセクション

複数コンテナのネットワークを細かくカスタマイズしたいときに使います。
デフォルトでもコンテナ間通信はできますが、セキュリティや用途に応じてカスタムネットワークを設定する場合があります。
初めはあまり触らずにデフォルトのネットワークを利用するだけでも十分です。

docker-compose.ymlの書き方サンプル

次の例は、シンプルなWebアプリとデータベースを連携させるためのdocker-compose.ymlのサンプルです。
あくまで一例であり、実際の環境に合わせてイメージしてみてください。

services:
  app:
    image: nginx:latest
    container_name: my-webapp
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - db

  db:
    image: mysql:latest
    container_name: my-db
    environment:
      - MYSQL_ROOT_PASSWORD=rootpass
      - MYSQL_DATABASE=my_database
      - MYSQL_USER=my_user
      - MYSQL_PASSWORD=my_password
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

サンプルのポイント解説

上記のサンプルには、Webアプリとしてnginxイメージを使うapp、そしてデータベースとしてmysqlイメージを使うdbを定義しています。

ports:

外部からアクセスするためのポートを指定する項目です。
"8080:80" と書いている場合、ホストの8080番ポートがコンテナの80番ポートに対応するという意味になります。

volumes:

データをコンテナの外部に保持するための設定です。
Webアプリ部分では ./html:/usr/share/nginx/html:ro と記述し、ローカルのhtmlフォルダをコンテナ内の /usr/share/nginx/html にマウントしています。
データベース部分では db_data:/var/lib/mysql と書くことで、コンテナ内の /var/lib/mysql ディレクトリを named volume にマウントしています。

depends_on:

appのコンテナが起動する前にdbコンテナを起動するという依存関係を示します。
ただし、これは「データベースが完全に立ち上がり、受け付け可能な状態になるまで待つ」という意味ではありません。
単にコンテナの起動順を示すものなので、アプリ起動時にDBが準備中だと接続エラーになる場合があります。
必要に応じてアプリ側のリトライロジックや健康チェックなどを組み合わせると良いでしょう。

コンテナ間通信の仕組みを理解する

複数コンテナを連携させる際、どのようにコンテナ間通信が行われるのか把握しておくと安心です。
デフォルトのdocker-composeでは、同一プロジェクト内のコンテナは自動的に同じネットワークに属します。

サービス名で通信できる理由

コンテナ間通信では、コンテナのIPアドレスを直接指定するのではなく、サービス名やコンテナ名を使うのが一般的です。
これはDockerが内部的にDNSを管理しているからです。
そのため、アプリのソースコードや設定ファイルで、ホスト名としてdb(上のサンプルではサービス名がdb)を指定すれば、同じネットワーク内で名前解決されます。

ポートの扱い

コンテナ内部とホスト側のポートマッピングは別物です。
コンテナ同士が通信する場合はコンテナの内部ポートにアクセスできますが、外部(ホスト)から通信する場合はポートマッピングを設定する必要があります。
たとえばWebサーバーコンテナの80番ポートをホストの8080番ポートに対応させたいなら、"8080:80"とするイメージです。

永続化とボリューム管理

データベースをDockerコンテナ内で動かすときは、データをどう扱うかが重要です。
そのままコンテナを消すとデータが全部消えてしまうからです。

なぜデータを永続化する必要があるか

多くのアプリケーションでは、ユーザーが入力したデータやアプリの設定情報など、消えてほしくないデータを扱う場面があります。
Dockerはコンテナを気軽に作り直せる利点がありますが、データが毎回消えてしまうと困ってしまいます。
そこで、volumeを使ってコンテナ外部にデータを保管できるようにします。

volumeの種類

1. named volume

docker-compose.ymlで volumes セクションを定義しておくと、named volumeとしてDockerが管理します。

2. bind mount

ホスト側のディレクトリをそのままコンテナにマウントする方法です。
開発時にファイル修正を素早く反映させるためによく使われます。

注意点

ボリュームを使っていても、マシンを入れ替えたりOSごと再インストールした場合にはデータが消えることもあります。
バックアップ体制を整えるなど、実際の運用ではデータ消失リスクをしっかり考えておくと安心です。

docker-composeの主要コマンド

docker-compose.ymlを用意したら、次はどんなコマンドを使うのか理解しておくとスムーズです。
ここではよく使うコマンドだけを簡単に紹介します。

docker-compose up

指定したdocker-compose.ymlに沿ってコンテナを起動します。
-d オプションを付けるとバックグラウンドモードで起動します。
例: docker-compose up -d

docker-compose down

起動中のコンテナやネットワーク、ボリュームを停止・削除します。
ただし、named volumeなどはオプションを付けない限り削除されません。
例: docker-compose down

docker-compose ps

現在起動中のコンテナ一覧とステータスを表示します。
例: docker-compose ps

docker-compose logs

各コンテナのログを表示します。
例えば docker-compose logs app のように特定のサービス名を指定すると、そのサービスのログが見られます。

docker-compose exec

すでに起動しているコンテナの中に入って操作するためのコマンドです。
例: docker-compose exec db bash など。

実務での活用シーン

初心者の方でも、実際の業務や学習環境でdocker-compose.ymlを使うメリットを感じられるシーンをいくつか紹介します。

複数コンテナを使う開発環境

Webサーバーやアプリサーバー、DB、キャッシュサーバーなど、サービスが増えると手動でコンテナを立ち上げる作業は大変です。
docker-compose.ymlにまとめておけば、コマンド一つで必要なコンテナが起動でき、環境構築が楽になります。

テスト環境の準備

プロジェクトごとに異なるバージョンのDBやプログラミング言語のランタイムが必要な場合、混在してしまうとローカル環境が混乱します。
docker-compose.ymlを使ってプロジェクト単位で切り替えられるようにすれば、環境を汚さずテストを進められます。

チーム開発での共有

docker-compose.ymlはテキストファイルであるため、バージョン管理ツールを通して簡単に共有できます。
新メンバーが加わったときや別のマシンに移行したときでも、同じファイルで環境が再現できる点が便利です。

よくあるエラーとトラブルシュート

docker-composeを使い始めたばかりのとき、いくつかのエラーに遭遇することがあります。
ここでは初心者の方がはまりやすい代表的なトラブル例と、その対処法を紹介します。

コンテナ同士が通信できない

原因
コンテナ名やネットワーク設定が間違っていることが多いです。
また、環境変数が想定と違っているケースもあります。

対策

  • docker-compose.ymlのサービス名と、実際にアプリ側で指定しているホスト名が合っているか確認する
  • ポート番号の指定が正しいか、コンテナ内部ポートとホスト側ポートが混在していないかを見直す

DBコンテナが起動していないうちにアプリが接続を試みる

原因
depends_onだけではDBの完全な起動を待ってからアプリが動くわけではないためです。
アプリ側が起動時にDB接続に失敗することがあります。

対策

  • アプリ側で再接続のロジックを組む
  • ヘルスチェックやリトライを活用する

ホスト側ファイルがコンテナに反映されない

原因
bind mountで指定したパスが間違っているか、パスの相対指定が不正なケースがあります。
もしくはファイルの所有権・権限設定などの問題がある場合も考えられます。

対策

  • docker-compose.ymlのvolumes記述が正しいか再確認する
  • ホスト側のパスが存在しているか、権限が適切かをチェックする

docker-compose.ymlをより活用する設定例

初期の頃はシンプルな構成で十分ですが、プロジェクトによってはさらに便利な設定を活かすこともあります。

環境変数ファイルの利用

ユーザー名やパスワードなど、外部に漏れてはいけない情報をdocker-compose.ymlに直書きするのは避けたい場合があります。
そのときは、.envファイルを使うことで環境変数を分離して管理できます。
docker-compose.ymlの中で ${VAR_NAME} のように参照すると、.envファイルから読み込める仕組みです。

buildオプションで自前のDockerイメージを使う

Dockerfileを用意して自分専用のイメージを作る場合には、imageの代わりにbuild: .のような指定ができます。
こうすると、docker-composeがDockerfileを元にイメージをビルドし、そのコンテナを起動してくれます。

複数のdocker-compose.ymlを使う

大規模なプロジェクトでは、baseとなるdocker-compose.ymlと、環境ごとに追加設定を書くdocker-compose.override.ymlなどを分ける方法もあります。
複数ファイルを組み合わせて使うことで、必要なコンテナ構成だけを選択的に起動できるメリットがあります。

セキュリティ面で意識すべきポイント

コンテナ同士の連携がスムーズになる一方で、セキュリティには注意が必要です。

不必要なポートの公開

docker-compose.ymlで ports を指定すると、そのポートはホストに公開されます。
外部からアクセス可能になるので、利用するポートだけを公開し、不要なポートは開放しないようにします。

パスワードや秘密鍵の取り扱い

docker-compose.ymlにパスワードや秘密鍵を直接書くと、それがソース管理レポジトリに含まれ、漏洩リスクが高まります。
.envファイルや秘匿情報管理の仕組みを併用するなど、慎重に扱うことをおすすめします。

コンテナイメージの信頼性

公式イメージや信頼できるベンダーのイメージを使うようにして、不審なイメージは避けましょう。
docker-compose.ymlで指定するイメージが意図したものか、常に確認する習慣をつけることが大切です。

実務で遭遇しがちなパターン

docker-compose.ymlを使っていると、プロジェクトが大きくなるにつれて様々なパターンが登場します。
ここでは、よくあるケースを簡単にまとめます。

マイクロサービス的な構成

サービスが増え、コンテナも増えると、docker-compose.ymlがどんどん長くなるケースがあります。
各サービスを別リポジトリで管理しつつ、統合テスト用にdocker-compose.ymlを用意することも多いです。

開発用と本番用の設定分割

開発環境ではソースコードをbind mountしてホットリロードする構成にし、本番環境用にはビルド済みイメージを使うなど、環境によって設定を分割するケースがあります。
本番ではロギングや監視ツールのコンテナを追加することもあり、複数のdocker-composeファイルを組み合わせることもあるでしょう。

ホストマシンのリソース管理

Dockerは軽量な仮想化技術ですが、コンテナ数が増えるとホストのCPUやメモリを圧迫することがあります。
docker-compose.ymlで各サービスにリソース制限を入れると、万が一の暴走も抑えやすくなります。

覚えておきたいTIPS

ここでは、docker-compose.ymlを扱う上で覚えておくと便利な小ネタをいくつか紹介します。

プロジェクト名を指定する

デフォルトでは、docker-composeコマンドを実行したディレクトリ名がプロジェクト名になります。
-p オプションを使うと明示的にプロジェクト名を指定できます。
プロジェクト名が異なるとコンテナ名やネットワーク名などにも影響するため、わかりやすく名前を付けておくとよいでしょう。

logsコマンドでリアルタイム出力を追う

docker-compose logs -f とすれば、リアルタイムでコンテナのログが流れてくる様子が見られます。
エラー対応やデバッグに役立つはずです。

downコマンド時にボリュームも消す

開発環境でデータをリセットしたい場合、docker-compose down -v とすれば、関連するnamed volumeも一括で削除できます。
本番環境で誤って実行しないよう、慎重に扱うことが大切です。

よくある質問

初心者の方が抱きやすい疑問について、いくつか回答しておきます。

docker-compose.ymlを複数に分けたくなったらどうするのか

サービス数が増えすぎて管理しにくくなったら、共通部分と環境別の部分でファイルを分ける方法があります。
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d のように複数のファイルを読み込めます。

今後docker-composeは使われなくなるのか

docker-composeは長年使用されてきましたが、Docker自体にcompose機能が統合される動きもあります。
ただし、それは使い勝手がなくなるという意味ではなく、より統合的な方向へ進化しているイメージです。
いずれにせよdocker-compose.yml形式の書き方を理解しておけば問題ありません。

注意したい運用上のポイント

開発だけでなく、運用でもdocker-composeが使われる場合があります。
ただ、本番運用で大規模なスケールを求めるときは別のオーケストレーションツールを使うケースが多いです。

複数のサービスを本番運用するときは、docker-composeだけでスケールアウトするのは難しい場合があります。 負荷分散やモニタリングをどのようにするかまで含め、全体設計をきちんと行うことが重要です。

本番運用時のログ・監視

コンテナ単位でログを収集したり、サービスの稼働状況を監視する仕組みが必要です。
ログを一元管理する仕組みや、コンテナオーケストレーションツールの導入などを検討してみるのも大切です。

セキュリティアップデートの適用

イメージの脆弱性を発見した場合、定期的にイメージを更新し、コンテナをリビルドして新しい環境を適用する必要があります。
docker-compose.ymlで参照しているイメージを更新し、定期的にアップデートの仕組みを回すことを意識してみてください。

トラブル時の調査方法

問題が起きたときは、docker-composeコマンドやDocker本体のログから情報を集めるのが基本です。
特にコンテナ内部で何が起きているのかわからないときは、以下のステップを試してみるとヒントが得られます。

コンテナログの確認

docker-compose logs でサービスごとのエラーメッセージをチェックします。
アプリ側のログとDB側のログ、それぞれ別々に表示して原因を切り分けましょう。

コンテナ内に入って確認

docker-compose exec <サービス名> bash でコンテナに入って、ログファイルや設定ファイルを直接確認する方法です。
アプリが正しく起動しているか、環境変数が期待通りに設定されているかを調べることができます。

yamlの文法エラー

意外とよくあるのが、インデントがズレているなどのyaml文法エラーです。
docker-composeコマンドがエラーで止まったら、ファイルのインデントを再チェックすると解決することがあります。

実務導入でのまとめ

docker-compose.ymlは単なる設定ファイルに見えますが、プロジェクトの成長とともに重要度が増してきます。
適切な構成や命名、そしてドキュメント化を行えば、開発チーム全体の生産性を上げることができます。

小さなプロジェクトからdocker-compose.ymlの運用に慣れておくと、大きな環境でもスムーズに導入できます。

最初から完璧を目指さず、まずはシンプルな構成から試してみましょう。
トラブルが発生したら、その都度設定を見直すことで知識や理解が深まっていきます。

まとめ

この記事では、 docker-compose.yml の書き方サンプル (複数コンテナ連携) をテーマに、初心者の方でもわかりやすい解説を心がけました。
複数コンテナを連携させると一見複雑そうに見えますが、docker-compose.ymlを活用すればまとまった形で管理できるので、思いのほかシンプルに運用できます。

複数のコンテナを使うシーンは、開発環境から本番環境まで広範囲に及びます。
とはいえ、まずは小規模の例から始めてみるのがおすすめです。
慣れてきたら、環境変数ファイルやビルドオプション、さらに複雑なネットワーク構成など、発展的な内容にも挑戦してみてください。

docker-compose.ymlはとても柔軟な仕組みで、多様なサービス連携を一元管理できます。
最終的にはチーム開発や大規模プロジェクトにも導入しやすくなるでしょう。
これを機に、コンテナ管理の効率化と安定した開発フローを手に入れてみてはいかがでしょうか。

Dockerをマスターしよう

この記事で学んだDockerの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。