はじめに
Docker を使うときに必ず登場する docker-compose.yml。
しかし、実際には
-
どの項目が何をするのか?
-
必須/任意は?
-
どこまで覚えればいいのか?
がわかりにくい。
本記事では、docker-compose.yml の主要な設定項目を体系的に整理し、
初心者が理解すべき内容を厳選してまとめる。
1. 基本構造(最小の docker-compose.yml)
version: "3.9"
services:
app:
build: .
ports:
- "3000:3000"
docker-compose.yml の構成はシンプルで、
-
services … コンテナの一覧
-
volumes … 永続化
-
networks … ネットワーク定義
が主に登場する。
2. services の全主要項目
services が docker-compose の中心。
1コンテナに1つの service を書く。
services:
<サービス名>:
<設定項目>
3. 主な設定項目
3-1. build(イメージビルドの設定)
例
複数の Dockerfile を使い分けたいケース。
services:
api:
build:
context: ./api
dockerfile: Dockerfile.prod
args:
NODE_ENV: production
build は Dockerfile から新しくイメージをビルドする設定 です。
この例では、./api ディレクトリをコンテキスト(ビルド対象)として、Dockerfile.prod を使って production 用のイメージをビルドしています。
args は Dockerfile のビルド時引数(ここでは NODE_ENV=production)
ポイント
- context は ビルド対象 directory 全体が送信される
→ .dockerignore を正しく設定しておかないと巨大なコンテキストを送ることになる
→ ビルドが 10〜30秒遅くなる原因に多い - dockerfile: のパスは context からの相対パス
3-2. image(既存イメージを使う)
例
CI/CDパイプラインでビルド済みイメージを pull する。
services:
api:
image: ghcr.io/myteam/api:1.0.3
image は 既存の Docker イメージを指定してコンテナを作る設定 です。
この例では、GitHub Container Registry の ghcr.io/myteam/api:1.0.3 を pull してコンテナを作成しています。
ポイント
- build: と image: を同時に書くと どちらが使われるか混乱する
→ compose v2 では build: が優先
→ ただし push/pull の挙動は image: が使われる - タグを固定しないと再現性が壊れる
→ "latest" は使わない方が良い(実務では事故起こしがち)
3-3. container_name(手動管理する時に必要)
例
自社ツールでローカル環境のコンテナに固定名称で接続したい場合。
services:
redis:
image: redis:7
container_name: redis-local
container_name は コンテナに手動で名前を付ける設定 です。
ポイント
- 複数環境(local/stg/prod)で名前が衝突しやすい
- Docker Compose v2 では container_name 使用が推奨されないケースがある
→ 大規模プロジェクトでは container_name はなるべく避ける
3-4. ports(ポート公開)
例
ローカルで Next.js を 3000 番で動かす場合。
services:
frontend:
ports:
- "3000:3000"
ports は コンテナのポートをホストに公開する設定 です。
この例では、コンテナ内のポート 3000 を、ホストの 3000 にマッピングしています。
ブラウザで http://localhost:3000 にアクセスすると、コンテナ内の Next.js アプリに接続できます。
ポイント
- "3000:3000" は文字列で書かないと YAML が勝手に整数扱い
- "8080:80" の左側がホスト、右側がコンテナ
→ 逆に書いて動かない事例が多い
3-5. environment(環境変数)
例(DB接続)
environment:
DB_HOST: db
DB_USER: root
DB_PASS: password
environment は コンテナ内で使う環境変数を直接指定する方法 です。
この例では、DB 接続情報をコンテナに渡しています。
コンテナ内では process.env.DB_HOST(Node.js)や $DB_HOST(bash)として参照可能です。
ポイント
- 値にスペースがあると YAML が壊れる
→ スペースが入る場合は、"hello world" と 必ずダブルクォーテーションで囲む - シークレット情報を yml に直接書くのは避ける
→ .env や secrets manager を使うべき
3-6. env_file(.env読み込み)
例
env_file:
- .env
env_file は コンテナに環境変数を読み込ませる設定 です。
この例では、同じディレクトリにある .env ファイルから環境変数を読み込みます。
ポイント
- .env を Git に push してはいけない(事故例多い)
- env_file と environment: の同名キーはenvironment: が優先
3-7. volumes(永続化)
例(MySQL)
volumes:
- db_data:/var/lib/mysql
volumes は コンテナのデータを永続化するための設定 です。
この例では、MySQL のデータディレクトリ /var/lib/mysql を
Compose 側で定義した 永続ボリューム db_data に保存しています
ポイント
- コンテナ破棄だけでは消えない
→ docker volume rm db_data が必要(ボリュームの削除) - permission 問題が起きやすい
→ コンテナの UID / GID とホスト側の UID / GID が異なると書き込みできない
3-8. working_dir(作業ディレクトリ)
例
working_dir: /app
working_dir は コンテナ内でコマンドを実行する際の作業ディレクトリ を指定する設定です。
ポイント
- Dockerfile の WORKDIR を上書きする
→Dockerfile で WORKDIR が設定されていても、Compose の working_dir を書くと 無効化される - ホストのパスをマウントすると WORKDIR が存在しない問題 が起きる
→ mkdir app を忘れがち
3-9. command(CMD の上書き)
例
開発環境だけ nodemon を使いたい。
command: ["npm", "run", "dev"]
command は コンテナ起動時に実行するコマンドを指定する設定 です。
ポイント
- command: は Dockerfile の CMD を上書き
→Dockerfile で CMD が設定されていても、Compose の command を書くと 無効化される
3-10. entrypoint(ENTRYPOINT の上書き)
例
アプリ起動前に初期化スクリプトを走らせる。
entrypoint: ["./docker-entrypoint.sh"]
entrypoint は コンテナ起動時に必ず実行されるコマンド を指定する設定です。
ポイント
- 上書きすると Dockerfile の ENTRYPOINT が完全に無効になる
3-11. depends_on(依存順序)
例
depends_on:
- db
- backend
depends_on は コンテナの起動順序を指定する設定 です。
ポイント(超重要)
-
db が READY になるまで待たない
→ あくまで「起動を開始させる順序」
本当に待ちたい場合は healthcheck と組み合わせる:
version: "3.9"
services:
# バックエンドサービス
backend:
# 省略
depends_on:
db:
condition: service_healthy # DBのヘルスチェックがOKになるまで待機
# データベースサービス
db:
# 省略
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
3-12. healthcheck(ヘルスチェック)
例
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000"]
interval: 10s
timeout: 2s
retries: 3
healthcheck は コンテナが正常に動作しているかを Docker が自動で確認する仕組みです。
この設定はざっくり言うと、
- test:どのコマンドでコンテナの健康状態を確認するか
- interval:チェックする間隔(10秒ごと)
- timeout:コマンドがタイムアウトするまでの時間(2秒)
- retries:失敗を何回許容するか(3回まで)
を決めています。
ポイント
- curl がイメージに入っていないことがある
→ Alpine、node イメージは特に注意 - healthcheck に失敗すると restart ループに陥る
→ アプリの起動順序が壊れる
3-13. restart(再起動ポリシー)
例
restart: unless-stopped
restart は コンテナが停止したときの自動再起動のルール を指定する設定です。
これは
- エラーで落ちたら自動再起動する
- ただしユーザーが「明示的に停止した場合(docker stop)」は再起動しない
という意味になります。
指定できる値
| 値 | 意味 |
|---|---|
| no(デフォルト) | 自動再起動しない |
| on-failure | 異常終了(exit code ≠ 0)のときだけ再起動 |
| always | どんな終了でも必ず再起動する |
| unless-stopped | always だが「手動停止したときだけ再起動しない」 |
ポイント
- always は Ctrl+C してもすぐ復活するためローカルでバグる
- ローカル開発では基本 no の方が安全
3-14. logging(ログ設定)
例
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
logging は コンテナのログの取り扱い方を指定する設定 です。
これは “ログを JSON 形式のファイルで保存し、サイズを制限する” という意味になります。
ポイント
- ログが肥大化してディスク圧迫する事故が多い
→ max-size / max-file の設定は必須級- max-size: "10m"
「ログ1ファイルの最大サイズは 10MB」
10MB に達したらファイルをローテーションします。 - max-file: "3"
保持するファイルは最大3つまで
- max-size: "10m"
3-15. networks(ネットワーク構成)
例
networks:
- backend
networks は コンテナ同士がどのネットワークで通信するかを決める設定 です。
上記の例はbackendというネットワークに参加させるという意味です。
services:
frontend:
networks:
- frontend
backend:
networks:
- backend
- frontend
db:
networks:
- backend
上記のように記述されている場合、下記の挙動になります。
- frontend と backend は通信できる
→ 同じ frontend ネットワークに属しているため - backend と db は通信できる
→ 同じ backend ネットワークに属しているため - frontend と db は通信できない(通常はそれが安全)
→ 別ネットワークなので名前解決不可
ポイント
- 特に指定しないと デフォルトブリッジネットワーク(Dockerが自動で作成する共通の部屋)に接続される
- 異なるネットワークにいるとサービス名で resolve できない
→ 「DBに接続できない」の原因に多い
最後に
今回は、これまでふわっと理解のまま触ってきた docker-compose.yml の主要な項目を整理してみました。
初めて触ると設定項目が膨大に見えますが、実際に開発でよく使うのはごく一部で、ふわっと理解でもなんとか対応できます。
ただ、ヘルスチェックの結果を監視して起動順序を強制する設定がうまくできておらず、何度も起動コマンドを叩いて順序が偶然正しかったときだけ正常に動作する、という経験もありました。
今回整理したことで、docker-compose をもう少し正しく使いこなせるよう精進していきたいと思います。