YAML•
2025-06-19
•7 min
•alltools.one Team
YAMLAnchorsAliasesDRYConfiguration
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- 前綴慣例來定義用於存放錨點的擴充欄位。更多模式請參閱我們的 YAML 與 Docker Compose 指南。
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]
# 無法透過合併將 port 8080 加入此列表
替代方案:另外定義一個擴充的列表。
3. 順序很重要
錨點必須在被引用之前定義:
# 錯誤——別名在錨點之前
service:
settings: *defaults
defaults: &defaults
timeout: 30
# 正確——錨點在別名之前
defaults: &defaults
timeout: 30
service:
settings: *defaults
4. 並非所有工具都支援合併鍵
<< 合併鍵不是 YAML 核心規範的一部分——它是一個型別特定的擴充。大多數主流 YAML 解析器都支援它,但某些嚴格的解析器可能不支援。
使用我們的 YAML 驗證器來驗證你的 YAML 錨點使用方式。
常見問題
錨點在轉換 YAML 為 JSON 時會保留嗎?
不會。當 YAML 被解析時,錨點和別名會被解析為它們的實際值。產生的 JSON 會將值展開內聯。這意味著轉換為 JSON 再轉回來會失去 DRY 結構。錨點只存在於 YAML 原始格式中。
可以在複雜的巢狀覆寫中使用錨點嗎?
合併鍵(<<)只執行淺層合併——它複製錨點映射中的頂層鍵。巢狀物件會被整個替換,而非深度合併。若需要深度合併行為,你需要使用工具特定的方案(Helm 的 merge 函式、自訂 YAML 處理器)。
相關資源
- YAML 驗證器 — 驗證包含錨點和別名的 YAML
- YAML 語法教學 — YAML 基礎知識
- YAML 與 Docker Compose — Docker 專用模式