Tasuke Hubのロゴ

ITを中心に困っている人を助けるメディア

分かりやすく解決策を提供することで、あなたの困ったをサポート。 全ての人々がスムーズに生活できる世界を目指します。

Docker Composeで開発環境を簡単構築!初心者向け完全ガイド

記事のサムネイル

Docker Composeで開発環境を簡単構築!初心者向け完全ガイド

TH

Tasuke Hub管理人

東証プライム市場上場企業エンジニア

情報系修士卒業後、大手IT企業にてフルスタックエンジニアとして活躍。 Webアプリケーション開発からクラウドインフラ構築まで幅広い技術に精通し、 複数のプロジェクトでリードエンジニアを担当。 技術ブログやオープンソースへの貢献を通じて、日本のIT技術コミュニティに積極的に関わっている。

🎓情報系修士🏢東証プライム上場企業💻フルスタックエンジニア📝技術ブログ執筆者

Docker Composeとは何か?基本概念を理解しよう

Docker Composeは複数のDockerコンテナを定義し、実行するためのツールです。単一の設定ファイルで複数のコンテナからなる環境を管理できるため、開発環境の構築や運用が格段に効率化されます。

Docker Composeの主な特徴

Docker Composeには以下のような特徴があります:

  • YAML形式の設定ファイルdocker-compose.ymlというファイルに環境設定を記述します
  • 複数コンテナの一括管理:一度のコマンドで複数のコンテナを起動・停止できます
  • 環境変数のサポート.envファイルや環境変数を使って柔軟に設定できます
  • ネットワークの自動構築:コンテナ間のネットワークを自動的に構成します
  • ボリュームの永続化:データを永続化する仕組みも用意されています

DockerとDocker Composeの違い

Dockerが単一のコンテナを管理するのに対し、Docker Composeは複数のコンテナからなるアプリケーション全体を管理します。例えば、WebアプリとデータベースとRedisキャッシュを別々のコンテナで動かすような構成を一括で管理できます。

Docker:単一コンテナの実行と管理
Docker Compose:複数コンテナの定義と統合管理

なぜDocker Composeを使うべきか

開発環境構築で悩んだ経験はありませんか?「自分の環境では動くのに、同僚の環境では動かない」という問題は、Docker Composeで解決できます。主なメリットは:

  1. 環境の再現性が高い:誰がどこで実行しても同じ環境が立ち上がります
  2. セットアップが簡単docker-compose up一つで開発環境が起動します
  3. 本番環境との差異を最小化:開発と本番の環境差異を減らせます
  4. チーム全体で統一された環境:新メンバーの参加時も環境構築の手間が省けます

Docker Composeを使うことで、「環境構築に1日かかった」というような無駄な時間を削減し、本来の開発業務に集中できるようになります。

おすすめの書籍

docker-compose.ymlファイルの書き方

Docker Composeの核心部分であるdocker-compose.ymlファイルの書き方を見ていきましょう。このファイルでコンテナの構成やネットワーク、ボリュームなどを定義します。

基本的な構造

docker-compose.ymlファイルは通常、以下のような構造になっています:

version: '3'  # Docker Composeファイルのバージョン

services:     # 各サービス(コンテナ)の定義
  service1:   # サービス名(任意)
    image: nginx:latest  # 使用するDockerイメージ
    ports:
      - "8080:80"  # ポートのマッピング(ホスト:コンテナ)
    volumes:
      - ./html:/usr/share/nginx/html  # ボリュームのマッピング
    environment:
      - ENV_VAR=value  # 環境変数の設定

  service2:   # 別のサービス
    build: ./app  # Dockerfileからビルドする場合
    depends_on:
      - service1  # 依存関係を定義

networks:      # カスタムネットワークの定義(オプション)
  my-network:
    driver: bridge

volumes:       # 永続ボリュームの定義(オプション)
  my-volume:

主要な設定項目

services

アプリケーションを構成する各サービス(コンテナ)を定義します。よく使われる項目は以下の通りです:

  • image: 使用するDockerイメージを指定します
  • build: Dockerfileからイメージをビルドする場合に指定します
  • ports: ポートのマッピング(ホスト:コンテナ)を設定します
  • volumes: ボリュームのマッピングを設定します
  • environment: 環境変数を設定します
  • depends_on: サービス間の依存関係を定義します
  • restart: コンテナの再起動ポリシーを設定します(例:always, on-failure

実際の例:ウェブアプリとデータベース

version: '3'

services:
  web:
    image: node:16
    working_dir: /app
    volumes:
      - ./app:/app
    ports:
      - "3000:3000"
    command: npm start
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgres://postgres:password@db:5432/mydb

  db:
    image: postgres:14
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb

volumes:
  postgres-data:

この例では、NodeJSのウェブアプリケーションとPostgreSQLデータベースを連携させる環境を定義しています。volumesセクションで定義されたpostgres-dataは、データベースのデータを永続化するために使用されます。

環境変数の使用

.envファイルを作成すると、docker-compose.yml内で環境変数を使用できます:

# .envファイル
DB_PASSWORD=mysecretpassword
APP_PORT=3000
# docker-compose.yml
services:
  web:
    ports:
      - "${APP_PORT}:3000"
  
  db:
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}

