はじめに

Dockerfileでイメージを作成し、コンテナを起動できるようになった。しかし、実際のアプリケーション開発では、Webサーバー、データベース、キャッシュサーバーなど複数のコンテナを連携させる必要があります。これらを個別のdocker runコマンドで管理するのは煩雑で、ミスも起きやすくなります。

Docker Composeは、複数のコンテナを1つの設定ファイル(compose.yaml)で定義し、一括で起動・停止できるツールです。本記事では、compose.yamlの基本構文からDocker Composeの主要コマンド、環境変数の管理方法まで体系的に解説します。この記事を読み終えると、以下のことができるようになります。

  • Docker Composeの役割とメリットを理解できる
  • compose.yamlでservices/volumes/networksを定義できる
  • docker compose up/down/logs/execなどの主要コマンドを使いこなせる
  • 環境変数を適切に管理できる

前提として、Dockerの基本コマンドとDockerfileの作成経験があることを想定しています。まだDockerの基本操作に慣れていない場合は、Docker基本コマンド完全ガイドを参照してください。

Docker Composeとは

Docker Composeは、マルチコンテナのDockerアプリケーションを定義・実行するためのツールです。YAMLファイル(compose.yaml)にアプリケーションのサービス構成を記述し、単一のコマンドで複数コンテナを一括管理できます。

なぜDocker Composeが必要なのか

複数コンテナを手動で管理する場合と、Docker Composeを使用する場合を比較してみましょう。

観点 手動管理(docker run) Docker Compose
起動コマンド コンテナごとに個別実行 docker compose up一発
設定の再現性 コマンド履歴に依存 compose.yamlで明文化
コンテナ間通信 手動でネットワーク設定 自動でネットワーク作成
依存関係管理 起動順序を手動で制御 depends_onで宣言的に定義
チーム共有 手順書が必要 compose.yamlを共有するだけ

例えば、WebアプリケーションとMySQLデータベースを起動する場合、手動では次のようなコマンドが必要です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# ネットワーク作成
docker network create myapp-network

# MySQLコンテナ起動
docker run -d --name mysql \
  --network myapp-network \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=myapp \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# Webアプリコンテナ起動
docker run -d --name webapp \
  --network myapp-network \
  -p 8080:80 \
  -e DATABASE_HOST=mysql \
  myapp:latest

Docker Composeを使えば、これらをcompose.yamlに定義し、docker compose up -dだけで起動できます。

Docker Composeのアーキテクチャ

Docker Composeの構成要素を図で理解しましょう。

flowchart TD
    subgraph ComposeYaml["compose.yaml"]
        services["services: コンテナ定義\n  web:\n  db:"]
        volumes["volumes: データ永続化\n  db-data:"]
        networks["networks: コンテナ間通信\n  backend:"]
    end
    ComposeYaml -->|"docker compose up"| DockerEngine
    subgraph DockerEngine["Docker Engine"]
        web["コンテナ: web"]
        db["コンテナ: db"]
        backendNetwork["ネットワーク: backend"]
        dbDataVolume["ボリューム: db-data"]
        web --- backendNetwork
        db --- backendNetwork
        db --- dbDataVolume
    end

compose.yamlの基本構文

compose.yamlは、Docker Composeの設定ファイルです。かつてはdocker-compose.ymlというファイル名が使われていましたが、現在はcompose.yamlが推奨されています。

ファイル名の優先順位

Docker Composeは以下の順序でファイルを検索します。

  1. compose.yaml(推奨)
  2. compose.yml
  3. docker-compose.yaml
  4. docker-compose.yml

基本構造

compose.yamlのトップレベル要素は以下の4つです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# プロジェクト名(オプション)
name: my-project

# サービス定義(必須)
services:
  web:
    image: nginx:latest
  db:
    image: postgres:18

# ボリューム定義(オプション)
volumes:
  db-data:

# ネットワーク定義(オプション)
networks:
  backend:

各トップレベル要素の役割は次のとおりです。

