YAML
YAML (YAML Ain't Markup Language) is a human-friendly data serialization language commonly used for configuration files, data exchange, and infrastructure-as-code. It emphasizes readability and uses indentation to structure data.
No commands found
Try adjusting your search term
Getting Started
Fundamental YAML concepts and basic syntax for beginners.
Basic Syntax
YAML fundamentals including comments, key-value pairs, and indentation rules.
Basic key-value pair
Simple key-value pairs are the foundation of YAML syntax. Keys are followed by a colon and space, then the value.
name: John Doeage: 30city: New Yorkpython -c "import yaml; print(yaml.safe_load(open('config.yaml')))"{'name': 'John Doe', 'age': 30, 'city': 'New York'}- Indentation is crucial in YAML; use spaces, not tabs.
- Keys and values are separated by a colon and at least one space.
Comments in YAML
Comments begin with
# This is a commentname: John Doe # inline commentage: 30# Another commentcity: New Yorkpython -c "import yaml; print(yaml.safe_load(open('config.yaml')))"{'name': 'John Doe', 'age': 30, 'city': 'New York'}- Comments can be placed on their own line or at the end of a line.
- Use comments to document configuration intent and choices.
Data Types
Understanding YAML data types including strings, numbers, booleans, and null values.
Different data types
YAML automatically infers data types based on content. Explicitly quote strings to avoid type inference issues.
string: "Hello World"integer: 42float: 3.14boolean_true: trueboolean_false: falsenull_value: nullpython -c "import yaml; print(yaml.safe_load(open('types.yaml')))"{'string': 'Hello World', 'integer': 42, 'float': 3.14, 'boolean_true': True, 'boolean_false': False, 'null_value': None}- YAML supports strings, integers, floats, booleans, and null values.
- Unquoted strings like 'true' and 'false' are parsed as booleans.
Quoted strings
Quoting forces YAML to treat values as strings. Single and double quotes work similarly in YAML.
single_quoted: 'hello'double_quoted: "world"unquoted: plain textnumber_as_string: '42'python -c "import yaml; print(yaml.safe_load(open('quotes.yaml')))"{'single_quoted': 'hello', 'double_quoted': 'world', 'unquoted': 'plain text', 'number_as_string': '42'}- Quote numbers if you want them treated as strings.
- Unquoted strings are converted based on content interpretation.
Comments
How to use comments effectively in YAML files for documentation and clarity.
Comment placement and styles
Comments provide documentation without affecting the parsed data structure.
# Top-level comment explaining the file# This configuration defines application settings
app: name: MyApp # The application name version: 1.0 # Version number # Debug mode settings debug: falsepython -c "import yaml; print(yaml.safe_load(open('comments.yaml')))"{'app': {'name': 'MyApp', 'version': 1.0, 'debug': False}}- Comments are ignored during parsing and do not appear in the output.
- Use comments to explain the purpose of configuration values.
Documenting complex structures
Comments help explain the purpose of configuration sections and individual settings.
# Database connection settingsdatabase: # Connection string for PostgreSQL host: localhost port: 5432 # Standard PostgreSQL port # Credentials for authentication username: admin password: secretpython -c "import yaml; print(yaml.safe_load(open('db_config.yaml')))"{'database': {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'}}- Group related comments with the sections they document.
- Keep comments concise and focused on the 'why', not the 'what'.
Data Structures
Understanding dictionaries, lists, and mixed nested structures in YAML.
Dictionaries
Creating and using dictionaries (key-value mappings) in YAML.
Simple dictionary
A dictionary is created by indenting key-value pairs under a parent key.
person: name: John Doe age: 30 email: john@example.compython -c "import yaml; print(yaml.safe_load(open('person.yaml')))"{'person': {'name': 'John Doe', 'age': 30, 'email': 'john@example.com'}}- Use consistent indentation to define dictionary membership.
- Each key-value pair must have the same indentation level.
Nested dictionaries
Dictionaries can be nested multiple levels deep by continuing to indent.
user: profile: name: Alice contact: email: alice@example.com phone: "555-1234" settings: theme: dark notifications: truepython -c "import yaml; print(yaml.safe_load(open('nested.yaml')))"{'user': {'profile': {'name': 'Alice', 'contact': {'email': 'alice@example.com', 'phone': '555-1234'}}, 'settings': {'theme': 'dark', 'notifications': True}}}- Each level of nesting increases indentation by 2 spaces.
- Maintain consistent indentation to correctly represent hierarchy.
Lists
Creating and using lists (arrays) in YAML.
Simple list
Lists are created using dashes (-) followed by a space, with each item on a new line.
fruits: - apple - banana - orange - grapepython -c "import yaml; print(yaml.safe_load(open('fruits.yaml')))"{'fruits': ['apple', 'banana', 'orange', 'grape']}- Each list item starts with a dash and a space.
- All list items must have the same indentation level.
Nested lists
Lists can contain other lists, creating multi-dimensional structures.
matrix: - - 1 - 2 - 3 - - 4 - 5 - 6 - - 7 - 8 - 9python -c "import yaml; print(yaml.safe_load(open('matrix.yaml')))"{'matrix': [[1, 2, 3], [4, 5, 6], [7, 8, 9]]}- Nested lists use additional indentation and dashes.
- Readability decreases with deep nesting; simplify when possible.
Mixed Structures
Combining dictionaries and lists in complex nested structures.
List of dictionaries
Each list item is a dictionary with multiple key-value pairs. The dash precedes the first key of each dictionary.
employees: - name: Alice department: Engineering salary: 80000 - name: Bob department: Sales salary: 60000 - name: Carol department: Engineering salary: 85000python -c "import yaml; print(yaml.safe_load(open('employees.yaml')))"{'employees': [{'name': 'Alice', 'department': 'Engineering', 'salary': 80000}, {'name': 'Bob', 'department': 'Sales', 'salary': 60000}, {'name': 'Carol', 'department': 'Engineering', 'salary': 85000}]}- The dash and first key are at the same indentation level.
- Subsequent keys are indented to align under the first key.
Dictionary with list values
Dictionary values can be lists. The list starts on the next indented line with dashes.
project: name: MyProject team: - Alice - Bob - Carol tools: - Python - Docker - Kubernetespython -c "import yaml; print(yaml.safe_load(open('project.yaml')))"{'project': {'name': 'MyProject', 'team': ['Alice', 'Bob', 'Carol'], 'tools': ['Python', 'Docker', 'Kubernetes']}}- List values are indented further than the parent key.
- Each list item is indented consistently.
Advanced Syntax
Exploring advanced YAML features like multiline strings and special characters.
Multiline Strings
Handling strings that span multiple lines using block scalars.
Literal block scalar
The pipe (|) operator preserves newlines and formatting within the string.
description: | This is a literal block scalar. Newlines are preserved exactly as written. Each line becomes a separate line in the string.python -c "import yaml; print(repr(yaml.safe_load(open('literal.yaml'))['description']))"'This is a literal block scalar.\nNewlines are preserved exactly as written.\nEach line becomes a separate line in the string.\n'- Literal blocks preserve all whitespace and newlines.
- Content must be indented below the pipe character.
Folded block scalar
The greater-than (>) operator folds lines into a single line, preserving paragraph breaks.
summary: > This is a folded block scalar. Line breaks are converted to spaces. Paragraphs are separated by blank lines.python -c "import yaml; print(repr(yaml.safe_load(open('folded.yaml'))['summary']))"'This is a folded block scalar. Line breaks are converted to spaces. Paragraphs are separated by blank lines.\n'- Folded blocks join lines with spaces.
- Blank lines create paragraph separations.
Special Strings
Handling quoted strings, escape sequences, and special characters.
Quoted strings with escapes
Double and single quotes allow special characters and escape sequences within strings.
single: 'It''s a string'double: "Line 1\nLine 2"path: "C:\\Users\\name\\file.txt"colon: "key: value"python -c "import yaml; d = yaml.safe_load(open('quoted.yaml')); print({k: repr(v) for k, v in d.items()})"{'single': "It's a string", 'double': 'Line 1\nLine 2', 'path': 'C:\\Users\\name\\file.txt', 'colon': 'key: value'}- Single quotes preserve most escapes literally; double quotes interpret them.
- Escape special characters like colons by quoting the entire string.
Escape sequences
Escape sequences in double-quoted strings are interpreted as special characters.
newline: "Line 1\nLine 2"tab: "Column1\tColumn2"quote: "She said \"hello\""backslash: "Path: C:\\\\folder"python -c "import yaml; d = yaml.safe_load(open('escapes.yaml')); print({k: repr(v) for k, v in d.items()})"{'newline': 'Line 1\nLine 2', 'tab': 'Column1\tColumn2', 'quote': 'She said "hello"', 'backslash': 'Path: C:\\folder'}- Common escapes include \\n (newline), \\t (tab), \\\\ (backslash).
- Single quotes do not interpret most escape sequences.
Anchors and Aliases
Creating references to reuse content within a YAML file.
Basic anchor and alias
Anchors (&) mark content for reference, and aliases (*) reuse that content with the merge key (<<).
defaults: &default_settings timeout: 30 retries: 3 debug: false
api_config: <<: *default_settings endpoint: https://api.example.compython -c "import yaml; print(yaml.safe_load(open('anchor.yaml')))"{'defaults': {'timeout': 30, 'retries': 3, 'debug': False}, 'api_config': {'timeout': 30, 'retries': 3, 'debug': False, 'endpoint': 'https://api.example.com'}}- Anchors are defined with & followed by a name.
- Aliases reference anchors with * followed by the same name.
Multiple alias usage
The same anchor can be referenced multiple times by different aliases throughout the file.
common: &common_values version: 1.0 author: 'Mohammad Abu Mattar'
service1: <<: *common_values name: Service One
service2: <<: *common_values name: Service Twopython -c "import yaml; print(yaml.safe_load(open('multi_alias.yaml')))"{'common': {'version': 1.0, 'author': 'Admin'}, 'service1': {'version': 1.0, 'author': 'Admin', 'name': 'Service One'}, 'service2': {'version': 1.0, 'author': 'Admin', 'name': 'Service Two'}}- Each alias creates an independent copy of the anchored content.
- Anchors must be defined before they are used with aliases.
Advanced Features
Exploring anchors, aliases, and merge keys for configuration inheritance.
Anchors
Defining and naming anchors for content reuse.
Defining anchors
Anchors are defined using & followed by a name, marking content for later reference.
default_env: &default_env LOG_LEVEL: info DEBUG: false
db_config: &db_defaults host: localhost port: 5432 pool_size: 10python -c "import yaml; print(yaml.safe_load(open('anchors.yaml')))"{'default_env': {'LOG_LEVEL': 'info', 'DEBUG': False}, 'db_config': {'host': 'localhost', 'port': 5432, 'pool_size': 10}}- Anchor names should be descriptive and follow naming conventions.
- Anchors mark the exact structure they're placed on (dictionaries or values).
Named anchors for inheritance
Named anchors allow defining base configurations that can be inherited by multiple services.
base_service: &base image: ubuntu:20.04 restart_policy: always environment: APP_ENV: production
web_service: <<: *base ports: - 80:8080python -c "import yaml; print(yaml.safe_load(open('base.yaml')))"{'base_service': {'image': 'ubuntu:20.04', 'restart_policy': 'always', 'environment': {'APP_ENV': 'production'}}, 'web_service': {'image': 'ubuntu:20.04', 'restart_policy': 'always', 'environment': {'APP_ENV': 'production'}, 'ports': ['80:8080']}}- Anchors are local to the file and cannot be referenced across files.
- The merge key (<<) combines anchored content with additional properties.
Aliases
Using aliases to reference anchored content.
Using aliases
Aliases (asterisk) reference anchored content, creating independent copies in each location.
shared_config: &shared timeout: 30 retries: 3
api_service: name: API config: *shared
worker_service: name: Worker config: *sharedpython -c "import yaml; d = yaml.safe_load(open('alias_usage.yaml')); import json; print(json.dumps(d, indent=2))"{ "shared_config": {"timeout": 30, "retries": 3}, "api_service": {"name": "API", "config": {"timeout": 30, "retries": 3}}, "worker_service": {"name": "Worker", "config": {"timeout": 30, "retries": 3}}}- An alias creates a new copy of the anchored content, not a reference.
- Aliases must refer to previously defined anchors.
Multiple references to same anchor
A single anchor can be referenced multiple times throughout the file via separate aliases.
defaults: &defaults cache: redis cache_ttl: 3600
app_settings: cache_settings: *defaults
service_settings: cache_settings: *defaults
worker_settings: cache_settings: *defaultspython -c "import yaml; print(yaml.safe_load(open('multi_ref.yaml')))"{'defaults': {'cache': 'redis', 'cache_ttl': 3600}, 'app_settings': {'cache_settings': {'cache': 'redis', 'cache_ttl': 3600}}, 'service_settings': {'cache_settings': {'cache': 'redis', 'cache_ttl': 3600}}, 'worker_settings': {'cache_settings': {'cache': 'redis', 'cache_ttl': 3600}}}- Each alias reference creates an independent copy of the content.
- Modifying one copy does not affect others.
Merge Keys
Using the merge key (<<) to inherit and extend configurations.
Using merge key for inheritance
The merge key (<<) incorporates anchored content and allows overriding specific values.
defaults: &defaults timeout: 30 retries: 3 debug: false
production: <<: *defaults environment: production debug: false
staging: <<: *defaults environment: staging debug: truepython -c "import yaml; print(yaml.safe_load(open('merge_inherit.yaml')))"{'defaults': {'timeout': 30, 'retries': 3, 'debug': False}, 'production': {'timeout': 30, 'retries': 3, 'debug': False, 'environment': 'production'}, 'staging': {'timeout': 30, 'retries': 3, 'debug': True, 'environment': 'staging'}}- The merge key must be used with an alias.
- Values defined after the merge key override inherited values.
Multiple merge keys
Multiple anchors can be merged using a list syntax [*anchor1, *anchor2].
base: &base port: 8080 timeout: 30
logging: &logging log_level: info log_file: /var/log/app.log
service: <<: [*base, *logging] name: MyService replicas: 3python -c "import yaml; print(yaml.safe_load(open('multi_merge.yaml')))"{'base': {'port': 8080, 'timeout': 30}, 'logging': {'log_level': 'info', 'log_file': '/var/log/app.log'}, 'service': {'port': 8080, 'timeout': 30, 'log_level': 'info', 'log_file': '/var/log/app.log', 'name': 'MyService', 'replicas': 3}}- When multiple anchors are merged, keys from later anchors override earlier ones if there are conflicts.
Collections and Nesting
Deep nesting, complex hierarchies, and organizing multi-level structures.
Nested Dictionaries
Creating and managing deeply nested dictionary structures.
Simple nested dictionaries
Nested dictionaries use increasing indentation to show hierarchical relationships.
company: name: TechCorp location: New York departments: engineering: team_lead: Alice members: 10 sales: team_lead: Bob members: 5python -c "import yaml; d = yaml.safe_load(open('nested_dict.yaml')); print(d['company']['departments']['engineering'])"{'team_lead': 'Alice', 'members': 10}- Each indentation level represents one level of nesting.
- Maintain consistent indentation (typically 2 spaces per level).
Deeply nested structure
Multiple levels of nesting create a clear hierarchy for complex configurations.
system: server: production: database: primary: host: prod-db-1.example.com port: 5432 credentials: username: prod_user password: secret123python -c "import yaml; d = yaml.safe_load(open('deep_nest.yaml')); print(d['system']['server']['production']['database']['primary']['credentials'])"{'username': 'prod_user', 'password': 'secret123'}- Keep nesting reasonable (3-4 levels) for readability.
- Consider flattening deeply nested structures using descriptive keys.
Nested Lists
Creating and managing lists containing other lists.
List of lists
Nested lists use additional dashes and indentation to represent multi-dimensional arrays.
grid: - - North - South - East - West - - Up - Down - Left - Rightpython -c "import yaml; print(yaml.safe_load(open('grid.yaml')))"{'grid': [['North', 'South', 'East', 'West'], ['Up', 'Down', 'Left', 'Right']]}- Each nesting level adds one dash and indentation.
- Readability decreases with excessive nesting.
List with mixed nesting
Nested lists can represent matrices or multi-dimensional structures.
data: - - 1 - 2 - - 3 - 4 - - 5 - 6python -c "import yaml; print(yaml.safe_load(open('mixed_nest.yaml')))"{'data': [[1, 2], [3, 4], [5, 6]]}- Consistent indentation is critical for correct parsing.
Complex Nesting
Combining lists and dictionaries in intricate structures.
List of objects with nested values
Complex structures combine list items (projects) with nested list values (tasks), each containing dictionaries.
projects: - name: ProjectA status: active tasks: - name: Task 1 assigned_to: Alice priority: high - name: Task 2 assigned_to: Bob priority: medium - name: ProjectB status: planning tasks: - name: Task 3 assigned_to: Carol priority: highpython -c "import yaml; d = yaml.safe_load(open('projects.yaml')); print(d['projects'][0]['tasks'])"[{'name': 'Task 1', 'assigned_to': 'Alice', 'priority': 'high'}, {'name': 'Task 2', 'assigned_to': 'Bob', 'priority': 'medium'}]- The dash for list items aligns with the first key of each item.
- Nested lists use additional indentation and dashes.
Hierarchical configuration
Hierarchical structures can represent multi-level configurations with lists of objects containing nested data.
environments: - name: development services: - name: api port: 3000 env_vars: DEBUG: 'true' LOG_LEVEL: debug - name: db port: 5432 env_vars: POSTGRES_DB: dev_db - name: production services: - name: api port: 8080 env_vars: DEBUG: 'false' LOG_LEVEL: errorpython -c "import yaml; d = yaml.safe_load(open('envs.yaml')); print(len(d['environments'][0]['services']))"2- Maintain consistent indentation throughout complex nesting.
- Document structure clearly to aid understanding.
Practical Examples
Real-world YAML usage, best practices, and solutions.
Configuration Files
Using YAML for application and service configuration.
Application configuration
Application configurations define settings for the entire application, including database and logging.
app: name: MyApplication version: 1.0.0 port: 8000
database: host: localhost port: 5432 name: myapp_db credentials: username: app_user password: secure_pwd
logging: level: info output: stdoutpython -c "import yaml; conf = yaml.safe_load(open('app.yaml')); print(f\"App: {conf['app']['name']}, DB: {conf['database']['name']}\")"App: MyApplication, DB: myapp_db- Group related settings under common keys.
- Use meaningful section names for clarity.
Docker Compose service
Docker Compose YAML defines multi-container services with images, ports, volumes, and environment variables.
services: web: image: nginx:latest ports: - "80:80" volumes: - ./html:/usr/share/nginx/html environment: NGINX_ENV: production db: image: postgres:13 environment: POSTGRES_DB: mydb POSTGRES_PASSWORD: secret ports: - "5432:5432"docker-compose configservices defined and validated- Each service is a list item with specific configuration.
- Environment variables are key-value pairs in a dictionary.
Best Practices
Following YAML best practices for readability and maintainability.
Proper indentation and structure
Proper indentation, comments, and consistent structure improve readability and maintainability.
# Database configuration - consistent spacing and indentationdatabase: primary: host: db-primary.example.com port: 5432 credentials: username: admin password: secure_password replica: host: db-replica.example.com port: 5432 credentials: username: replica_user password: replica_passwordpython -c "import yaml; print(yaml.safe_load(open('db_config.yaml')))"proper YAML structure loaded successfully- Use 2 spaces for each indentation level consistently.
- Include comments explaining configuration purpose.
Avoiding common mistakes
Clear naming, proper structure, and meaningful comments make YAML files more maintainable.
# Good: Clear naming and structureservices: - name: api_service port: 8000 timeout: 30 - name: worker_service port: 8001 timeout: 60
# Bad: Unclear abbreviations and comments# svc:# - nm: api # Too abbreviated# p: 8000python -c "import yaml; d = yaml.safe_load(open('good.yaml')); print(f\"Services: {[s['name'] for s in d['services']]}\")"Services: ['api_service', 'worker_service']- Use full, descriptive names instead of abbreviations.
- Avoid overly clever or minimal formatting.
Validation and Use
Parsing YAML, validating syntax, and loading in different languages.
Parsing YAML in Python
Python's `yaml` module (PyYAML) can parse YAML files into Python dictionaries.
application: name: PythonApp debug: true port: 5000 database: host: localhost port: 5432import yamlwith open('app.yaml', 'r') as f: config = yaml.safe_load(f)print(config['application']['name'])print(config['application']['database']['host'])PythonApplocalhost- Always use `safe_load()` to avoid executing arbitrary code.
- Handle file exceptions for missing or invalid YAML files.
YAML validation
YAML validation tools check for syntax errors and formatting issues before using configuration.
# Using yamllint for syntax validationyamllint config.yaml
# Or validating with Pythonpython -c "import yaml; yaml.safe_load(open('config.yaml'))"yamllint config.yamlconfig.yaml is valid- Use yamllint for comprehensive linting and style checking.
- Python's `safe_load()` provides basic syntax validation.