Docker Compose入門|インストール・使い方・基本コマンドを初心者向けに解説


はじめに

Dockerを使い始めると、Webサーバー、アプリケーション、データベースなど、複数のコンテナを同時に動かしたくなる場面が出てきます。

コンテナごとに長いdocker runコマンドを実行することもできますが、起動のたびにポートやボリューム、環境変数などを指定するのは手間がかかります。設定の入力漏れや、開発者ごとの環境差が発生する原因にもなります。

この問題を解決するのがDocker Composeです。Docker Composeでは、コンテナの構成をcompose.yamlに記述し、コマンド1つでまとめて起動・停止できます。

この記事では、Docker Composeの基礎から、NginxとRedisを実際に起動する手順、よく使うコマンド、エラーの対処法までを初心者向けに解説します。

Docker Composeとは

Docker Composeは、複数のコンテナで構成されるアプリケーションを定義し、まとめて実行するためのツールです。

使用するイメージ、ポート番号、ボリューム、環境変数、コンテナ間のネットワークなどをYAML形式のファイルに記述します。一般的なファイル名はcompose.yamlです。

設定を書いた後は、次のコマンドで定義したサービスをまとめて起動できます。

docker compose up -d

Docker Composeは、開発環境だけでなく、テスト環境、ステージング環境、CIなどでも利用できます。ただし、本番環境で使用する場合は、可用性、監視、バックアップ、シークレット管理などを別途設計する必要があります。

DockerとDocker Composeの違い

DockerとDocker Composeは競合するものではなく、役割が異なります。

項目DockerDocker Compose
主な役割イメージの作成やコンテナの実行複数サービスの構成と一括管理
主な設定方法Dockerfileやコマンドオプションcompose.yaml
代表的なコマンドdocker build、docker rundocker compose up、docker compose down

Dockerでも複数のコンテナを個別に起動できます。しかし、Docker Composeを使うと、その構成をファイルとして保存し、同じ環境を繰り返し再現しやすくなります。

Docker Composeを使うメリット

複数のコンテナをまとめて操作できる

Webサーバーとデータベースなど、複数のサービスをdocker compose upでまとめて起動できます。停止や削除も一括で実行できます。

環境を再現しやすい

必要なイメージ、ポート、ボリュームなどがcompose.yamlに残るため、別のPCでも同じ構成を再現しやすくなります。チーム開発でも設定を共有できます。

コンテナ同士をサービス名で接続できる

Docker Composeは、プロジェクト用のネットワークを標準で作成します。同じComposeプロジェクト内のコンテナは、IPアドレスではなくwebやredisなどのサービス名をホスト名として通信できます。

設定ミスを減らせる

毎回長いコマンドを入力する必要がないため、オプションの付け忘れやポート番号の指定間違いを減らせます。

Docker Composeを使うための準備

Docker Desktopを使用する場合

MacやWindowsでDocker Desktopをインストールしている場合、通常はDocker Composeも含まれています。追加インストールは不要です。

ターミナルで次のコマンドを実行し、バージョンが表示されることを確認してください。

docker compose version

続けて、Docker自体が起動しているか確認します。

docker info

Dockerデーモンへの接続エラーが表示された場合は、Docker Desktopを起動してから再度実行してください。

LinuxでDocker Engineを使用する場合

UbuntuなどでDocker Engineを使用しており、Composeプラグインが未導入の場合は、Docker公式リポジトリを設定したうえで次のようにインストールします。

sudo apt-get update
sudo apt-get install docker-compose-plugin

インストール後は、次のコマンドで確認できます。

docker compose version

docker-composeは旧形式のコマンドです。現在は、ハイフンのないdocker composeを使用します。

ハンズオン:NginxとRedisをDocker Composeで起動する

ここからは、WebサーバーのNginxとインメモリデータストアのRedisを、Docker Composeで同時に起動します。

今回作成するファイル構成は次のとおりです。

docker-compose-sample/
├── compose.yaml
└── html/
    └── index.html

1. 作業用ディレクトリを作成する

mkdir -p docker-compose-sample/html
cd docker-compose-sample