これによって、機密情報をバージョン管理対象外にしたり、環境ごとに設定を変えたりできます。

あわせて読みたい

おすすめの書籍

実践例:Webアプリケーション開発環境の構築

ここでは実際に使えるWebアプリケーション開発環境の構築例をご紹介します。フロントエンド(React)、バックエンド(Node.js)、データベース(MongoDB)の3層構成の環境を作ってみましょう。

プロジェクト構成

まずは以下のようなディレクトリ構造を作成します:

my-web-app/
  ├── docker-compose.yml
  ├── frontend/
  │   ├── Dockerfile
  │   └── ...(Reactプロジェクトファイル)
  ├── backend/
  │   ├── Dockerfile
  │   └── ...(Node.jsプロジェクトファイル)
  └── .env

フロントエンドのDockerfile

# frontend/Dockerfile
FROM node:16-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

バックエンドのDockerfile

# backend/Dockerfile
FROM node:16-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 4000

CMD ["npm", "start"]

docker-compose.yml

version: '3'

services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    volumes:
      - ./frontend:/app
      - /app/node_modules
    environment:
      - REACT_APP_API_URL=http://localhost:4000
    depends_on:
      - backend

  backend:
    build: ./backend
    ports:
      - "4000:4000"
    volumes:
      - ./backend:/app
      - /app/node_modules
    environment:
      - MONGODB_URI=mongodb://mongo:27017/myapp
    depends_on:
      - mongo

  mongo:
    image: mongo:5.0
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db

volumes:
  mongo-data:

.envファイル

NODE_ENV=development
MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=example

実行手順

  1. 上記のファイル構成を作成します
  2. コマンドラインでプロジェクトディレクトリに移動します
  3. 以下のコマンドを実行します:
docker-compose up

これで以下の環境が立ち上がります:

ホットリロードの活用

上記の設定では、ボリュームマウントを使用しているため、ローカルでコードを変更するとコンテナ内にも即座に反映され、開発がスムーズに進みます。

volumes:
  - ./frontend:/app  # ローカルのfrontendディレクトリをコンテナの/appにマウント
  - /app/node_modules  # node_modulesディレクトリはコンテナ内のものを使用

この設定により、node_modulesはコンテナ内のものを使いつつ、ソースコードはローカルのものがリアルタイムで反映されます。

おすすめの書籍

ネットワークとボリュームの設定方法

Docker Composeの強力な機能の一つに、ネットワークとボリュームの管理があります。これらを適切に設定することで、コンテナ間の通信やデータの永続化を効果的に行えます。

ネットワークの設定

基本的なネットワーク

Docker Composeは、デフォルトで同じdocker-compose.ymlファイル内のサービス用にネットワークを作成します。サービス名をホスト名として使用でき、コンテナ間で通信できます。

services:
  web:
    image: nginx
    
  api:
    image: node:16
    # apiサービスからwebサービスに"http://web"としてアクセス可能

カスタムネットワークの作成

より細かく制御したい場合は、カスタムネットワークを定義できます:

services:
  web:
    networks:
      - frontend
  
  api:
    networks:
      - frontend
      - backend
  
  db:
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 外部からのアクセスを遮断

この例では、apiサービスは両方のネットワークに属し、webdbの間の通信を仲介できます。また、backendネットワークはinternal: trueとしているため、インターネットへの接続が遮断されます。

ネットワークドライバー

主なネットワークドライバーには以下のようなものがあります:

  • bridge: 同一ホスト内のコンテナ間通信に使用(デフォルト)
  • host: ホストのネットワークをそのまま使用
  • overlay: 複数のDockerホスト間でのコンテナ通信に使用
  • none: ネットワークを無効化
networks:
  my-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: my-custom-bridge

ボリュームの設定

ボリュームの種類

Docker Composeでは主に3種類のボリュームが使用できます:

  1. 名前付きボリューム: Docker管理の永続ボリューム
  2. バインドマウント: ホストのディレクトリをコンテナにマウント
  3. tmpfs/匿名ボリューム: メモリ上の一時的なファイルシステム

名前付きボリュームの使用

データベースなど永続化が必要なデータには名前付きボリュームを使用します:

services:
  db:
    image: postgres
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:
    # ボリュームの追加設定(オプション)
    driver: local
    driver_opts:
      type: none
      device: /path/on/host/postgres-data
      o: bind

