🐁

Compose V2のdocker composeファイルの書き方メモ

2024/05/14に公開


それなりに本格的にDocker Composeを使うことになったので調べていると、知っている知識から少し変わっていました。それらも含め近頃のCompose V2とやらは大体こういう風に書くらしいという個人メモです。詳細は公式をご覧ください。公式に書いていないことは手元の環境で検証したりしてますが保証はしません。

前提

$ docker --version
Docker version 26.1.2, build 211e74b
$ docker compose version
Docker Compose version v2.27.0
  • docker compose コマンドを使用する
    • docker-compose (Docker Compose V1)は既にEOL
  • ファイル名には compose.yaml を使用する

トップレベル項目

version

obsoleteの模様。これが書きたかった。deprecatedではなくobsoleteなのが驚いた。

name

コンテナ名等の接頭辞を指定できる。
例:

compose.yaml
name: suffix
services:
  app:
  ...
volumes:
  app-volume:
networks:
  app-network:
  • コンテナ名: suffix-app-1
  • ボリューム名: suffix_app-volume
  • ネットワーク名: suffix_app-network

services

おなじみの項目。以下の子項目の記述は極一部のため詳細は公式参照

  • configs, secrets
    • トップレベルの同項目で定義した内容をvolumesの代わりにマウント可能
      • これら項目を使用する場合、対応するトップレベルconfigs, secretsが必須
    • デフォルトでは読み取り専用(0444)としてマウントされる
      • modeで指定しても書き込みできるようにはならない
      • そのためマウントした情報が書き換わらないことを保証できる
    • ファイル,ディレクトリどちらもマウント可能
      # short syntax, mounted on each comment
      services:
        app:
          configs:
            - config1  # /config1
            - config2  # /config2
          secrets:
            - secret1  # /run/secrets/secret1
            - secret2  # /run/secrets/secret2
      
      # long syntax, mounted on the path of target
      services:
        app:
          configs:
            - source: config1  # /run/config1
              target: /run/config1
          secrets:
            - source: secret1  # /tmp/secret1
              target: /tmp/secret1
              mode: 0400
      
  • extends
    • 1つのサービス内で複数のextendsを定義することはできない
      • 各サービスの共通部分をよく使う定義の組み合わせで表現したかったができないらしい
  • ports
    • 値はダブルクオーテーションで囲まれるべき
      • :区切りで数値を書くとyamlパーサーに60進数として認識される (それを避けるため)
      • ダブルクオーテーション無しで60未満のポートを1つだけ書くと以下で起動できない
        • validating compose.yaml: services.app.ports must be a list
  • volumes
    • 名前付きボリュームを使用する場合、トップレベルvolumesが必須
    • ./myvol:/run/myvol:roのようにすると読み取り専用になる
    • Long syntaxの場合、typetmpfs を指定することでメモリ領域をマウント可能
      • npipe を指定することでnamed pipeが使用できるらしいが、以下のエラーが出た
        • Error response from daemon: invalid mount config for type "npipe": mount type unknown
  • container_name
    • トップレベルのname項目を無視して指定の名前にする
  • init
  • shm_size
  • mem_limit
    • 指定しなければ制限なしになるらしい
    • Macでは指定しなくても2GBの制限があるらしい
    • Windowsでも制限があるらしい

networks

servicesnetworksで使用するネットワークを定義する。詳細は公式参照。基本的に docker compose up で作成され、docker compose down で削除される。(他で使用中の場合は削除されない)

  • driver
    • bridgehostを指定する
  • external
    • trueだと自動作成,削除されない
      • docker compose up の時に指定の名前のネットワークがない場合エラー
  • name
    • トップレベルのname項目を無視して指定の名前にする

volumes

servicesvolumesで使用する名前付きボリュームを定義する。詳細は公式参照。基本的にdocker compose up で作成され、自動で削除はされない。

  • external
    • trueだと自動作成されない
      • docker compose up の時に指定の名前のボリュームがない場合エラー
  • name
    • トップレベルのname項目を無視して指定の名前にする

configs

servicesconfigsで使用するマウント元を定義する。詳細は公式参照

services:
  app:
    configs:
      - config1  # like ./foo:/config1:ro
      - config2  # if content has ${VAR}, able to change dinamicaly by .env file

configs:
  config1:
    file: ./foo
  config2:
    content: |
      value1=foobar
      value2=enable

secrets

servicessecretsで使用するマウント元を定義する。詳細は公式参照

services:
  app:
    secrets:
      - source: secret1  # like ./foo/bar.txt:/tmp/secret1:ro
        target: /tmp/secret1

secrets:
  secret1:
    file: ./foo/bar.txt

その他

個人的テンプレート

compose.yaml
name: prefix
services:
  srv1:
    # container_name: specific-name
    image: ubuntu:latest
    build:
      context: .
      dockerfile: Dockerfile
      dockerfile_inline: |
        FROM ubuntu:latest
        ARG DEBIAN_FRONTEND=noninteractive
        RUN apt update && apt install -y ca-certificates && rm -rf /var/lib/apt/lists/*
    depends_on:
      - db
      - srv2
    init: true
    restart: unless-stopped
    shm_size: 128mb #1gb
    # mem_limit: 256mb
    hostname: myhost
    # network_mode: "host" #or "none"
    networks:
      - mynet1
    ports:
      - "8080:80"
    environment:
      - TZ=Asia/Tokyo
    env_file: ./srv1.env #`.env` is only set defaults, so not preffered
    configs:
      - source: srv1-config
        target: /run/entrypoint.sh
      - source: srv1-config-dir
        target: /srv/conf.d
    secrets:
      - source: srv1-cert
        target: /srv/key.pem
      - source: srv1-cert-dir
        target: /srv/cert
    volumes:
      - /var/log/srv1:/srv/log
      - ./memo.txt:/srv/memo.txt:ro
    # user: myuser
    working_dir: /srv
    command: /bin/sh -c "/run/entrypoint.sh"
  srv2:
configs: #readonly
  srv1-config:
    file: ./setup.sh
  srv1-config-dir:
    file: ./srv1.d
secrets: #readonly
  srv1-cert:
    file: ./private/srv1.key
  srv1-cert-dir:
    file: ./cert
networks:
  mynet1:
    # name: specific-name

compose.yamldocker run -it的な

  • docker run -itと同じようなことをcompose.yamlを使って実行する方法
    1. 以下をservicesappに追加する
    tty: true
    stdin_open: true
    command: /bin/bash
    
    1. docker compose run --rm appで実行する

コマンドメモ

  • docker compose up -d : バックグラウンドでコンテナ群を起動
  • docker compose stop : コンテナ群を停止 (削除無し)
  • docker compose down : コンテナ群を停止 (関連オブジェクト削除)
  • docker compose build --no-cache [SERVICE_NAME] : コンテナを新規ビルド
  • docker compose pull [SERVICE_NAME] : コンテナのイメージを更新
  • docker exec -it [CONTAINER_NAME] sh : 指定コンテナ内をshellで確認

参考文献

Discussion