2. HTMLファイルを作成する

htmlディレクトリの中にindex.htmlを作成し、次の内容を保存します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Docker Compose Sample</title>
</head>
<body>
  <h1>Docker Composeで起動できました</h1>
</body>
</html>

3. compose.yamlを作成する

プロジェクトの直下にcompose.yamlを作成し、次の内容を保存します。

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data

volumes:
  redis-data:

現在のCompose仕様では、先頭にversionを書く必要はありません。古いサンプルにあるversion: "3"などを追加すると、環境によっては廃止予定を示す警告が表示されます。

4. compose.yamlの内容を確認する

起動前に、YAMLの構文や設定内容を確認します。

docker compose config

設定に問題がなければ、正規化されたCompose設定が表示されます。インデントの間違いなどがある場合は、エラーメッセージを確認してcompose.yamlを修正してください。

5. コンテナを起動する

docker compose up -d

upはサービスの作成と起動を行うコマンドです。-dを付けると、コンテナをバックグラウンドで実行します。

6. 起動状態を確認する

docker compose ps

webとredisの状態がUpまたはrunningになっていれば起動成功です。

ブラウザで次のURLへアクセスしてください。

http://localhost:8080

「Docker Composeで起動できました」と表示されれば、Nginxコンテナは正常に動作しています。

7. ログを確認する

すべてのサービスのログを表示する場合は、次のコマンドを使用します。

docker compose logs

ログをリアルタイムで追い続ける場合は-fを付けます。

docker compose logs -f

Nginxだけのログを確認することもできます。

docker compose logs web

docker compose logs -fを終了するときは、Control + Cを押します。コンテナ自体は停止しません。

8. Redisの動作を確認する

execを使うと、起動中のサービス内でコマンドを実行できます。

docker compose exec redis redis-cli ping

次のように表示されれば、Redisは正常に動作しています。

PONG

また、webコンテナからredisというサービス名を名前解決できることも確認できます。

docker compose exec web getent hosts redis

IPアドレスとredisが表示されれば、Composeが作成したネットワーク上でサービス名による通信が可能です。

9. コンテナを停止・削除する

docker compose down

downを実行すると、このComposeプロジェクトで作成したコンテナとネットワークが停止・削除されます。

今回作成したRedisの名前付きボリュームは、通常のdocker compose downでは削除されません。データも含めて削除する場合は、次のコマンドを使用します。

docker compose down -v

注意: -vを付けると名前付きボリュームのデータも削除されます。データベースなどの必要なデータが入っている場合は、バックアップを確認してから実行してください。

compose.yamlの各項目を理解する

services

アプリケーションを構成するサービスを定義します。今回の例では、webとredisがサービス名です。

image

コンテナの作成に使用するDockerイメージを指定します。

image: nginx:alpine

Dockerfileから独自のイメージを作る場合は、imageの代わりにbuildを使用できます。

build: .

.は、compose.yamlと同じディレクトリをビルドコンテキストにする指定です。Docker Composeで既存イメージを使うだけなら、Dockerfileは必須ではありません。

buildの詳細形式:contextとdockerfile

build: .は簡略形式です。同じ指定を、contextとdockerfileに分けて書くこともできます。

build:
  context: .
  dockerfile: Dockerfile

それぞれの役割は次のとおりです。

項目役割
contextビルドコンテキストとなるディレクトリを指定する。通常、DockerfileのCOPYなどで取り込むローカルファイルは、このディレクトリを基準に指定する
dockerfileビルドに使用するDockerfileを指定する。相対パスは、contextで指定したディレクトリを基準に解釈される

この例では、compose.yamlと同じディレクトリをビルドコンテキストにし、その中のDockerfileを使います。dockerfileを省略した場合も、ビルドコンテキスト直下のDockerfileが使われます。

ファイルの配置やDockerfileの名前を変えたい場合は、詳細形式が便利です。例えば、compose.yamlと同じ場所にappディレクトリがあり、その中のDockerfile.devを使うなら、次のように指定します。

