1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Docker Composeのextendsでcompose.yamlを共通化して見やすくする

Last updated at Posted at 2023-03-12

extendsについて

Compose Specの機能として extends というものがあり、この機能を使うとComposeファイル内の別サービスを拡張し、オプションで設定を上書きするこができます。

例えば下記のような compose.yaml があったとして、 webadmin の差分が ports しかない
という場合に extends をうまく活用することで、 compose.yaml の見た目をスッキリさせることができます。

extends 活用前

# compose.yaml

services:
  web:
    image: php:8.2.3-apache
    volumes:
      - ./index.php:/var/www/html/index.php
    ports:
      - 8080:80
    user: root
  admin:
    image: php:8.2.3-apache
    volumes:
      - ./index.php:/var/www/html/index.php
    ports:
      - 8888:80
    user: root

extends 活用後

# compose.yaml

services:
  web:
    image: php:8.2.3-apache
    volumes:
      - ./index.php:/var/www/html/index.php
    ports:
      - 8080:80
    user: root
  admin:
    extends: web
    ports:
      - 8888:80

実際にやってみるとかなり見通しが良くなったと思います。
ただ、この状態だと正常に動作しません。
実際に extends活用後compose.yamldocker compose up -d を行うと8080ポートが競合を起こした旨のエラーが発生します。

$ docker compose up -d
[+] Running 2/3
 ⠿ Network private_default    Created                                                                                                                                                                                                  0.0s
 ⠿ Container private-admin-1  Started                                                                                                                                                                                                  0.5s
 ⠿ Container private-web-1    Starting                                                                                                                                                                                                 0.5s
Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:8080 -> 0.0.0.0:0: listen tcp 0.0.0.0:8080: bind: address already in use

直感的にextendsした側でportsを設定すればextends元のports設定は上書きされてくれそうな感じがしますが、実際はextends元のports設定がマージされます。
docker compose convert を実行して確認すると下記のような結果が得られます(web8080:808888:80の設定がされていること確認できます)。

# docker compose convert の結果

name: private
services:
  admin:
    extends:
      service: web
    image: php:8.2.3-apache
    networks:
      default: null
    ports:
    - mode: ingress
      target: 80
      published: "8080"
      protocol: tcp
    - mode: ingress
      target: 80
      published: "8888"
      protocol: tcp
~~~~~ 以下結果省略 ~~~~~

spec.md を確認すると、
以下のキーはシーケンシャルな値として扱う必要があり、マージの結果生じた重複はすべて削除され、ユニークな要素のみが含まれるようになります。
cap_add, cap_drop, configs, deploy.placement.constraints, deploy.placement.preferences, deploy.reservations.generic_resources, device_cgroup_rules, expose, external_links, ports, secrets, security_opt
と書かれていました。
つまり、これらのキーでextends元にある設定は必ず受け継がれるということになります。

fileオプションを使う

それでは今回のようなports競合を起こしてしまうケースの場合にはextendsは使えないのかというと、そうではありません。
extendsにはfileというオプションがあり、これを活用することでportsの競合を回避することが可能です。

それでは実際に先ほどの例に適用してみます。
まず、 compose.yamlを下記のように変更します。
extendsfileオプションが追加して compose.base.yaml を読み込むようにしています。
また、 base サービスを拡張元に設定しています。

# compose.yaml

services:
  web:
    extends:
      file: compose.base.yaml
      service: base
    ports:
      - 8080:80
  admin:
    extends:
      file: compose.base.yaml
      service: base
    ports:
      - 8888:80

次にcompose.base.yamlを作成します(compose.yaml と同じディレクトリに配置してください)。

compose.base.yaml

services:
  base:
    image: php:8.2.3-apache
    volumes:
      - ./index.php:/var/www/html/index.php
    user: root

docker compose up -d && docker compose ps を実行して動作確認。
無事起動することが確認できました。

$ docker compose up -d && docker compose ps
[+] Running 2/0
 ⠿ Container private-web-1    Running                                                                                                                                                                                                  0.0s
 ⠿ Container private-admin-1  Running                                                                                                                                                                                                  0.0s
NAME                IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
private-admin-1     php:8.2.3-apache    "docker-php-entrypoi…"   admin               4 minutes ago       Up 4 minutes        0.0.0.0:8888->80/tcp
private-web-1       php:8.2.3-apache    "docker-php-entrypoi…"   web                 4 minutes ago       Up 4 minutes        0.0.0.0:8080->80/tcp

所感

最初からfileを使っていればports競合を踏むこともなかったのですが、composeファイルが1つ増えるのが微妙かなと思い見事にハマりました。
仮にfileを使わなくてもうまくいくパターンだとしても、チームでの運用を考えるとextendsを使うときはfile必須で利用する運用に統一しておいた方がハマらなくて良さそうだなと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?