YAMLアンカーとエイリアス:DRY設定パターン
YAMLファイルの複数のセクションで同じ設定を繰り返すことは、DRY(Don't Repeat Yourself)原則に違反し、メンテナンスの問題を引き起こします。YAMLのアンカーとエイリアスは、値を一度定義して複数回参照することでこの問題を解決します。
基本構文
アンカー (&):再利用する値をマークする
エイリアス (*):アンカーされた値を参照する
# アンカーを定義
defaults: &default_settings
timeout: 30
retries: 3
log_level: info
# エイリアスで参照
development:
<<: *default_settings
log_level: debug
production:
<<: *default_settings
retries: 5
<< マージキーは、参照されたアンカーからすべてのキーバリューペアを取り込みます。マージ後に定義されたプロパティは、アンカーの値をオーバーライドします。
解決後の結果:
development:
timeout: 30
retries: 3
log_level: debug # オーバーライド済み
production:
timeout: 30
retries: 5 # オーバーライド済み
log_level: info
アンカーの種類
スカラーアンカー
単一の値を再利用:
max_connections: &max_conn 100
database:
pool_size: *max_conn
cache:
pool_size: *max_conn
シーケンスアンカー
リスト全体を再利用:
common_ports: &ports
- 80
- 443
web_server:
ports: *ports
load_balancer:
ports: *ports
マッピングアンカー
オブジェクト全体を再利用(最も一般的なパターン):
logging: &log_config
driver: json-file
options:
max-size: "10m"
max-file: "3"
services:
api:
logging: *log_config
worker:
logging: *log_config
マージキー (<<)
マージキーには特定の動作があります:
- 参照されたマッピングからすべてのキーバリューペアをコピーする
- 明示的に設定されたキーはマージされたキーより優先される
- 複数のマージは順番に処理される(競合の場合は最初のものが優先)
# 複数のマージ
base: &base
a: 1
b: 2
extra: &extra
b: 3
c: 4
combined:
<<: [*base, *extra]
# 結果: a=1, b=2 (baseが優先), c=4
実践的な例
Docker Compose
x-common: &common
restart: unless-stopped
networks:
- app-network
logging:
driver: json-file
options:
max-size: "10m"
services:
api:
<<: *common
image: myapp/api:latest
ports:
- "8080:8080"
environment:
DATABASE_URL: postgres://db:5432/myapp
worker:
<<: *common
image: myapp/worker:latest
environment:
QUEUE_URL: redis://cache:6379
scheduler:
<<: *common
image: myapp/scheduler:latest
Docker Composeでは、アンカーを保持する拡張フィールドに x- プレフィックスの慣例を使用します。詳しいパターンはDocker ComposeのためのYAMLガイドをご覧ください。
GitHub Actions
jobs:
test:
runs-on: ubuntu-latest
env: &common_env
NODE_VERSION: '20'
CI: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm test
build:
runs-on: ubuntu-latest
needs: test
env:
<<: *common_env
BUILD_TARGET: production
steps:
- uses: actions/checkout@v4
- run: npm run build
Kubernetes
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
resources: &resources
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
- name: sidecar
resources: *resources # 同じリソース制限
制限事項と注意点
1. ファイル間参照は不可
アンカーは単一のYAMLファイル内でのみ機能します。別のファイルで定義されたアンカーを参照することはできません。ファイル間の再利用には、Helm、Jsonnet、Kustomizeなどのテンプレートツールを使用してください。
2. シーケンスの部分的オーバーライドは不可
リストをマージして部分的にオーバーライドすることはできません。リスト全体が置換されます:
base_ports: &ports
- 80
- 443
service:
ports: *ports # 正確に [80, 443] が取得されます
# マージでこのリストにポート8080を追加することはできません
回避策:拡張されたリストを別途定義してください。
3. 順序が重要
アンカーは参照される前に定義する必要があります:
# 誤り - アンカーの前にエイリアス
service:
settings: *defaults
defaults: &defaults
timeout: 30
# 正しい - エイリアスの前にアンカー
defaults: &defaults
timeout: 30
service:
settings: *defaults
4. すべてのツールがマージキーをサポートしているわけではない
<< マージキーはYAMLコア仕様の一部ではなく、型固有の拡張です。ほとんどの一般的なYAMLパーサーはサポートしていますが、一部の厳格なパーサーはサポートしていない場合があります。
YAMLバリデーターでYAMLアンカーの使用法を検証してください。
FAQ
YAMLをJSONに変換するとアンカーは保持されますか?
いいえ。YAMLがパースされると、アンカーとエイリアスは値に解決されます。結果のJSONでは値がインライン展開されます。つまり、JSONに変換して戻すとDRY構造が失われます。アンカーはYAMLソースフォーマットにのみ存在します。
複雑なネストされたオーバーライドでアンカーを使用できますか?
マージキー (<<) は浅いマージのみを実行します。アンカーされたマッピングのトップレベルキーのみをコピーします。ネストされたオブジェクトは完全に置換され、ディープマージはされません。ディープマージの動作には、ツール固有のソリューション(Helmの merge 関数、カスタムYAMLプロセッサーなど)が必要です。
関連リソース
- YAMLバリデーター — アンカーとエイリアスを含むYAMLの検証
- YAML構文チュートリアル — YAMLの基礎
- Docker ComposeのためのYAML — Docker固有のパターン