services:
  web:
    build:
      context: ./app
      dockerfile: Dockerfile.dev

この場合、使用するファイルはapp/Dockerfile.devです。dockerfileにapp/Dockerfile.devと書くと、contextの./appからさらにappをたどる指定になるため注意してください。

また、このDockerfileにCOPY . /appと書くと、通常はビルドコンテキストであるホスト側のappディレクトリ内のファイルがコピー対象になります。Dockerfileの名前を変えても、COPYのコピー元の基準はcontextです。

これらは、自作イメージをビルドする場合の設定例です。実行するには、指定した場所に対応するDockerfileを用意してください。今回のNginxとRedisのハンズオンは既存イメージを使用するため、imageの設定で進められます。Docker Docs

ports

ホスト側とコンテナ側のポートを接続します。

ports:
  - "8080:80"

左側の8080がMacやWindowsなどのホスト側、右側の80がコンテナ側のポート番号です。

volumes

サービス内のvolumesでは、ホスト上のファイルをコンテナへマウントしたり、コンテナで使うデータをコンテナの外に保存したりできます。マウントとは、別の場所にあるファイルや保存領域を、コンテナ内の指定したパスで利用できるようにすることです。

今回の設定では、バインドマウントと名前付きボリュームの2種類を使っています。

バインドマウント:ホスト上のファイルを共有する

Nginxでは、次の設定を使用しています。

volumes:
  - ./html:/usr/share/nginx/html:ro

これは、ホスト側のhtmlディレクトリを、コンテナ内の/usr/share/nginx/htmlで利用できるようにするバインドマウントです。

設定の部分意味
./html共有するホスト側のディレクトリ。今回の構成ではcompose.yamlと同じ場所にあるhtmlを指す
/usr/share/nginx/htmlコンテナ内でファイルを利用するパス。Nginxの公開ディレクトリ
roread-only。コンテナ側からは読み取り専用にする指定

ファイルをイメージにコピーしているわけではなく、ホスト上の同じファイルをコンテナから参照しています。Nginxが起動している間にホスト側のhtml/index.htmlを書き換え、ブラウザを再読み込みすると、変更を確認できます。HTMLを変更するたびにイメージをビルドし直す必要はありません。

roが制限するのは、コンテナ側からの書き込みです。ホスト側でファイルを編集することはできます。読み書きを許可したバインドマウントでは、コンテナ側で行った変更や削除もホスト側に反映されるため、読み取りだけでよい場合はroを指定しましょう。

名前付きボリューム:Dockerが管理する保存領域を使う

Redisでは、次の設定を使用しています。

services:
  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data

volumes:
  redis-data:

これは、redis-dataという名前で宣言した保存領域を、コンテナ内の/dataに接続する名前付きボリュームです。

サービス内のvolumesでは接続先を指定し、ファイルの最上位にあるvolumesでは、そのComposeプロジェクトで使用する名前付きボリュームを宣言します。ここではホスト上の./redis-dataというフォルダを共有しているわけではありません。保存領域の作成や管理はDockerが行います。

同じComposeプロジェクトで同じボリュームを使えば、コンテナを削除・再作成しても、ボリュームに保存済みのデータを引き継げます。ただし、別のPCにcompose.yamlをコピーするだけで、保存データまで移動するわけではありません。

なお、Redisのメモリ上のデータがすべて自動的に保存されることを意味するわけではありません。ここで保持されるのは/dataへ書き込まれたファイルであり、Redis自体の永続化設定とは区別してください。

バインドマウントと名前付きボリュームの比較

比較項目バインドマウント名前付きボリューム
今回の指定例./html:/usr/share/nginx/html:roredis-data:/data
保存領域の指定ホスト上のファイルやディレクトリのパスを指定するDockerが管理する保存領域を名前で指定する
主な用途ソースコード、HTML、設定ファイルなどの共有データベースなどが書き込むデータの保存
ホスト側での編集指定したファイルを普段のエディタで直接編集できる保存先の実体を直接編集する運用は避け、コンテナやバックアップ用の手順を通して扱う
通常のdocker compose downホスト上のファイルは削除されないボリュームと保存済みデータは削除されない
今回の構成でdocker compose down -vホスト上のファイルは削除されないComposeで宣言したボリュームと保存済みデータが削除される