要素 説明 必須/オプション
name プロジェクト名。コンテナ名のプレフィックスに使用 オプション
services コンテナの定義。アプリケーションの各コンポーネントを記述 必須
volumes 名前付きボリュームの定義。データ永続化に使用 オプション
networks カスタムネットワークの定義。コンテナ間通信の制御に使用 オプション

シンプルなcompose.yamlの例

NginxとMySQLを使った最小構成の例を見てみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp

この設定でdocker compose up -dを実行すると、NginxコンテナとMySQLコンテナが起動し、自動的に同一ネットワークに接続されます。

servicesの定義方法

servicesはcompose.yamlの中核となる要素です。各サービスがDockerコンテナに対応し、コンテナの設定を詳細に定義できます。

主要な属性

サービス定義でよく使われる属性を紹介します。

image

使用するDockerイメージを指定します。

1
2
3
services:
  web:
    image: nginx:1.25-alpine

タグを省略するとlatestが使用されますが、本番環境では明示的にタグを指定することを推奨します。

build

Dockerfileからイメージをビルドする場合に使用します。

1
2
3
4
5
services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile

contextはビルドコンテキストのパス、dockerfileはDockerfileの名前を指定します。単純な場合は短縮形も使えます。

1
2
3
services:
  app:
    build: ./app

ports

ホストとコンテナ間のポートマッピングを定義します。

1
2
3
4
5
6
7
services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"           # ホスト8080→コンテナ80
      - "443:443"           # ホスト443→コンテナ443
      - "127.0.0.1:3000:3000"  # localhostのみバインド

形式は"ホストポート:コンテナポート"です。YAMLでは80:80のような形式が浮動小数点数と解釈される可能性があるため、クォートで囲むことを推奨します。

environment

コンテナ内の環境変数を設定します。マップ形式とリスト形式の2つの書き方があります。

1
2
3
4
5
6
7
8
services:
  db:
    image: postgres:18
    # マップ形式
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
1
2
3
4
5
6
7
8
services:
  db:
    image: postgres:18
    # リスト形式
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp

volumes

ボリュームマウントを定義します。詳細は後述の「volumesの定義方法」で解説します。

1
2
3
4
5
6
services:
  db:
    image: mysql:8.0
    volumes:
      - db-data:/var/lib/mysql        # 名前付きボリューム
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql  # バインドマウント

depends_on

サービスの依存関係を定義し、起動順序を制御します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
services:
  web:
    image: nginx:latest
    depends_on:
      - app
      - db

  app:
    build: ./app
    depends_on:
      - db

  db:
    image: postgres:18

この設定では、dbappwebの順で起動します。

より厳密な制御が必要な場合は、conditionを使ってサービスの状態を指定できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
services:
  web:
    image: nginx:latest
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:18
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

service_healthyを指定すると、依存先サービスのヘルスチェックが成功するまで待機します。

command

コンテナ起動時に実行するコマンドを上書きします。

1
2
3
4
services:
  app:
    image: node:20-alpine
    command: npm run dev

リスト形式でも指定できます。

1
2
3
4
services:
  app:
    image: node:20-alpine
    command: ["npm", "run", "dev"]

restart

コンテナの再起動ポリシーを設定します。

1
2
3
4
services:
  web:
    image: nginx:latest
    restart: unless-stopped
説明
no 再起動しない(デフォルト)
always 常に再起動
on-failure 異常終了時のみ再起動
unless-stopped 手動停止以外は再起動

実践的なサービス定義例

Webアプリケーション、API、データベースの3層構成の例です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    environment:
      - API_URL=http://api:8080
    depends_on:
      - api
    restart: unless-stopped

  api:
    build: ./api
    ports:
      - "8080:8080"
    environment:
      DATABASE_HOST: db
      DATABASE_PORT: 5432
      DATABASE_NAME: myapp
      DATABASE_USER: admin
      DATABASE_PASSWORD: secret
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:18
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "admin", "-d", "myapp"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  db-data:

