Docker基礎 #3 - Docker Compose

Last Edited: 3/2/2025

このブログ記事では、DockerにおけるDocker Composeについて紹介します。

DevOps

前回の記事では、Dockerfileからイメージをビルドし、そのイメージからDockerコンテナを実行する方法を紹介しました。 また、開発中のコード変更ごとに新しいイメージを作成しないためにボリュームを使用する方法についても説明しました。 今回の記事では、これらの機能をより簡単に実行できるDocker Composeを紹介します。

Docker Compose

小規模なプロジェクトでは、docker run --name myserver_c myserver -d -p 3000:4000 -v /Users/.../server:/app -v /app/node_modulesのようなコマンドを手動で入力して、 イメージを実行し、コンテナをインスタンス化することは容易です。しかし、フロントエンドとバックエンド用に複数のコンテナを実行したり、水平スケーリングを行ったりする場合、 この長いコマンドを手動で入力するのは面倒で、何よりもエラーが発生しやすくなります。解決策の一つはバッシュスクリプトを設定することですが、 Dockerはより良いネイティブソリューションであるDocker Composeを提供しており、docker-compose.yamlで以下のようにビルドを設定できます。

docker-compose.yaml
version: "3.8" # Docker Composeのバージョン
 
services:
  myserver: # サービス名
    build: ./server # Dockerfileのディレクトリー
    container_name: myserver_c
    ports:
      - "3000:4000" # ローカルポート:コンテナポート
    volumes:
      - ./server:/app # ボリューム (relative local path: container path)
      - /app/node_modules # 匿名ボリューム

上記のdocker-compose.yamlの例では、<directory_name>_myserverイメージ(ディレクトリ名はYAMLファイルが存在するディレクトリの名前)を作成し、 ポートとボリュームのマッピングを持つmyserver_cコンテナを起動します。イメージのビルドでは、buildセクション下のパス(この場合は./server)を探し、 そのディレクトリ内のDockerfileを使用します。イメージをビルドして実行するにはdocker compose upコマンドを使用し、コンテナを停止するにはdocker compose downを使用できます。 コンテナを停止する際、関連するイメージとボリュームも一緒に削除するにはdocker compose down -rmi all -vを使用できます。

水平スケーリング

Docker Composeを使用すると、複数のディレクトリ内のDockerfileから複数のイメージをビルドし、それらを実行して一度に複数のコンテナを起動できます。 次の例は、水平スケーリングのために同じDockerfileから複数のイメージとコンテナを起動する例です。

docker-compose.yaml
version: "3.8"
 
services:
  myserver1:
    build: ./server
    container_name: myserver_c1
    ports:
      - "3000:4000"
  myserver2:
    build: ./server
    container_name: myserver_c2
    ports:
      - "3001:4000"
  myserver3:
    build: ./server
    container_name: myserver_c3
    ports:
      - "3002:4000"

上記では同じDockerfileを使用して3つのイメージとコンテナを作成し、ローカルポート300030013002にマッピングしています。 これらのローカルポートにトラフィックを分散するリバースプロキシやロードバランサーを設定することで、水平スケーリングを実現できます。 ただし、リバースプロキシもコンテナ化することができ、これによりサーバーをローカルポートに公開せずに、コンテナポート経由で直接サーバーと通信できるようになります。 また、以下のようにreplicasフィールドを使用することもできるようになります:

docker-compose.yaml
version: "3.8"
 
services:
  myserver:
    build: ./server
    container_name: myserver_c
    deploy:
      replicas: 3
  reverse-proxy:
    # ...リバースプロキシの設定 (省略)

上記では、サーバー用に3つのコンテナを自動的に起動しますが、これらはローカルポートには公開されません。 これにより、ローカルポートに公開されているリバースプロキシからのアクセスに制限できます(このリバースプロキシの実装については、この記事では省略し、次回の記事で取り上げます)。 上記の実装では、docker compose upの後にdocker compose scale myserver=6などを使用して、サービスmyserverの数を動的に設定することができ、 柔軟な水平スケーリングが可能になります。

イメージの依存関係

複数のイメージを設定する際、特定の順序でイメージをビルドして実行することが重要な場合があります。 例えば、トラフィックを分散するリバースプロキシを設定する前にサーバーをビルドする必要があり、 フロントエンドをビルドする前にバックエンドWebサーバーをビルドする必要があります。depends_onフィールドを使用して、 イメージのビルドと実行の順序を以下のように設定できます:

docker-compose.yaml
version: "3.8"
 
services:
  backend:
    build: ./backend
    container_name: backend_c
    ports:
      - "4000:4000"
  frontend:
    build: ./frontend
    container_name: frontend_c
    ports:
      - "3000:3000"
    depends_on:
      - backend

上記のように、問題のサービスの前にビルドして実行する必要があるサービスの名前をdepends_onフィールドにリストすることで、 バックエンドサービスがフロントエンドサービスの設定前にビルドされ実行されることを保証できます。

結論

この記事では、Docker Composeとその基本機能を紹介し、サービスの構成とビルドを簡単に行う方法を説明しました。 この記事で触れなかったDocker Composeの機能はまだ多くありますので、詳細については下記の公式ドキュメントを参照することをお勧めします。

リソース