compose.ymlの見慣れない記法について調べてみた
2024-02-26
azblob://2024/02/26/eyecatch/2024-02-26-yaml-anchor-mergekey-000.jpg

初めに

先日投稿したブログでdocker composeでコンテナを管理するcompose.ymlを乗せたのですが、そこで見慣れない項目がありました。

それがこの部分で、

x-base_service: &base_service
  tty: true

...
name: streamdiffusion
services:
  examples:
    <<: *base_service

のように&や*がついていたり、<<という属性があったりします。

この記法を初めて見たときはStableDiffsionのcompose.ymlで、上のリンクにあるブログではそれを参考にある程度雰囲気で書いていたのですが、気になったのでちゃんと調べることにしました。

検索

yaml <<

みたいに検索しても、yamlのほんとに基本的なことしか出てこなかったので、とりあえずGaiXerに聞いてみました。

yamlの<<や&、*はなんですか?

YAML では `<<`, `&`, `*` は特殊な記法を表すために用いられます。

- `&`: アンカーを作成します。アンカーはあるデータに名前を付けるのに使用され、そのデータは後から参照することができます。

例:
```yaml
person: &person
  name: John
  age: 30
```

- `*`: 作成したアンカーを参照します。アンカーを参照することで、データを再利用することができます。

例:
```yaml
employee:
  <<: *person
  role: Engineer
```
上記の例では、`employee` は `person` と同じ `name` と `age` を持ちます。

- `<<`: マージキーとも呼ばれます。他のマップを現在のマップにマージするのに使われます。

例:
```yaml
base: &base
  name: Everyone
  age: 30

developer:
  <<: *base
  skills: 
    - Python
    - Java
```

上記の例では、`developer` は `base` の `name` と `age` を持ち、さらに `skills` という新しい属性を持ちます。

アンカーやマージキーというらしいです。とはいえ個人的にLLMが出す回答を無条件に信頼するわけにもいかないので何らかのドキュメントにあたりたいところです。

幸いにもアンカーやマージキーというキーワードは出てきたのでこれでもう一回検索してみます。

するとansibleのドキュメントにyaml アンカーおよびエイリアス: 変数値の共有という項目がありました。

どうやらGaiXerの言ってることはおおよそ正しそうです。

しかし、せっかくなので実際に試すことにします。

実験

こんなyamlファイルを用意しました

person: &person
  name: John
  age: 30

employee:
  name: Taro
  age: 25
  skills: 
    - &s1 Python
    - &s2 Java

developer:
  <<: *person
  name: Rick
  skills:
    - *s1
    - C#

これをyqコマンドを使ってJSONで出力させることで、developer属性がどのように解釈されたのかを見てみます。

yq -o json .developer test.yml

するとこのような出力になりました

{
  "age": 30,
  "name": "Rick",
  "skills": [
    "Python",
    "C#"
  ]
}

personのnameを引き継ぎ、nameは上書きされていること、skillsにPythonが入っていることでちゃんとアンカーを参照したりマージできていることが分かります。

ただし、一点注意することがあって、developerを

developer:
  name: Rick
  <<: *person
  skills:
    - *s1
    - C#

のようにしてしまうと、name: Rickを上書きして

{
  "name": "John",
  "age": 30,
  "skills": [
    "Python",
    "C#"
  ]
}

なってしまったので、マージキーの順番には気を付ける必要がありそうです。

終わりに

yamlファイルを作ったりすることはdocker compose以外にもたまにあったのでまさかこんなことができるとは思ってもみませんでした。

こういうよく知ってるものでも、自分の知らない記法だったり構文だったりが見られるのはOSSのいいところですね。