YAML Anchors & Aliases: Reuse Konfigurasi Tanpa Duplikasi
Pernah punya file docker-compose.yml dengan 5 service yang semuanya butuh konfigurasi logging, network, atau environment variable yang sama persis? Copy-paste blok yang sama berkali-kali memang jalan, tapi begitu ada perubahan, kamu harus edit di banyak tempat — dan rawan lupa satu. YAML punya fitur bawaan untuk masalah ini: anchors dan aliases.
Fitur ini jarang diajarkan di tutorial YAML dasar, padahal sangat berguna terutama untuk file konfigurasi besar seperti Docker Compose, Kubernetes manifest, atau GitHub Actions workflow.
Apa itu Anchor dan Alias?
Anchor (ditandai simbol &) adalah cara memberi "nama" pada sebuah blok atau nilai YAML supaya bisa dipakai ulang di tempat lain. Alias (ditandai simbol *) adalah cara memanggil kembali blok yang sudah diberi anchor tersebut. Analoginya mirip variabel di bahasa pemrograman: anchor itu seperti mendeklarasikan variabel, alias itu seperti memakai variabel tersebut.
Selain menghemat baris kode, anchor dan alias juga mengurangi risiko human error — kalau kamu harus mengubah satu nilai yang muncul di 10 tempat berbeda, cukup ubah di satu anchor dan semua alias otomatis ikut berubah saat file di-parse ulang. Ini jauh lebih aman dibanding mengandalkan find-and-replace manual yang rawan salah satu tempat terlewat.
Contoh Paling Sederhana
defaults: &defaults
adapter: postgres
host: localhost
development:
<<: *defaults
database: myapp_development
test:
<<: *defaults
database: myapp_test
Di contoh ini, &defaults menandai blok adapter dan host sebagai anchor bernama defaults. Lalu di bagian development dan test, <<: *defaults berarti "gabungkan (merge) semua isi anchor defaults ke sini". Hasil setelah di-parse, development akan punya adapter: postgres, host: localhost, dan database: myapp_development — tiga field sekaligus, padahal cuma menulis satu baris.
Merge Key: <<
Simbol << disebut merge key. Fungsinya menggabungkan isi map dari anchor ke dalam map saat ini. Kalau ada key yang sama di kedua map, key yang didefinisikan secara eksplisit di map saat ini akan menang (override), bukan yang dari anchor. Contoh:
base: &base
timeout: 30
retries: 3
service_a:
<<: *base
timeout: 60 # override, jadi 60 bukan 30
Hasil service_a akan punya timeout: 60 (override) dan retries: 3 (warisan dari base) — kombinasi keduanya.
Alias Tanpa Merge: Reuse Nilai Sederhana
Anchor dan alias tidak harus dipakai dengan merge key. Kamu juga bisa memakainya untuk nilai tunggal (string, number, list):
company: &company_name "PT Nusantara Digital"
report_title: *company_name
email_signature: *company_name
Di sini, report_title dan email_signature akan sama-sama bernilai "PT Nusantara Digital" — kalau nama perusahaan berubah, cukup edit satu tempat di anchor.
Contoh Nyata: Docker Compose
Ini kasus penggunaan paling umum di dunia nyata. Bayangkan beberapa service yang semuanya butuh setting logging yang sama:
x-logging: &default-logging
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
services:
web:
image: myapp/web
logging: *default-logging
worker:
image: myapp/worker
logging: *default-logging
scheduler:
image: myapp/scheduler
logging: *default-logging
Perhatikan key x-logging di atas — awalan x- adalah konvensi Docker Compose untuk field "extension" yang tidak divalidasi sebagai service asli, cocok dipakai khusus sebagai tempat menaruh anchor supaya tidak bentrok dengan schema Compose.
Contoh Nyata: GitHub Actions
Anchor juga sering dipakai di workflow CI/CD untuk menghindari duplikasi step atau environment yang sama di banyak job:
env: &common_env
NODE_ENV: production
API_URL: https://api.example.com
jobs:
build:
env: *common_env
steps:
- run: npm run build
test:
env: *common_env
steps:
- run: npm test
Anchor untuk List (Array)
Anchor tidak terbatas pada map/object, bisa juga dipakai untuk list:
common_ports: &ports
- "80:80"
- "443:443"
service_a:
ports: *ports
service_b:
ports: *ports
Batasan dan Hal yang Perlu Diperhatikan
- Anchor harus didefinisikan sebelum dipakai — YAML dibaca top-down, alias tidak bisa merujuk ke anchor yang didefinisikan di bawahnya.
- Merge key
<<hanya bekerja untuk map, bukan untuk list. Kalau butuh reuse list dan menambah elemen, kamu harus pakai fitur lanjutan seperti multiple merge key<<: [*a, *b](didukung sebagian parser) atau susun ulang strukturnya. - Tidak semua tool mendukung merge key secara penuh — sebagian parser YAML strict spec 1.1/1.2 memperlakukan
<<berbeda. Selalu test hasil parsing di environment target sebelum dipakai di production. - Alias meng-copy referensi, bukan deep clone independen di sebagian implementasi bahasa pemrograman (misal Python PyYAML) — kalau kamu memodifikasi hasil alias di kode setelah parsing, bisa saja ikut mengubah anchor aslinya karena keduanya menunjuk objek yang sama di memory.
Kapan Sebaiknya Pakai Anchor & Alias?
Fitur ini paling berguna kalau kamu punya konfigurasi berulang dalam jumlah banyak — misalnya lebih dari 3 service dengan setting yang identik, atau matrix testing dengan environment variable yang sama. Untuk file kecil dengan 1-2 pengulangan saja, terkadang lebih mudah dibaca kalau ditulis eksplisit tanpa anchor, karena anchor bisa membuat file agak sulit dibaca bagi orang yang belum familiar dengan sintaksnya.
Anchor Bersarang dan Kombinasi Beberapa Anchor
Anchor bisa dipakai berlapis — sebuah blok yang sudah memakai alias tetap bisa diberi anchor baru lagi untuk dipakai ulang lebih jauh. Ini berguna kalau kamu punya hierarki konfigurasi bertingkat, misalnya base config, lalu regional config yang mewarisi base, lalu environment-specific config yang mewarisi regional:
base: &base
timeout: 30
regional_id: ®ional_id
<<: *base
region: "id"
currency: "IDR"
production_id:
<<: *regional_id
debug: false
Beberapa parser YAML juga mendukung multiple merge key dalam satu map, ditulis sebagai list alias:
combined:
<<: [*base, *regional_id]
Perlu diingat, dukungan multiple merge key ini tidak universal di semua parser, jadi selalu cek dulu di library YAML yang kamu pakai (misalnya PyYAML, js-yaml, atau SnakeYAML) sebelum mengandalkannya di production.
Anchor vs Referensi Eksternal (Include File)
Penting dibedakan: anchor dan alias hanya bekerja di dalam satu file YAML yang sama (atau dalam satu multi-document stream yang dipisah ---, tergantung parser). Anchor tidak bisa dipakai untuk "include" file YAML lain seperti import di bahasa pemrograman. Kalau kamu butuh reuse konfigurasi lintas file, itu fitur terpisah yang biasanya disediakan oleh tool di atas YAML (misalnya Helm {{ include }} di Kubernetes, atau fitur <<: !include non-standar di beberapa custom loader), bukan bagian dari spesifikasi YAML itu sendiri.
YAML Anchors & Aliases: Reuse Configuration Without Duplication
Ever had a docker-compose.yml with 5 services that all need the exact same logging, network, or environment variable configuration? Copy-pasting the same block over and over works, but the moment something changes, you have to edit it in multiple places — and it's easy to miss one. YAML has a built-in feature for exactly this problem: anchors and aliases.
This feature is rarely covered in basic YAML tutorials, even though it's extremely useful, especially for large config files like Docker Compose, Kubernetes manifests, or GitHub Actions workflows.
What Are Anchors and Aliases?
An anchor (marked with &) is a way to "name" a YAML block or value so it can be reused elsewhere. An alias (marked with *) is how you call back that anchored block. Think of it like variables in a programming language: an anchor is like declaring a variable, and an alias is like using that variable.
The Simplest Example
defaults: &defaults
adapter: postgres
host: localhost
development:
<<: *defaults
database: myapp_development
test:
<<: *defaults
database: myapp_test
In this example, &defaults marks the adapter and host block as an anchor named defaults. Then in the development and test sections, <<: *defaults means "merge everything from the defaults anchor in here." After parsing, development ends up with adapter: postgres, host: localhost, and database: myapp_development — three fields from writing just one line.
The Merge Key: <<
The << symbol is called the merge key. Its job is to merge the map contents from an anchor into the current map. If the same key exists in both maps, the one explicitly defined in the current map wins (it overrides the anchor's value). Example:
base: &base
timeout: 30
retries: 3
service_a:
<<: *base
timeout: 60 # overridden, becomes 60 instead of 30
The resulting service_a ends up with timeout: 60 (overridden) and retries: 3 (inherited from base) — a combination of both.
Aliases Without Merging: Reusing Simple Values
Anchors and aliases don't have to be used with a merge key. You can also use them for a single value (string, number, list):
company: &company_name "PT Nusantara Digital"
report_title: *company_name
email_signature: *company_name
Here, both report_title and email_signature will equal "PT Nusantara Digital" — if the company name ever changes, you only need to edit it in one place, the anchor.
Real-World Example: Docker Compose
This is the most common real-world use case. Imagine several services that all need the same logging settings:
x-logging: &default-logging
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
services:
web:
image: myapp/web
logging: *default-logging
worker:
image: myapp/worker
logging: *default-logging
scheduler:
image: myapp/scheduler
logging: *default-logging
Notice the x-logging key above — the x- prefix is a Docker Compose convention for "extension" fields that aren't validated as an actual service, making it a good spot to place anchors without clashing with the Compose schema.
Real-World Example: GitHub Actions
Anchors are also commonly used in CI/CD workflows to avoid duplicating steps or the same environment across multiple jobs:
env: &common_env
NODE_ENV: production
API_URL: https://api.example.com
jobs:
build:
env: *common_env
steps:
- run: npm run build
test:
env: *common_env
steps:
- run: npm test
Anchors for Lists (Arrays)
Anchors aren't limited to maps/objects — they can be used for lists too:
common_ports: &ports
- "80:80"
- "443:443"
service_a:
ports: *ports
service_b:
ports: *ports
Limitations and Things to Watch Out For
- Anchors must be defined before they're used — YAML is read top-down, so an alias can't reference an anchor defined further below it.
- The merge key
<<only works for maps, not lists. If you need to reuse a list and add elements to it, you'll need an advanced feature like multiple merge keys<<: [*a, *b](supported by some parsers) or restructure the data. - Not every tool fully supports merge keys — some parsers that strictly follow YAML spec 1.1/1.2 treat
<<differently. Always test the parsed output in your target environment before relying on it in production. - Aliases copy a reference, not an independent deep clone, in some language implementations (e.g. Python's PyYAML) — if you mutate an alias's result in code after parsing, it may also change the original anchor since both point to the same object in memory.
When Should You Actually Use Anchors & Aliases?
This feature is most useful when you have a large amount of repeated configuration — for example, more than 3 services with identical settings, or a test matrix sharing the same environment variables. For small files with just 1-2 repetitions, it's sometimes easier to read if written out explicitly without anchors, since anchors can make a file harder to follow for people unfamiliar with the syntax.
Nested Anchors and Combining Multiple Anchors
Anchors can be layered — a block that already uses an alias can itself be given a new anchor for further reuse. This is handy when you have a tiered configuration hierarchy, e.g. a base config, then a regional config that inherits from base, then an environment-specific config that inherits from regional:
base: &base
timeout: 30
regional_id: ®ional_id
<<: *base
region: "id"
currency: "IDR"
production_id:
<<: *regional_id
debug: false
Some YAML parsers also support multiple merge keys in a single map, written as a list of aliases:
combined:
<<: [*base, *regional_id]
Keep in mind this multiple merge key support isn't universal across all parsers, so always check the YAML library you're using (e.g. PyYAML, js-yaml, or SnakeYAML) before relying on it in production.
Anchors vs External References (File Includes)
It's important to distinguish: anchors and aliases only work within a single YAML file (or within one multi-document stream separated by ---, depending on the parser). Anchors cannot be used to "include" another YAML file the way import works in a programming language. If you need to reuse configuration across files, that's a separate feature usually provided by a tool layered on top of YAML (e.g. Helm's {{ include }} in Kubernetes, or a non-standard <<: !include in some custom loaders), not something part of the YAML spec itself.