+ 作る
図を読み込んでいます…
1 / 5
Dockerを理解しよう / 全3章

第3章 Docker を理解しよう:docker compose で複数の箱をまとめる

発行
かえで
版
第2版
改訂
分量
5コマ・2,095字

Web・DB・キャッシュと箱が増えたとき、docker run を何本も打つ代わりに compose.yaml に宣言としてまとめる。run のオプションが YAML の項目にそのまま対応すること、サービス名がホスト名になるネットワーク、up と down、そして Dockerfile・イメージ・コンテナ・ボリューム・レジストリ・compose がどうつながるかの全体像。

アプリは1つの箱では終わらない

ここまでで、1つのコンテナを作って動かすところまで来ました。でも実際のアプリは、Web アプリ本体に加えてデータベース、キャッシュ、場合によっては Web サーバーやジョブ実行の仕組みなど、複数の部品で成り立っています。それぞれを別のコンテナとして動かすのが Docker の流儀です。1つの箱に全部詰めるより、部品ごとに箱を分けたほうが、差し替えも更新も楽だからです。

ただ、箱が3つになると docker run も3本になります。それぞれのオプションを覚え、起動の順番を守り、web から db へどう繋ぐかを設定する。手で打つのは面倒で、人によって打ち方がずれると「自分の環境では動くのに」が再発します。これを解決するのが docker compose です。

  • アプリは1つの箱では終わらない
  • docker run -d --name db -e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data postgres:16
  • docker run -d --name cache redis:7
  • docker run -d --name web -p 3000:3000 -e DATABASE_URL=postgres://db:5432/app --network mynet myapp:1.0
  • web myapp:1.0 → :3000
  • db postgres:16 + ボリューム
  • cache redis:7
  • 毎回3本のコマンドを覚える? 起動順は? web から db へどう繋ぐ? → これを1つのファイルにまとめるのが docker compose
  • web + DB + キャッシュ。コンテナが増えると、run のオプションを手で打つのは辛い

compose.yaml:run の指示書をまとめて書く

docker compose は、複数コンテナの構成を1つの YAML ファイル(compose.yaml、古い名前では docker-compose.yml)に書いて、1コマンドでまとめて上げ下げする道具です。

図を見ると、前のアニメモで見た docker run のオプションが、そのまま YAML の項目に対応しているのが分かります。使うイメージは image:、自分でビルドするなら build:、-p は ports:、-e は environment:、-v は volumes:。services: の下に並ぶ db・cache・web が、それぞれ1つのコンテナになります。

つまり compose.yaml は「run の指示書を複数まとめたもの」です。手で打っていたことを宣言として書き、ファイルごと Git に入れて共有できる。だからチーム全員が同じ構成で、同じコマンド1つで環境を立ち上げられます。

  • compose.yaml:run のオプションがそのまま YAML の項目になる
  • services:  db:   image: postgres:16   environment:    POSTGRES_PASSWORD: secret   volumes:    - pgdata:/var/lib/postgresql/data
  • run のオプション → compose の項目
  • postgres:16(イメージ名) → image:
  • docker build . → build: .
  • cache:   image: redis:7  web:   build: .   ports:    - "3000:3000"
  • -p 3000:3000 → ports:
  • -e KEY=VALUE → environment:
  • -v pgdata:/var/... → volumes:
  • environment:    DATABASE_URL: postgres://db:5432/app   depends_on: [db, cache] volumes:  pgdata:
  • --name web → サービス名(web:)がそのまま名前に
  • 起動の順番 → depends_on:
  • 1サービス = 1コンテナ。手で打っていたことを 宣言として書き、ファイルごと Git で共有できる
  • compose.yaml は「run の指示書」を複数まとめたもの。読めば構成が全部分かる

ネットワーク:サービス名がそのままホスト名になる

compose ならではの便利さが2つあります。1つ目がネットワークです。compose は up のときに専用の仮想ネットワークを自動で作り、全サービスをそこに繋ぎます。そしてサービス名がそのままホスト名になります。web のコンテナから見ると、db というホスト名で PostgreSQL に、cache というホスト名で Redis に届きます。

ここでよく戸惑うのが、設定ファイルに書くホスト名が localhost ではないことです。同じ PC の上で動いていても、コンテナはそれぞれ別のネットワーク空間に居るので、web にとっての localhost は web 自身です。DB に繋ぐなら db と書きます。