volumesの定義方法

volumesは、コンテナのデータを永続化するために使用します。compose.yamlでは、トップレベルでボリュームを定義し、サービス内でマウントします。

ボリュームの種類

Docker Composeで使用できるボリュームには、名前付きボリュームとバインドマウントの2種類があります。

ボリュームの種類

┌─────────────────────────────────────────────────────────────────┐
│ 名前付きボリューム                                               │
│                                                                 │
│  ホスト                        コンテナ                          │
│  ┌────────────────────┐       ┌────────────────────┐           │
│  │ /var/lib/docker/   │       │                    │           │
│  │   volumes/         │  ───▶ │  /var/lib/mysql    │           │
│  │     db-data/       │       │                    │           │
│  └────────────────────┘       └────────────────────┘           │
│  Dockerが管理                                                    │
├─────────────────────────────────────────────────────────────────┤
│ バインドマウント                                                 │
│                                                                 │
│  ホスト                        コンテナ                          │
│  ┌────────────────────┐       ┌────────────────────┐           │
│  │                    │       │                    │           │
│  │  ./src             │  ───▶ │  /app/src          │           │
│  │                    │       │                    │           │
│  └────────────────────┘       └────────────────────┘           │
│  ユーザーが管理                                                  │
└─────────────────────────────────────────────────────────────────┘
種類 用途 記法例
名前付きボリューム データベースなどの永続データ db-data:/var/lib/mysql
バインドマウント ソースコードの同期(開発時) ./src:/app/src

名前付きボリュームの定義

名前付きボリュームは、トップレベルのvolumesで定義します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
services:
  db:
    image: postgres:18
    volumes:
      - db-data:/var/lib/postgresql/data
      - backup-data:/backup

volumes:
  db-data:
  backup-data:

ボリュームにオプションを指定することもできます。

1
2
3
4
5
6
7
volumes:
  db-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /data/postgres

バインドマウント

開発環境では、ホストのソースコードをコンテナにマウントして、コード変更を即座に反映させることが一般的です。

1
2
3
4
5
6
7
services:
  app:
    build: ./app
    volumes:
      - ./app/src:/app/src          # ソースコードをマウント
      - ./app/package.json:/app/package.json
      - /app/node_modules           # node_modulesはマウントしない(匿名ボリューム)

バインドマウントでは、パスが./../で始まる場合はホストのパス、そうでない場合は名前付きボリュームとして解釈されます。

短縮形と長形式

ボリュームマウントは短縮形と長形式の2つの書き方があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
services:
  app:
    volumes:
      # 短縮形
      - db-data:/var/lib/postgresql/data
      - ./config:/app/config:ro

      # 長形式
      - type: volume
        source: db-data
        target: /var/lib/postgresql/data
      - type: bind
        source: ./config
        target: /app/config
        read_only: true

長形式を使うと、より詳細なオプションを指定できます。

networksの定義方法

Docker Composeは、デフォルトでプロジェクト用のネットワークを自動作成します。カスタムネットワークを定義することで、サービス間の通信をより細かく制御できます。

デフォルトネットワーク

compose.yamlでnetworksを明示的に定義しない場合、Docker Composeは<プロジェクト名>_defaultという名前のブリッジネットワークを自動作成し、すべてのサービスをこのネットワークに接続します。

1
2
3
4
5
6
7
8
# networksを定義しない場合
services:
  web:
    image: nginx:latest
  db:
    image: postgres:18
# 自動的に同一ネットワークに接続され、
# webコンテナからは「db」というホスト名でdbコンテナにアクセス可能

カスタムネットワークの定義

複数のネットワークを定義して、サービス間の通信を分離できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
services:
  frontend:
    image: nginx:latest
    networks:
      - frontend-net

  api:
    build: ./api
    networks:
      - frontend-net
      - backend-net

  db:
    image: postgres:18
    networks:
      - backend-net

networks:
  frontend-net:
  backend-net:

この構成では、以下のような通信制御が実現されます。

