お問い合わせ
docker-compose.yml の書き方10選:インフラエンジニアが現場で使う構成をまとめた

docker-compose.yml の書き方10選:インフラエンジニアが現場で使う構成をまとめた

Jay-Piy wabi_motion

docker-compose.yml の書き方10選:インフラエンジニアが現場で使う構成をまとめた

docker-compose.ymlの書き方を10パターンで解説。最小構成から本番環境を意識したリソース制限・ログ設定まで、実際に動くYAMLをそのまま掲載。depends_onの落とし穴やポートマッピングの注意点もインフラエンジニアが実体験をもとに説明します。

docker-compose.yml の書き方10選:インフラエンジニアが現場で使う構成をまとめた

「docker-compose.ymlって、どう書けばいいの?」——最初にDocker Composeを触ったとき、ほぼ全員がここで止まります。YAMLのインデントにハマり、ポート番号を逆に書いて繋がらず、depends_onを信じすぎてDBより先にアプリが起動して接続エラー。思い当たる人は多いはずです。

この記事では、docker-compose.ymlの書き方を10パターンに分けて解説します。基本的な構文から本番環境を意識した構成まで、実際に動く形で紹介します。「とりあえず動く設定ファイルが欲しい」という方は、そのまま使ってください。


前提:YAMLの基本ルールを30秒で押さえる

docker-compose.ymlを書く前に、YAMLのルールを2つだけ覚えてください。これを知らないとインデントエラーで詰まります。

  • インデントはスペースのみ:タブはNG。スペース2つか4つで統一する
  • キーと値はコロンで区切るimage: nginx のように書く

別のエディタからコピペするとタブが混入することがあります。VSCodeなら「タブをスペースに変換」を設定しておくと安心です。


1. 最小構成:とにかく動かす

まずは最小構成から。Nginxを1コンテナ起動するだけのシンプルなパターンです。

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"

portsの書き方は「ホスト側:コンテナ側」の順です。ここを逆に書くと繋がりません。最初に必ずハマるポイントなので覚えておいてください。


2. バージョン指定:書くべきか書かざるべきか

古いドキュメントを見るとversion: '3.8'という記述が出てきます。これはComposeファイルのスキーマバージョンを指定するものですが、Docker Compose v2以降では不要になりました。

# 古い書き方(非推奨)
version: '3.8'
services:
  web:
    image: nginx:latest

# 現在の書き方(versionなしでOK)
services:
  web:
    image: nginx:latest

古いドキュメントを参考にしていると混乱します。公式ドキュメントは常に最新を確認してください。


3. imageとbuild:既存イメージか自前ビルドか

コンテナのベースを指定する方法は2つです。

# 既存イメージを使う場合
services:
  web:
    image: ubuntu:latest

# Dockerfileからビルドする場合
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile

contextはdocker-compose.ymlからの相対パスで指定します。「ビルドに必要なファイルがどこにあるか」を指定するイメージです。ここのパス指定を間違えると、ローカルのファイルがコンテナにコピーされずビルドが失敗します。


4. ポートマッピングと環境変数

実際のアプリケーションでよく使う設定です。

services:
  app:
    image: node:18
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=db
      - DB_USER=myuser
      - DB_PASSWORD=mypassword

パスワードなどの機密情報を直書きするのはNGです。.envファイルで管理しましょう。

# .envファイル
DB_PASSWORD=secret_value

# docker-compose.yml
environment:
  - DB_PASSWORD=${DB_PASSWORD}

.envファイルはGitにコミットしないこと。.gitignoreに追加してください。


5. ボリューム:データを消さないための設定

コンテナを削除するとデータも消えます。データベースのデータを残したい場合はボリュームが必須です。

services:
  db:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

ボリュームを設定し忘れてコンテナを削除し、DBのデータを全消しした経験があります。特にDB系のサービスには必ず設定してください。


