Open5

Docker Compose 小技

mythrnrmythrnr

docker-compose.yml を書くときによくやることを書く

mythrnrmythrnr

環境変数を使う

プロキシだったり、ポート番号だったり、開発環境は様々

docker-compose.yml
version: "3.8"

services:
  app:
    build:
      context: "."
      args:
        REQUIRED_VALUE: "${REQUIRED_VALUE:?required}"
        HTTP_PROXY: "${HTTP_PROXY}"
        HTTPS_PROXY: "${HTTPS_PROXY}"
    image: "repo/name:${MYPJ_APP_TAG:-latest}"
    ports:
      - "${MYPJ_APP_PORT:-8080}:8080"

(リファレンス: Variable substitution

解説

環境変数はshellの変数展開を使えるので、空のときにエラーにしたりデフォルト値を指定したりできる。が、あまり複雑なことはしないに越したことはない

  • ${REQUIRED_VALUE:?required}REQUIRED_VALUE が空の場合に required とメッセージが出てエラーになる
  • ${MYPJ_APP_TAG:-latest}MYPJ_APP_TAG が空の場合に latest を返す
  • ${HTTP_PROXY} は任意入力だが、未指定の場合は警告が出るので、 docker-compose コマンドの出力結果をそのまま別のことに使っている場合は注意
mythrnrmythrnr

アンカーを使う

同じ設定が重なりがちな場合に使う

docker-compose.yml
version: "3.8"

services:
  app1:
    build:
      context: "."
      args: &args
        APP_VALUE: "app1"
        REQUIRED_VALUE: "${REQUIRED_VALUE:?required}"
        HTTP_PROXY: "${HTTP_PROXY}"
        HTTPS_PROXY: "${HTTPS_PROXY}"
    image: "repo/name:${MYPJ_APP_TAG:-latest}"
    logging: &logging
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "5"

  app2:
    build:
      context: "."
      args:
        <<: *args
        APP_VALUE: "app2"
    image: "repo/name:${MYPJ_APP_TAG:-latest}"
    logging: *logging
Extension fieldsを使う例

リファレンス: Extension fields

docker-compose.yml
version: "3.8"

x-logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "5"

services:
  app1:
    build:
      context: "."
      args: &args
        APP_VALUE: "app1"
        REQUIRED_VALUE: "${REQUIRED_VALUE:?required}"
        HTTP_PROXY: "${HTTP_PROXY}"
        HTTPS_PROXY: "${HTTPS_PROXY}"
    image: "repo/name:${MYPJ_APP_TAG:-latest}"
    logging: *logging

  app2:
    build:
      context: "."
      args:
        <<: *args
        APP_VALUE: "app2"
    image: "repo/name:${MYPJ_APP_TAG:-latest}"
    logging: *logging

解説

  • アンカーやエイリアスは、Docker Compose ではなく YAML の仕様
    GitHub Actions でも使えてくれ
  • &args で指定したものは *args で使える.
  • そのまま使う( *logging )他、マージして使うことも可能( <<: *args )。この例の場合、 *argsAPP_VALUEapp1 から app2 に上書きされる
  • パッと見でわかりやすい程度に抑える
mythrnrmythrnr

プロジェクト同士をつなぐ

マイクロサービス同士で連携したいようなときに使う。
事前に docker network create でネットワークを作成しておく

docker network create my_project_network
docker-compose.yml(一部)
# (略)

networks:
  my_project_network:
    external:
      name: "my_project_network"

# (略)
project A の docker-compose.yml
docker-compose.yml
version: "3.8"

services:
  app:
    image: "repo/project-a:latest"
    networks:
      - "my_project_network"

networks:
  my_project_network:
    external:
      name: "my_project_network"
project B の docker-compose.yml
docker-compose.yml
version: "3.8"

services:
  app:
    image: "repo/project-b:latest"
    expose:
      - 8080
    networks:
      my_project_network:
        aliases:
          - "app.project-b.local"

networks:
  my_project_network:
    external:
      name: "my_project_network"

解説

  • my_project_network に両方の project A の app と project B の app をつなぐ
  • この例では project A の app から project B の appapp.project-b.local というホスト名で接続できる( expose を忘れずに)
mythrnrmythrnr

Health Check をちゃんとやる

MySQL を例に

version: "3.8"

services:
  app:
    image: "alpine"
    command: echo "hello world"
    depends_on:
      database:
        condition: "service_healthy"
    networks:
      - "default"

  database:
    image: "mysql"
    expose:
      - 3306
    environment:
      MYSQL_ROOT_PASSWORD: "your-password"
    healthcheck:
      test:
        ["CMD-SHELL", "mysql -u root -pyour-password -e 'select 1;' || exit 1"]
      interval: "1s"
      timeout: "5s"
      retries: 30
      start_period: "3s"
    networks:
      - "default"

解説

  • 上記 services.database.healthcheck は「 3s 経ってから test のコマンドを最大 30 回実行する。1回ごとのタイムアウトは 5s で、次の実行まで 1s 待つ」という意味になる