今回のように、自分で編集するHTMLを共有するならバインドマウント、コンテナが書き込むデータを保存するなら名前付きボリュームと考えると、使い分けやすくなります。

Composeファイルでは、どちらもサービス内のvolumesに記述できます。volumesに書かれているからといって、すべてが名前付きボリュームになるわけではありません。

参考:Docker公式:ホストファイルの共有とマウントの違い、docker compose down

Docker Composeでよく使うコマンド

コマンド内容
docker compose up -dサービスをバックグラウンドで作成・起動する
docker compose psサービスの状態を確認する
docker compose logs -fログをリアルタイムで表示する
docker compose stopコンテナを削除せず停止する
docker compose start停止中のコンテナを再開する
docker compose restartサービスを再起動する
docker compose exec web shwebサービスのコンテナ内でシェルを起動する
docker compose pull定義されたイメージを取得する
docker compose configCompose設定を検証・表示する
docker compose downコンテナとネットワークを停止・削除する

よくあるエラーと対処法

Cannot connect to the Docker daemonと表示される

Docker Engineが起動していない可能性があります。MacやWindowsではDocker Desktopを起動し、画面上で起動完了を確認してから再実行してください。

port is already allocatedと表示される

指定したホスト側ポートを、別のアプリケーションやコンテナが使用しています。次のコマンドで実行中のコンテナを確認します。

docker ps

既存のサービスを停止できない場合は、compose.yamlのホスト側ポートを変更します。

ports:
  - "8081:80"

変更後はhttp://localhost:8081へアクセスします。

yaml: line … と表示される

YAMLのインデントや記号に問題があります。YAMLではタブではなく半角スペースを使用し、同じ階層の項目はインデントをそろえてください。

次のコマンドで設定を検証すると、問題のある場所を見つけやすくなります。

docker compose config

compose.yamlを変更しても反映されない

設定内容によっては、既存コンテナの再作成が必要です。

docker compose up -d --force-recreate

Dockerfileを変更した場合は、イメージを再ビルドして起動します。

docker compose up -d --build

まとめ

Docker Composeを使うと、複数のコンテナ、ネットワーク、ボリュームなどの構成をcompose.yamlで管理できます。

今回の重要なポイントは次のとおりです。

  • 現在はdocker-composeではなくdocker composeを使用する
  • docker compose up -dでサービスをまとめて起動できる
  • docker compose psとdocker compose logsで状態を確認できる
  • 同じプロジェクトのコンテナはサービス名で通信できる
  • 自作イメージのビルドでは、contextでビルド対象の範囲、dockerfileで使用するDockerfileを指定できる
  • バインドマウントはホスト上のファイル共有、名前付きボリュームはDockerが管理する保存領域の利用に使える
  • docker compose downでコンテナとネットワークを削除できる
  • docker compose down -vは保存データも削除するため注意する

まずは今回のNginxとRedisを起動し、表示、ログ確認、停止までを一通り試してみてください。Docker Composeの基本的な流れをつかめると、Webアプリケーションとデータベースを組み合わせた開発環境も作りやすくなります。

次のステップ

環境変数を.envファイルで管理する

次は、ポート番号やデータベース名など、環境ごとに変わる値を.envファイルへ分離してみましょう。compose.yamlを直接書き換える回数を減らし、開発環境ごとの設定を管理しやすくできます。ただし、パスワードやAPIキーを含む.envをGitへ誤って登録しないよう注意が必要です。

healthcheckでサービスの準備完了を確認する

コンテナが起動したことと、アプリケーションが利用可能になったことは同じではありません。healthcheckを追加すると、Webサーバーやデータベースが正常に応答できる状態かをDocker Composeから確認できます。複数サービスの起動順序や障害調査を学ぶ次の題材としておすすめです。

参考資料


“Docker Compose入門|インストール・使い方・基本コマンドを初心者向けに解説” への3件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です