Dockerは単体のコンテナ管理に便利なツールですが、実際の開発環境や本番環境では複数のコンテナを連携させる必要があります。そこで活躍するのがDocker Composeです。今回は、Docker Composeの基本的な使い方と、効率的な環境構築のポイントを解説します。
Docker Composeとは?
Docker Composeは、複数のDockerコンテナを定義し実行するためのツールです。YAMLファイルを使って、アプリケーションを構成するサービス、ネットワーク、ボリュームなどを宣言的に記述できます。これにより、複雑なマルチコンテナアプリケーションを簡単に構築・管理することが可能になります。
インストール方法
Docker Desktopをインストールしている場合は、Docker Composeも一緒にインストールされています。単体でインストールする場合は、OSに応じて以下のようにインストールします。
Linuxの場合
sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
macOSの場合(Homebrewを使用)
brew install docker-compose
Windowsの場合
Docker Desktopをインストールするか、WSL2を使用している場合はLinuxと同様の手順でインストールします。
docker-compose.ymlの基本構成
Docker Composeの設定は、通常「docker-compose.yml」という名前のファイルに記述します。基本的な構成は以下の通りです:
version: '3'
services:
web:
build: ./web
ports:
- "8000:8000"
volumes:
- ./web:/code
depends_on:
- db
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_USER=user
- POSTGRES_DB=mydb
volumes:
postgres_data:
主要な要素
- version: 使用するDocker Composeファイルのバージョンを指定します。
- services: アプリケーションを構成する各コンテナの設定を定義します。
- volumes: データを永続化するためのボリュームを定義します。
- networks: コンテナ間の通信ネットワークを定義します(上記例では省略)。
基本的なコマンド
Docker Composeでよく使うコマンドを紹介します:
- 起動:
docker-compose up
– 定義されたサービスを起動します。- バックグラウンドで実行する場合:
docker-compose up -d
- バックグラウンドで実行する場合:
- 停止:
docker-compose down
– サービスを停止し、コンテナを削除します。- ボリュームも削除する場合:
docker-compose down -v
- ボリュームも削除する場合:
- ビルド:
docker-compose build
– サービスのイメージをビルドまたは再ビルドします。 - ログ確認:
docker-compose logs
– サービスのログを表示します。- 特定のサービスのみ表示:
docker-compose logs <service_name>
- 特定のサービスのみ表示:
- 状態確認:
docker-compose ps
– 実行中のサービスを表示します。 - 実行:
docker-compose exec <service_name> <command>
– 実行中のサービスでコマンドを実行します。
実践的な環境構築例
Webアプリケーション + データベース環境
以下は、Webアプリケーション(Node.js)とデータベース(MySQL)を連携させる環境の例です:
version: '3'
services:
app:
build: ./app
ports:
- "3000:3000"
volumes:
- ./app:/usr/src/app
- /usr/src/app/node_modules
environment:
- NODE_ENV=development
- DB_HOST=db
- DB_USER=root
- DB_PASSWORD=example
- DB_NAME=myapp
depends_on:
- db
db:
image: mysql:8.0
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./init-db:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=example
- MYSQL_DATABASE=myapp
command: --default-authentication-plugin=mysql_native_password
volumes:
mysql_data:
開発環境と本番環境の分離
開発環境と本番環境で設定を分けたい場合は、複数のComposeファイルを使い分けることができます:
docker-compose.yml(共通設定)
version: '3'
services:
app:
build: ./app
depends_on:
- db
db:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
docker-compose.override.yml(開発環境設定)
version: '3'
services:
app:
ports:
- "3000:3000"
volumes:
- ./app:/usr/src/app
environment:
- NODE_ENV=development
- DEBUG=true
db:
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=dev_password
- MYSQL_DATABASE=myapp_dev
docker-compose.prod.yml(本番環境設定)
version: '3'
services:
app:
ports:
- "80:3000"
environment:
- NODE_ENV=production
- DEBUG=false
db:
environment:
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
- MYSQL_DATABASE=myapp_prod
本番環境を起動する場合は以下のコマンドを使用:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
効率的な環境構築のポイント
1. 環境変数の活用
.env
ファイルを使って環境変数を管理すると、機密情報をバージョン管理から除外できます:
# .env
DB_PASSWORD=super_secret_password
EXTERNAL_PORT=8080
YAMLファイル内で参照:
services:
web:
ports:
- "${EXTERNAL_PORT}:8000"
db:
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
2. ヘルスチェックの設定
コンテナが正常に起動したことを確認するためのヘルスチェックを設定できます:
services:
db:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
3. depends_onとcondition
サービス間の依存関係とヘルスチェックを組み合わせて、確実な起動順序を保証:
services:
app:
depends_on:
db:
condition: service_healthy
4. ボリュームマウントの最適化
開発環境でのコードの変更をリアルタイムに反映させるため、ボリュームマウントを活用します。ただし、node_modulesなどはマウントから除外するとパフォーマンスが向上します:
volumes:
- ./app:/usr/src/app # ソースコードをマウント
- /usr/src/app/node_modules # node_modulesはコンテナ内のものを使用
トラブルシューティング
1. ポートの競合
すでに使用されているポートを指定すると起動に失敗します。別のポートを使用するか、競合しているサービスを停止しましょう。
2. ボリュームの権限問題
Linuxでは、マウントしたボリュームの所有者がroot(コンテナ内のUID)になり、ホスト側から編集できなくなることがあります。これを解決するには:
services:
app:
user: "${UID}:${GID}" # ホストのユーザーIDとグループIDを使用
3. コンテナ間の通信問題
サービス名がホスト名として使用できるため、コンテナ間で通信する場合は、IPアドレスではなくサービス名を使用します:
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydb
# ↑ ここでdbサービスを指定
まとめ
Docker Composeを使うことで、複雑な開発環境や本番環境を簡単に構築・管理できます。YAMLファイルで環境を宣言的に記述し、バージョン管理することで、「動くはずの環境」を共有できるようになります。チーム開発やCI/CDパイプラインの構築にも役立つツールなので、ぜひマスターしておきましょう。
正しく設計されたDocker Compose環境は、「どの環境でも同じように動作する」という Docker の最大の利点を最大限に活かすことができます。
コメント