6. ネットワーク:コンテナ間の通信を制御する

Docker Composeはデフォルトで同一ファイル内のコンテナが通信できるネットワークを作成します。明示的に定義したい場合はこのように書きます。

services:
  web:
    image: nginx:latest
    networks:
      - frontend

  app:
    image: node:18
    networks:
      - frontend
      - backend

  db:
    image: mysql:8.0
    networks:
      - backend

networks:
  frontend:
  backend:

本番環境では「DBはバックエンドネットワークにだけ繋ぐ」といった設計が必要です。全部同じネットワークに繋いだままだと、セキュリティ上の問題になります。


7. depends_on:起動順序を制御する(ただし過信するな)

DBが起動する前にアプリが起動して接続エラー——よくあるパターンです。depends_onで起動順序を制御できます。

services:
  app:
    build: .
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

重要:depends_onだけでは「コンテナが起動した」ことしか確認しません。「DBが接続を受け付ける状態になった」かどうかは別の話です。condition: service_healthyとhealthcheckを組み合わせて使うのが正解です。


8. 再起動ポリシー:落ちても自動で復旧させる

サーバー再起動時やコンテナのクラッシュ時に自動復旧させる設定です。

services:
  app:
    image: node:18
    restart: unless-stopped

主なポリシーはこちらです。

  • always:常に再起動(Dockerデーモン再起動時も含む)
  • on-failure:異常終了時のみ再起動
  • unless-stopped:手動停止以外は再起動

本番環境ではunless-stoppedalwaysを設定しておくのが基本です。


9. WebアプリとDBの連携:よく使う構成セット

Node.js + MySQLの構成例です。実際のプロジェクトでそのまま使える形で書きました。

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=db
      - DB_USER=myuser
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_NAME=mydb
    depends_on:
      db:
        condition: service_healthy
    networks:
      - app_network
    restart: unless-stopped

  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=myuser
      - MYSQL_PASSWORD=${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app_network

networks:
  app_network:

volumes:
  db_data:

アプリ側でDB接続のホスト名をlocalhostにすると繋がりません。サービス名(この例ではdb)をホスト名として指定してください。コンテナ間通信ではサービス名がホスト名になります。


10. 本番環境を意識した構成:セキュリティとリソース制限

本番環境では開発環境と異なる設定が必要です。最低限意識すべき項目を追加した例です。

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.prod
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PASSWORD=${DB_PASSWORD}
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    networks:
      - frontend
      - backend
    restart: unless-stopped

  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=myuser
      - MYSQL_PASSWORD=${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend
    restart: unless-stopped

networks:
  frontend:
  backend:

volumes:
  db_data:

追加しているポイントは3つです。

  • リソース制限deploy.resources):暴走したコンテナがサーバーのリソースを食い尽くすのを防ぎます
  • ログローテーションlogging):ログが溜まり続けてディスクがパンクするのを防ぎます
  • ネットワーク分離:DBをフロントエンドネットワークから切り離します

まとめ

今回紹介した10パターンをまとめます。

  • 最小構成でNginxを起動
  • versionキーは現在不要
  • imageとbuildの使い分け
  • ポートマッピングと環境変数(.envで管理)
  • ボリュームでデータを永続化
  • ネットワークでコンテナ間通信を制御
  • depends_on + healthcheckで起動順序を保証
  • 再起動ポリシーで自動復旧
  • WebアプリとDBの連携構成
  • 本番環境を意識したリソース制限とログ設定

最初から全部完璧に設定しようとしなくて大丈夫です。まず最小構成で動かして、必要な設定を一つずつ足していくのが一番の近道です。docker-compose.ymlは「動いてから育てる」ものです。

最後までお読みいただき、誠にありがとうございました。

ITエンジニアとして働きながら、AI・映像制作・AWSについて実体験をもとに発信しています。少しでも参考になれば嬉しいです。

他の記事もぜひ読んでみてください。