ネットワーク分離の例

┌──────────────────────────────────────────────────────────────────┐
│                                                                  │
│   ┌──────────────┐                                               │
│   │  frontend    │                                               │
│   │  コンテナ     │                                               │
│   └──────┬───────┘                                               │
│          │                                                       │
│   ┌──────▼───────────────────────┐                               │
│   │     frontend-net             │                               │
│   └──────────────────┬───────────┘                               │
│                      │                                           │
│             ┌────────▼────────┐                                  │
│             │      api        │                                  │
│             │    コンテナ      │                                  │
│             └────────┬────────┘                                  │
│                      │                                           │
│   ┌──────────────────▼───────────┐                               │
│   │      backend-net             │                               │
│   └──────────────────┬───────────┘                               │
│                      │                                           │
│             ┌────────▼────────┐                                  │
│             │       db        │                                  │
│             │    コンテナ      │ ← frontendからは直接アクセス不可  │
│             └─────────────────┘                                  │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

frontendコンテナはapiにアクセスできますが、dbには直接アクセスできません。apiコンテナは両方のネットワークに接続されているため、frontendとdbの両方と通信できます。

ネットワークオプション

ネットワークに詳細なオプションを指定することもできます。

1
2
3
4
5
6
networks:
  backend-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16

サービス内でのネットワーク設定

サービスごとにネットワーク接続の詳細を設定できます。

1
2
3
4
5
6
7
8
services:
  api:
    image: myapi:latest
    networks:
      backend-net:
        aliases:
          - api-service
        ipv4_address: 172.28.0.10

aliasesを使うと、同一ネットワーク内の他のコンテナから別名でアクセスできるようになります。

Docker Composeの主要コマンド

Docker Composeの操作に使用する主要コマンドを紹介します。現在のDocker CLIでは、docker compose(スペース区切り)が標準です。

docker compose up

コンテナを作成して起動します。最も頻繁に使用するコマンドです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# フォアグラウンドで起動(ログが表示される)
docker compose up

# バックグラウンドで起動(デタッチモード)
docker compose up -d

# イメージを再ビルドして起動
docker compose up --build

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

主要なオプションは以下のとおりです。

オプション 説明
-d, --detach バックグラウンドで実行
--build 起動前にイメージをビルド
--force-recreate コンテナを強制的に再作成
--no-deps 依存サービスを起動しない
--scale SERVICE=NUM サービスのインスタンス数を指定

docker compose down

コンテナを停止し、コンテナとネットワークを削除します。

1
2
3
4
5
6
7
8
# コンテナとネットワークを削除
docker compose down

# ボリュームも削除
docker compose down -v

# イメージも削除
docker compose down --rmi all
オプション 説明
-v, --volumes 名前付きボリュームも削除
--rmi all すべてのイメージを削除
--rmi local カスタムタグのないイメージのみ削除
--remove-orphans compose.yamlに定義されていないコンテナも削除

docker compose logs

コンテナのログを表示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 全サービスのログを表示
docker compose logs

# 特定サービスのログを表示
docker compose logs web

# ログをフォロー(リアルタイム表示)
docker compose logs -f

# 最新100行のみ表示
docker compose logs --tail 100

# タイムスタンプを表示
docker compose logs -t
オプション 説明
-f, --follow ログをリアルタイムでフォロー
--tail N 最新N行のみ表示
-t, --timestamps タイムスタンプを表示
--no-color カラー出力を無効化

docker compose exec

実行中のコンテナ内でコマンドを実行します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# webコンテナでシェルを起動
docker compose exec web /bin/sh

# dbコンテナでpsqlを実行
docker compose exec db psql -U postgres

# 環境変数を指定して実行
docker compose exec -e DEBUG=1 app npm run test

# rootユーザーで実行
docker compose exec -u root web cat /etc/passwd
オプション 説明
-d, --detach バックグラウンドで実行
-e, --env 環境変数を設定
-u, --user 実行ユーザーを指定
-w, --workdir 作業ディレクトリを指定