バインドマウントの使用

開発中のソースコードなど、ホストで編集したファイルをコンテナに反映したい場合にはバインドマウントを使用します:

services:
  web:
    image: node:16
    volumes:
      - ./src:/app/src:ro  # ホストのsrcディレクトリを読み取り専用でマウント
      - ./public:/app/public

ボリュームの使用例

複数の使い分けをした実例を見てみましょう:

services:
  web:
    image: node:16
    volumes:
      # バインドマウント(開発用ソースコード)
      - ./src:/app/src
      # 匿名ボリューム(node_modulesをホストと共有しない)
      - /app/node_modules
      # 名前付きボリューム(キャッシュデータの永続化)
      - npm-cache:/root/.npm

  db:
    image: postgres
    volumes:
      # 名前付きボリューム(データベースファイルの永続化)
      - db-data:/var/lib/postgresql/data

volumes:
  npm-cache:
  db-data:

環境別の設定

本番環境と開発環境で設定を変えたい場合は、複数のdocker-composeファイルを用意し、オーバーライドする方法が便利です:

# 開発環境(デフォルト設定 + 開発用設定を適用)
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

# 本番環境(デフォルト設定 + 本番用設定を適用)
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

この方法で、ベースとなる設定を共有しつつ、環境ごとに必要な設定だけを上書きできます。

おすすめの書籍

関連記事

Docker Composeのコマンド一覧と使い方

Docker Composeを使いこなすためには、基本的なコマンドを理解することが重要です。ここでは、日常的に使用する主要なコマンドとその使い方を解説します。

基本的なコマンド

環境の起動

# フォアグラウンドで起動(ログが表示される)
docker-compose up

# バックグラウンドで起動
docker-compose up -d

# 特定のサービスだけ起動
docker-compose up -d web db

環境の停止

# Ctrl+Cでも停止できますが、以下のコマンドも使えます
docker-compose down

# コンテナとネットワークを削除するが、ボリュームは保持
docker-compose down

# コンテナ、ネットワーク、ボリュームをすべて削除
docker-compose down -v

# コンテナ、ネットワーク、イメージをすべて削除
docker-compose down --rmi all

状態確認

# 実行中のコンテナを確認
docker-compose ps

# すべてのコンテナを確認(停止中も含む)
docker-compose ps -a

# コンテナのログを表示
docker-compose logs

# 特定のサービスのログをフォロー(リアルタイム表示)
docker-compose logs -f web

その他のよく使うコマンド

# コンテナ内でコマンドを実行
docker-compose exec web npm test

# コンテナを再構築
docker-compose build

# 特定のサービスだけ再構築
docker-compose build web

# 設定ファイルの構文チェック
docker-compose config

# ビルド済みイメージを使わずに起動
docker-compose up --build

応用的な使い方

docker-compose.ymlの構文チェック

本番環境で問題が発生する前に、構文エラーをチェックしましょう:

docker-compose config

スケーリング

複数のサービスインスタンスを起動する場合:

# webサービスを3インスタンス起動
docker-compose up -d --scale web=3

この場合、ポートが重複しないように設定する必要があります:

services:
  web:
    ports:
      - "3000-3002:3000"  # ポート範囲を指定

サービスの再起動ポリシー

特に本番環境では、コンテナの再起動ポリシーを設定しておくと安心です:

services:
  web:
    restart: always  # 常に再起動
  
  db:
    restart: unless-stopped  # 明示的に停止された場合以外は再起動
  
  worker:
    restart: on-failure:5  # 失敗時に最大5回まで再起動

リソース制限

メモリやCPUの使用量を制限する場合:

services:
  web:
    deploy:
      resources:
        limits:
          cpus: '0.5'  # CPU使用率を50%に制限
          memory: 512M  # メモリ使用量を512MBに制限
        reservations:
          cpus: '0.25'  # 最低でもCPUの25%を確保
          memory: 256M  # 最低でも256MBのメモリを確保

開発ワークフロー

以下は、Docker Composeを使った一般的な開発ワークフローです:

  1. 環境の起動: docker-compose up -d
  2. コードの変更: ホスト側でコードを編集(ボリュームマウントにより即時反映)
  3. ログの確認: docker-compose logs -f
  4. テストの実行: docker-compose exec web npm test
  5. 環境の再構築(必要な場合): docker-compose build web && docker-compose up -d
  6. 開発終了時: docker-compose down

プロジェクト名の指定

デフォルトではディレクトリ名がプロジェクト名になりますが、明示的に指定することもできます:

# プロジェクト名を指定して起動
docker-compose -p myproject up -d

# または環境変数で指定
COMPOSE_PROJECT_NAME=myproject docker-compose up -d

