YAML Guide
A practical reference for YAML syntax, formatting rules, and real-world usage in DevOps and cloud infrastructure.
What is YAML?
YAML (YAML Ain't Markup Language) is a human-readable data serialization format. It was designed to be simple to write and easy to read — unlike XML or JSON, which prioritize machine parsing over human authoring.
YAML is used everywhere in modern DevOps: Kubernetes manifests, Docker Compose files, GitHub Actions workflows, Ansible playbooks, CI/CD pipelines, Helm charts, and application configuration files.
Technically, YAML is a superset of JSON — every valid JSON document is also valid YAML. But YAML's real power is in its clean, minimal syntax: indentation instead of braces, dashes instead of brackets, and support for comments.
YAML Syntax Basics
Key-Value Pairs
The fundamental unit of YAML is the key-value pair. A colon and a space separate the key from the value:
name: Alice age: 30 active: true score: 9.5 notes: ~ # null value
Nested Mappings (Objects)
Nested objects use indentation. Child keys are indented under their parent with consistent spacing (2 or 4 spaces — never tabs):
server:
host: localhost
port: 8080
tls:
enabled: true
cert: /etc/ssl/cert.pemLists (Sequences)
Lists use a dash followed by a space. List items can be scalars or nested mappings:
# Simple list
fruits:
- apple
- banana
- cherry
# List of objects
users:
- name: Alice
role: admin
- name: Bob
role: viewerComments
YAML supports comments starting with #. Comments can appear on their own line or inline after a value:
# This is a comment name: Alice # inline comment # age: 30 # commented-out key
Strings & Quoting
Most strings don't need quotes. Use quotes when the value contains special characters like colons, hash signs, or leading/trailing spaces:
# No quotes needed name: Alice Smith version: 1.2.3 # Quotes required message: "Hello: World" # colon in value tag: "#production" # hash in value path: " leading space" # leading space # Single quotes (literal — no escapes) regex: 'd+.d+' # Double quotes (supports escape sequences) newline: "line1 line2"
YAML Data Types
YAML automatically infers data types. This is powerful but can also surprise you when values like true, null, or 1.0 are interpreted as booleans, null, or floats instead of strings.
# Strings name: Alice city: "New York" # Integers port: 8080 count: -5 # Floats ratio: 3.14 temperature: -0.5 # Booleans (true/false, yes/no, on/off) enabled: true debug: false # Null (empty or explicit) optional: ~ also_null: null # Multi-line strings description: | This is a literal block scalar. Newlines are preserved. Great for scripts and SQL. summary: > This is a folded scalar. Newlines become spaces. Good for long descriptions.
Anchors & Aliases — Avoid Repetition
YAML anchors (&name) mark a value for reuse. Aliases (*name) reference the anchor. This is useful in CI/CD configs and Docker Compose to DRY up repeated blocks:
# Define a reusable block with an anchor
defaults: &defaults
image: node:18
restart: unless-stopped
environment:
NODE_ENV: production
# Reuse with an alias (merges the block)
web:
<<: *defaults
ports:
- "3000:3000"
worker:
<<: *defaults
command: node worker.jsMulti-Document YAML Files
A single YAML file can contain multiple independent documents separated by ---. This is common in Kubernetes, where you might keep a Deployment and Service together in one file:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
# ...
---
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
selector:
app: my-app
ports:
- port: 80The YAML formatter on this site handles multi-document files natively. It validates and formats each document independently and shows a document count badge.
Kubernetes YAML Structure
Every Kubernetes manifest follows the same top-level structure. Understanding this structure makes it easier to spot errors:
apiVersion: apps/v1 # API group/version
kind: Deployment # Resource type
metadata:
name: my-app # Required: resource name
namespace: production # Optional: namespace
labels:
app: my-app
version: "1.0"
spec: # Desired state (varies by kind)
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:1.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512MiCommon Kubernetes YAML mistakes:
- • Indentation under containers: Each container is a list item starting with
- - • Labels must be strings: Quote numeric values like
version: "1.0" - • Resource quantities:
100m(millicores),128Mi(mebibytes) are strings — no quotes needed
Docker Compose YAML
Docker Compose files define multi-container applications. The top-level keys are services, volumes, and networks:
services:
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- app
app:
build: .
environment:
DATABASE_URL: postgres://db:5432/mydb
SECRET_KEY: ${SECRET_KEY} # from .env file
depends_on:
- db
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
volumes:
db-data:GitHub Actions Workflow YAML
GitHub Actions workflows live in .github/workflows/*.yml. A malformed workflow fails silently — you only find out after pushing:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm testCommon GitHub Actions YAML issues:
- • Steps must be a list: Each step starts with
- name:at the same indent level - • run: is a string: Multi-line commands use
run: |(literal block scalar) - • on: needs quotes in some parsers: If you have issues, quote it as
"on":
YAML vs JSON — When to Use Each
| YAML | JSON | |
|---|---|---|
| Comments | ✓ Supported | ✗ Not supported |
| Human readability | High | Moderate |
| Verbosity | Low | High |
| API interchange | Uncommon | Standard |
| Config files | Standard | Common |
| Whitespace sensitivity | Yes (significant) | No |
| Data types | Rich (with type coercion) | 6 types, explicit |
| Multi-document | ✓ Supported (---) | ✗ Not supported |
Rule of thumb: Use YAML for files humans read and edit (config, CI/CD, infrastructure). Use JSON for machine-to-machine data exchange (APIs, databases, serialization). When in doubt, use whichever format the tool or framework already expects.
YAML Best Practices
Use 2-space indentation
2 spaces is the de facto standard for YAML in Kubernetes and most DevOps tooling. 4 spaces is also acceptable. Never use tabs — YAML strictly forbids them.
Always validate before deploying
Invalid YAML fails silently in many tools or produces confusing errors downstream. Validate locally first using a tool like this one.
Quote values that look like other types
Values like "true", "null", "1.0", or "0775" can be misinterpreted as booleans, null, floats, or octal numbers. Quote them when you mean a string.
Use anchors to DRY up repeated blocks
When the same configuration appears in multiple places (e.g., environment variables across services), define it once with an anchor and reference it with aliases.
Keep line length reasonable
Long values can be wrapped using YAML block scalars (| or >) or broken into multi-line sequences. Aim for under 120 characters per line.
Pin versions explicitly
In Docker images, Kubernetes API versions, and GitHub Actions, always specify exact versions (image: nginx:1.25.3 instead of image: nginx:latest). This prevents unexpected breakage.
Ready to format your YAML?
Use the free online tool to format, validate, and convert your YAML instantly — no login, no server, no data collection.
Open the YAML Formatter