docker compose ps

コンテナの状態を一覧表示します。

1
2
3
4
5
6
7
8
# 実行中のコンテナを表示
docker compose ps

# 停止中を含むすべてのコンテナを表示
docker compose ps -a

# 特定フォーマットで表示
docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"

docker compose start / stop / restart

コンテナのライフサイクルを制御します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 停止中のコンテナを起動
docker compose start

# コンテナを停止(削除はしない)
docker compose stop

# コンテナを再起動
docker compose restart

# 特定サービスのみ操作
docker compose restart web

stopdownと異なり、コンテナを削除しません。設定を変更せずに一時停止したい場合に使用します。

docker compose build

イメージをビルドします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 全サービスをビルド
docker compose build

# 特定サービスのみビルド
docker compose build web

# キャッシュを使わずビルド
docker compose build --no-cache

# ビルド引数を指定
docker compose build --build-arg VERSION=1.0

docker compose pull / push

イメージの取得・プッシュを行います。

1
2
3
4
5
6
7
8
# 全サービスのイメージを取得
docker compose pull

# 特定サービスのイメージを取得
docker compose pull db

# ビルドしたイメージをレジストリにプッシュ
docker compose push

コマンド比較表

主要コマンドの用途をまとめます。

コマンド 作成 起動 停止 削除 用途
up Yes Yes - - 初回起動、設定変更後の再起動
down - - Yes Yes 完全停止、クリーンアップ
start - Yes - - 停止中コンテナの起動
stop - - Yes - 一時停止
restart - Yes Yes - 再起動

環境変数の管理方法

Docker Composeでは、環境変数を柔軟に管理できます。データベースの接続情報やAPIキーなど、環境ごとに異なる設定を外部化することで、セキュリティと可搬性を向上させます。

環境変数の設定方法

1. compose.yaml内で直接指定

最もシンプルな方法ですが、機密情報には不向きです。

1
2
3
4
5
6
services:
  app:
    image: myapp:latest
    environment:
      NODE_ENV: production
      API_KEY: your-api-key

2. .envファイルを使用

プロジェクトルートに.envファイルを配置すると、自動的に読み込まれます。

1
2
3
4
# .env
POSTGRES_USER=admin
POSTGRES_PASSWORD=secret
POSTGRES_DB=myapp
1
2
3
4
5
6
7
8
# compose.yaml
services:
  db:
    image: postgres:18
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}

.envファイルは.gitignoreに追加し、Gitにコミットしないようにしましょう。

3. env_fileで外部ファイルを指定

サービスごとに異なる環境変数ファイルを読み込めます。

1
2
3
4
5
6
services:
  app:
    image: myapp:latest
    env_file:
      - ./common.env
      - ./app.env
1
2
3
4
5
6
# common.env
LOG_LEVEL=info
TZ=Asia/Tokyo

# app.env
DATABASE_URL=postgres://admin:secret@db:5432/myapp

複数ファイルを指定した場合、後から読み込まれたファイルの値が優先されます。

4. シェル環境変数を参照

ホストマシンの環境変数を参照することもできます。

1
2
3
4
5
services:
  app:
    image: myapp:latest
    environment:
      API_KEY: ${API_KEY}  # ホストの環境変数を参照
1
2
3
# シェルで環境変数を設定してから実行
export API_KEY=my-secret-key
docker compose up -d

環境変数の優先順位

同じ環境変数が複数箇所で定義されている場合、以下の優先順位で適用されます(上が高優先)。

  1. docker compose run -eで指定した値
  2. シェル環境変数
  3. .envファイル
  4. env_fileで指定したファイル
  5. compose.yamlのenvironmentで指定した値
  6. DockerfileのENVで指定した値

環境別設定の管理

開発環境と本番環境で異なる設定を使う場合、複数のファイルを組み合わせます。