これは、同じマシン上で複数の環境を並行して実行する場合に役立ちます。

実行環境の切り替え

開発環境と本番環境で設定を分けるケースは多いでしょう:

# 開発環境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# ステージング環境
docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d

# 本番環境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

このように、基本設定とオーバーライド設定を組み合わせて使用できます。

おすすめの書籍

トラブルシューティングと解決法

Docker Composeを使っていると、様々な問題に遭遇することがあります。ここでは、よくある問題とその解決策を紹介します。

コンテナが起動しない

問題: コンテナが起動せず、すぐに終了してしまう

$ docker-compose up
Creating network "myapp_default" with the default driver
Creating myapp_web_1 ... done
Creating myapp_db_1  ... done
Attaching to myapp_web_1, myapp_db_1
myapp_web_1 exited with code 1

解決策:

  1. ログを確認する

    docker-compose logs web
  2. Dockerfileを確認する

    • ENTRYPOINTやCMDが正しく設定されているか
    • 必要なファイルがコピーされているか
  3. 環境変数の確認

    • 必要な環境変数が設定されているか
    • .envファイルが正しく読み込まれているか
  4. コンテナ内で直接コマンドを実行してみる

    docker-compose run --rm web bash
    # コンテナ内で問題を調査

ポートの競合

問題: ポートが既に使用されているというエラーが表示される

ERROR: for web  Cannot start service web: driver failed programming external connectivity on endpoint myapp_web_1: Bind for 0.0.0.0:3000 failed: port is already allocated

解決策:

  1. 使用中のポートを確認する

    # macOSやLinuxの場合
    lsof -i :3000
    
    # Windowsの場合
    netstat -ano | findstr :3000
  2. 別のポートを使用する

    services:
      web:
        ports:
          - "3001:3000"  # ホスト側のポートを3001に変更
  3. 既存のプロセスを終了させる

    # PIDを特定してからkill
    kill $(lsof -t -i:3000)

ボリュームの問題

問題: データが永続化されない、またはパーミッションエラーが発生する

解決策:

  1. ボリュームの確認

    docker volume ls
    docker volume inspect myapp_db-data
  2. ボリュームの再作成

    docker-compose down -v  # ボリュームを削除
    docker-compose up -d    # 再作成して起動
  3. パーミッション問題の解決

    services:
      web:
        user: "1000:1000"  # ホストと同じUIDを使用

ネットワーク関連の問題

問題: コンテナ間で通信できない

解決策:

  1. ネットワークの確認

    docker network ls
    docker network inspect myapp_default
  2. コンテナ名での接続確認

    docker-compose exec web ping db
  3. depends_onの設定確認

    services:
      web:
        depends_on:
          - db

イメージのビルド問題

問題: イメージのビルドに失敗する

解決策:

  1. キャッシュを使わずにビルド

    docker-compose build --no-cache
  2. Dockerfileの修正

    • 命令の順序を最適化(キャッシュ効率を上げる)
    • マルチステージビルドの活用
  3. コンテキストの制限

    services:
      web:
        build:
          context: ./frontend
          dockerfile: Dockerfile

メモリ不足の問題

問題: メモリ不足でコンテナがクラッシュする

解決策:

  1. Dockerのリソース制限を確認・調整

    • Docker Desktopの設定で割り当てメモリを増やす
  2. サービスごとにメモリ制限を設定

    services:
      web:
        deploy:
          resources:
            limits:
              memory: 512M

その他の一般的なトラブルシューティング

  1. すべてクリーンアップして再起動

    docker-compose down --volumes --remove-orphans
    docker-compose up --build
  2. Docker Composeのバージョン確認

    docker-compose version
  3. Dockerのログを確認

    docker system info
    docker system events
  4. コンテナ内のシェルにアクセスして調査

    docker-compose exec service_name sh

一般的なベストプラクティス

トラブルを未然に防ぐために役立つ習慣:

  1. 小さな変更を段階的に行う:一度に多くの変更を加えると、問題の原因特定が難しくなります

  2. バージョンを明示的に指定する:イメージタグにはlatestではなく具体的なバージョンを指定しましょう

    services:
      db:
        image: postgres:14.2  # latestではなく、具体的なバージョンを指定
  3. ヘルスチェックを利用する:コンテナの状態を監視しましょう

    services:
      web:
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
          interval: 1m
          timeout: 10s
          retries: 3
  4. ログを適切に設定する:問題調査に役立ちます

    services:
      web:
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: "3"

以上のトラブルシューティング手法を活用すれば、Docker Composeで発生する一般的な問題のほとんどを解決できます。問題解決の過程で得た知識は、今後のコンテナ運用にも役立つでしょう。

おすすめの書籍

おすすめ記事

おすすめコンテンツ