2つ目が depends_on で、起動の順番を指定できます。web は db と cache が立ち上がってから起動する、と書いておけます。また ports: を書いていないサービスは外から見えません。図の db と cache は web からだけ届き、ブラウザからは直接触れない。これが自然に守られるのも compose の利点です。

  • ネットワーク:サービス名がそのままホスト名になる
  • compose が自動で作る専用ネットワーク(myproject_default)
  • db (postgres:16)
  • インターネット
  • web (myapp:1.0)
  • db:5432
  • localhost:3000
  • cache:6379
  • cache (redis:7)
  • db と cache は ports: を書いていないので外からは見えない(web からだけ届く)
  • 設定ファイルに書く DB のホスト名は localhost ではなく db。 同じ PC 上でも、コンテナごとに別のネットワーク空間に居るから
  • サービス名で呼び合える。localhost ではなく db・cache と書く

up と down:まとめて上げ、まとめて下ろす

日常的に使うのは、ほぼ2つのコマンドです。docker compose up -d で、必要ならイメージをビルドまたは pull し、ネットワークを作り、depends_on の順にコンテナを起動します。docker compose down で、コンテナとネットワークを消します。ボリュームは残るので、翌日 up すれば DB のデータはそのままです。

ログは docker compose logs -f web のようにサービス名で絞って見られ、docker compose exec web sh で動いているコンテナの中に入ってコマンドを打てます。Dockerfile や依存を変えたときは up -d --build でビルドし直します。

前のアニメモで見た「環境とソースを分ける」考え方は、compose でも同じです。volumes: に .:/app のようにソースのマウントを書いておけば、コードを直すたびに up し直す必要はなく、ビルドし直すのは Dockerfile や依存が変わったときだけです。

  • up と down:まとめて上げ、まとめて下ろす
  • docker compose up -d
  • 必要なら build / pull → ネットワーク作成 → depends_on の順に起動
  • docker compose logs -f web
  • ログを見る(サービス名で絞れる)
  • docker compose exec web sh
  • 動いているコンテナの中に入ってコマンドを打つ
  • docker compose down
  • コンテナとネットワークを消す。ボリュームは残る(-v を付けると消える)
  • docker compose up -d --build
  • Dockerfile や依存を変えたときはビルドし直して上げる
  • ソースをマウント(volumes: - .:/app)していれば、コードの変更は up し直さなくても反映される。 --build が要るのは Dockerfile や依存を変えたときだけ
  • 日常は up -d と down の2つ。データはボリュームに居るので down しても消えない

全体像:5つの言葉でつながる

3つのアニメモで見てきたことを1枚にまとめます。Dockerfile を build するとイメージができ、イメージを run するとコンテナが動く。コンテナの中のデータはボリュームに逃がし、外との通信はポート公開で開ける。複数のコンテナをまとめて扱うのが compose で、イメージを配るのがレジストリ。

そして一貫して効いていた考え方が「環境とソースを分ける」でした。環境(ランタイムと依存)は変わる頻度が低いのでイメージに焼いて配る。ソースは頻繁に変わるので、開発中はマウントし、本番向けには最後の薄い層として COPY する。会社のイメージはプロダクトそのものなので非公開レジストリに置き、CI も本番も手元も同じイメージを pull して使う。

実際のプロジェクトで迷ったら、Dockerfile と compose.yaml と CI の設定ファイルを開いて、「どのイメージを、どこから、どう使っているか」をこの5つの言葉に当てはめてみてください。たいていの疑問はそこで解けます。

  • 全体像:build → run、まとめる compose、配るレジストリ
  • compose でまとめる
  • Dockerfile
  • build
  • イメージ
  • run
  • コンテナ
  • -p
  • 外の世界(ブラウザ・他サービス)
  • push
  • pull
  • -v
  • レジストリ
  • ボリューム
  • ・環境(ランタイム + 依存)はイメージに、ソースは COPY かマウントで ・消えて困るデータはボリュームに、外との通信はポート公開で ・会社のイメージは非公開レジストリへ。CI も手元も同じものを pull する
  • Docker は「環境を箱に詰めて、同じ箱をどこでも開く」道具。この5つの言葉で全部つながる

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]