🛳️

便利なcompose.yaml の機能

に公開

なんの記事?

Docker compose の管理・運用が楽になる細かい話のまとめ

compose の機能

volumes

コンテナとホストOS間でデータを共有する
volume の種類は3通りある

特徴 保存先 利用例 削除方法
ボリュームマウント Dockerによって管理される永続化ストレージ /var/lib/docker/volumes DBデータ、ログ docker volume rm <ボリューム名>
バインドマウント ホストOSのファイルシステム上の任意のディレクトリをコンテナにマウント 任意のホストディレクトリ 設定ファイル ホストOSから手動で削除
tmpfs マウント 一時的なストレージ メモリ内 機密情報、一時ファイル コンテナ停止時に自動削除
longhand.yaml
services:
  backend:
    ...
    volumes:
      # ボリュームマウントの定義
      # source: Dockerによって管理される名前付きボリュームの名前
      # target: コンテナ内のマウントパス
      - type: volume
        source: my_volume
        target: /app/data
        read_only: false

      # バインドマウントの定義
      # source: ホストOS上のパス (Docker Composeファイルからの相対パス)
      # target: コンテナ内のマウントパス
      - type: bind
        source: ./config
        target: /app/config
        read_only: true

      # tmpfs マウントの定義
      # target: コンテナ内のマウントパス
      # type: 'tmpfs' を明示的に指定
      # tmpfs: tmpfs に特化したオプションを指定
      - type: tmpfs
        target: /app/tmp_cache
        tmpfs:
          size: 100m # tmpfs の最大サイズを100MBに制限
          mode: '0755' # tmpfs のディレクトリ権限を 'drwxr-xr-x' に設定
volumes:
  # 'my_volume' の定義
  my_volume:
    driver: local

ややこしいことにvolumesの定義はlong syntax と short syntaxがあり、バインドマウントのショートシンタックスは挙動が異なる

  • long: ホストOS側にバインド元のフォルダが無ければエラー
  • short: ホスト側にバインド元のフォルダが無ければ自動生成
    • エラー無し&ログにも出ないので気が付きにくく、「なぜかフォルダがマウントされていない」状況に陥りやすい (私見)
shorthand.yaml
services:
  backend:
    volumes:
      # ボリュームマウントの定義
      - my_volume:/app/data

      # バインドマウントの定義
      - ./data:/app/config:ro
volumes:
  my_volume:
    driver: local

profile

各コンテナにプロファイルを付与し、起動するコンテナを up -d 時に制御する
ローカル環境では設定をこっち!開発環境ではこっち!という場合に有効かも

services:
  web:
    profiles: ["dev", "debug"]
    image: web

  backend:
    image: backend
    profiles: ["dev"]

  db:
    image: mysql

  phpmyadmin:
    image: phpmyadmin
    profiles: ["debug"]

起動方法は以下のように --profile を指定してあげる

  • up (profile指定なし): profile無しのdbが起動する
  • --profile dev up: profile無しのdbとweb, backendが起動する
  • --profile debug up: profile無しのdbとweb, phpmyadminが起動する
  • --profile debug --profile dev up: 全サービスが起動する
docker compose --profile <プロファイル名> up -d
COMPOSE_PROFILES=<プロファイル名> docker compose up -d

depends_on

コンテナ間の依存関係を明示する
コンテナAが起動した後にコンテナBを起動しなければいけない場合など有効かも

以下の例の場合

  • docker compose up -d を実行する
  • webとdbが起動する
  • dbが起動したら、apiが起動する
services:
  web:
    image: web

  api:
    image: api
    depends_on:
      - db

  db:
    image: db

dbの起動まで待機ではなく、ヘルスチェックの完了まで待ちたい場合は下記のようにする

  api:
    image: api
    depends_on:
      db:
        condition: service_healthy

healthcheck

コンテナ内のサービスが正常しているかを判断する

  • test: 正常性確認のために実行するコマンド
  • interval: test の実行頻度 (defalut: 30s)
  • timeout: test の実行結果待機時間 (defalut: 30s)
  • retries: test の再試行回数 (defalut: 3)
  • start_period: test の実行開始までの時間 (defalut: 0s)

healthcheckの結果は、 docker compose ps で確認可能

  • success: testコマンドの戻り値が"0"
  • unhealthy: testコマンドの戻り値が"1"
  • reserved: testコマンドの戻り値が"2" (使用禁止)
services:
  backend:
    ...
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 1m30s
      timeout: 10s
      retries: 3
      start_period: 40s

env_file

環境変数を外部ファイルから参照する
compose.yamlに記載したくない機密情報や環境ごとに切り替える必要のある設定を保有する場合に有効かも
※機密情報を .env に書いていいかは別の話

services:
  backend:
    ...
    environment:
      TZ: jst
    env_file:
      - ./.prod.env
      - ./.credential.env

entrypoint

コンテナ起動時に実行されるコマンドを定義する
DockerfileのENTRYPOINT命令と同じ役割を持つが、Docker Composeファイルで指定することで、Dockerfileを編集せずにエントリポイントを上書き可能

以下の場合、 $ /app/start.sh run がコンテナ上で実行される

services:
  backend:
    image: my-backend-image
    # コンテナ起動時に `/app/start.sh` を実行する
    entrypoint: ["/app/start.sh"]
    command: ["run"]

複数のyamlファイル

extends

複数のDocker Composeファイル間で共通の設定を共有するための機能
ベースとなるComposeファイルを指定し、その設定を継承・拡張することができる。
設定をDRYにでき、管理を容易にする

base.yaml
services:
  web:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
child.yaml
services:
  web:
    # base-compose.yaml#web 設定を継承
    extends:
      file: base-compose.yaml
      service: web
    # 開発環境向けの追加設定
    # --------------------------------------
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf  # 別のボリュームを追加
    environment:
      VAL: development

override

Docker Composeで複数のComposeファイルを使用する際に、設定を上書きするための機能

compose.yml をベースとして、compose.override.yml というファイルが存在する場合、

  1. composeは両ファイルを読み込み
  2. compose.yamlの設定をcompose.override.yml で上書き
  3. コンテナ起動
    となる

環境ごとの設定や一時的なデバッグ設定などを、元のComposeファイルを変更せずに適用できる

compose.yaml
services:
  web:
    image: my-web-app:latest
    ports:
      - "80:80"
    environment:
      APP_ENV: production
compose.override.yaml
services:
  web:
    # web ポートと環境変数を上書き
    ports:
      - "8080:80"
    environment:
      APP_ENV: development
    volumes:
      - ./app:/app

環境ごとのyaml

Docker Composeで複数のComposeファイルを使用する際に、環境ごとにyamlを作成しておくテクニック

  • prod環境へは、compose.prod.yaml を適用する
  • dev環境へは、compose.dev.yaml を適用する
  • ローカル環境へは、compose.yaml を適用する

下記のように -f でcomposeファイルを明示的に指定すればOK
overrideやextendsと組み合わせるとより構造的にファイル管理ができる
※やりすぎ注意

docker compose -f compose.prod.yaml up -d

参考

https://docs.docker.com/reference

Discussion