初めに
先日投稿したブログで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のいいところですね。