1
2
3
4
5
6
# ディレクトリ構成
├── compose.yaml        # 共通設定
├── compose.dev.yaml    # 開発環境用
├── compose.prod.yaml   # 本番環境用
├── .env.dev            # 開発環境の環境変数
└── .env.prod           # 本番環境の環境変数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# compose.yaml(共通設定)
services:
  app:
    build: ./app

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

volumes:
  db-data:
1
2
3
4
5
6
7
8
9
# compose.dev.yaml(開発環境用オーバーライド)
services:
  app:
    volumes:
      - ./app/src:/app/src
    environment:
      NODE_ENV: development
    ports:
      - "3000:3000"
1
2
3
4
5
6
# compose.prod.yaml(本番環境用オーバーライド)
services:
  app:
    environment:
      NODE_ENV: production
    restart: always

複数ファイルを指定して起動します。

1
2
3
4
5
# 開発環境
docker compose -f compose.yaml -f compose.dev.yaml --env-file .env.dev up -d

# 本番環境
docker compose -f compose.yaml -f compose.prod.yaml --env-file .env.prod up -d

変数のデフォルト値

環境変数が未設定の場合のデフォルト値を指定できます。

1
2
3
4
5
6
7
services:
  app:
    environment:
      # 未設定の場合は「development」を使用
      NODE_ENV: ${NODE_ENV:-development}
      # 未設定または空の場合は「3000」を使用
      PORT: ${PORT:-3000}
構文 説明
${VAR:-default} 未設定の場合にdefaultを使用
${VAR-default} 未設定の場合にdefaultを使用(空文字は維持)
${VAR:?error} 未設定の場合にエラーメッセージを表示して終了
${VAR?error} 未設定の場合にエラーメッセージを表示して終了(空文字は許可)

機密情報の管理

パスワードやAPIキーなどの機密情報は、Docker Secretsを使用することを推奨します。ただし、Docker Secretsは主にDocker Swarmモード向けの機能です。ローカル開発では、.envファイルをGit管理外にする運用が一般的です。

1
2
3
4
# .gitignore
.env
.env.*
!.env.example

.env.exampleとしてテンプレートをリポジトリに含め、実際の値は各開発者がローカルで設定する方法が安全です。

1
2
3
4
5
# .env.example(リポジトリに含める)
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
API_KEY=

実践的なcompose.yaml例

ここまで学んだ内容を活用した実践的な構成例を紹介します。

Webアプリケーション + データベース + キャッシュ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
name: webapp

services:
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
    depends_on:
      - app
    restart: unless-stopped
    networks:
      - frontend

  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    environment:
      NODE_ENV: ${NODE_ENV:-production}
      DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
      REDIS_URL: redis://redis:6379
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped
    networks:
      - frontend
      - backend

  db:
    image: postgres:18
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./db/init:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "${DB_USER}", "-d", "${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    restart: unless-stopped
    networks:
      - backend

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    restart: unless-stopped
    networks:
      - backend

volumes:
  db-data:
  redis-data:

networks:
  frontend:
  backend:

この構成のポイントは以下のとおりです。

  • ネットワーク分離: frontendとbackendを分離し、nginxからdbへの直接アクセスを防止
  • ヘルスチェック: dbのヘルスチェックにより、確実に起動完了を待機
  • データ永続化: PostgreSQLとRedisのデータをボリュームで永続化
  • 環境変数: 機密情報は.envファイルで管理

まとめ

本記事では、Docker Composeの基本からcompose.yamlの書き方、主要コマンド、環境変数の管理方法まで解説しました。

Docker Composeを使用することで、以下のメリットが得られます。

  • 複数コンテナを1つのファイルで宣言的に定義できる
  • docker compose up一発でマルチコンテナ環境を構築できる
  • ネットワークやボリュームが自動的に管理される
  • 環境変数の外部化により、環境ごとの設定が容易になる

次のステップとして、以下の学習をおすすめします。

  • Docker Composeを使った実際のアプリケーション開発
  • Docker Swarmによるオーケストレーション
  • Kubernetesへの移行を見据えた設計

参考リンク