Dev
2026-04-23
· 7 min lettura
✍️ Team ToolsCove
Cos'è YAML e come si usa: guida con esempi pratici
YAML è il formato di configurazione di Docker, Kubernetes, GitHub Actions e centinaia di altri strumenti. Capirne la sintassi — e le trappole — ti risparmia ore di debug.
Cos'è YAML?
YAML (acronimo ricorsivo di YAML Ain't Markup Language) è un formato di serializzazione dati progettato per essere leggibile dagli umani. A differenza di JSON o XML, è basato sull'indentazione e non richiede parentesi o virgolette per la maggior parte dei valori.
È lo standard de facto per i file di configurazione: lo trovi in Docker Compose, Kubernetes, GitHub Actions, Ansible, Helm, GitLab CI, e in decine di framework moderni.
Struttura di base
YAML è costruito su tre primitive: scalari, sequenze e mapping.
# Scalari (valori semplici)
nome: Mario Rossi
eta: 30
attivo: true
saldo: 1250.50
note: null # oppure ~
# Stringa multiriga (literal block |: preserva newline)
descrizione: |
Prima riga.
Seconda riga.
Terza riga.
# Stringa multiriga (folded block >: collassa newline in spazi)
bio: >
Questa lunga frase viene
resa come una riga sola
nel valore parsato.
# Sequenza (lista)
linguaggi:
- Python
- JavaScript
- Go
# Inline (stile JSON — valido anche in YAML)
colori: [rosso, verde, blu]
# Mapping (oggetto)
indirizzo:
via: Via Roma 1
citta: Milano
cap: "20100" # virgolette per evitare interpretazione numerica
YAML vs JSON — Confronto diretto
Lo stesso documento nei due formati:
YAML
utente:
id: 42
nome: Mario
email: mario@ex.it
ruoli:
- admin
- editor
attivo: true
note: null
JSON equivalente
{
"utente": {
"id": 42,
"nome": "Mario",
"email": "mario@ex.it",
"ruoli": [
"admin",
"editor"
],
"attivo": true,
"note": null
}
}
YAML è più compatto e leggibile, ma ha due differenze cruciali: supporta i commenti (con #) e usa l'indentazione invece delle parentesi. La pulizia visiva ha un costo: gli errori di indentazione sono silenziosi e difficili da individuare a occhio.
⚠️ Mai usare tab! YAML accetta solo spazi per l'indentazione — i tab causano errori di parsing. Configura il tuo editor per usare 2 spazi come indentazione per i file .yml/.yaml.
Tipi di dati impliciti — Le trappole
YAML 1.1 (usato da molti parser) interpreta automaticamente alcuni valori come tipi non-stringa. Questo causa bug sottili:
# Booleani "nascosti" in YAML 1.1:
campo1: yes # → true (attenzione!)
campo2: no # → false
campo3: on # → true
campo4: off # → false
campo5: "yes" # → stringa "yes" (corretto)
# Numeri con zeri iniziali interpretati come ottali:
porta: 0777 # → 511 in ottale! Usa "0777" come stringa
# Date interpretate automaticamente:
data: 2026-04-23 # → oggetto Date, non stringa
data_str: "2026-04-23" # → stringa
# YAML 1.2 (spec moderna) è molto più prevedibile su questi casi
Anchor e Alias — Riutilizza blocchi
Una delle funzionalità più potenti di YAML per i file di configurazione complessi è la possibilità di definire blocchi riutilizzabili con anchor (&) e richiamarli con alias (*):
# Definisci un anchor
defaults: &defaults
restart: always
logging:
driver: json-file
options:
max-size: "10m"
# Riutilizzalo con alias + merge key
services:
web:
<<: *defaults # merge di defaults
image: nginx:alpine
ports:
- "80:80"
api:
<<: *defaults # stessi defaults riutilizzati
image: node:20
environment:
NODE_ENV: production
Esempi reali pronti da usare
Docker Compose — App fullstack
version: "3.9"
services:
db:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_DB: myapp
POSTGRES_USER: admin
POSTGRES_PASSWORD: ${DB_PASSWORD} # variabile d'ambiente
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin"]
interval: 10s
timeout: 5s
retries: 5
api:
build: ./backend
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: postgres://admin:${DB_PASSWORD}@db:5432/myapp
JWT_SECRET: ${JWT_SECRET}
ports:
- "3000:3000"
web:
build: ./frontend
restart: unless-stopped
depends_on:
- api
ports:
- "80:80"
- "443:443"
volumes:
db_data:
GitHub Actions — CI/CD Pipeline
name: CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test
- run: npm run build
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to production
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: ./scripts/deploy.sh
Template generico configurazione app
# config.yml — template da adattare
app:
name: my-app
version: "1.0.0"
environment: production # development | staging | production
debug: false
secret_key: "${SECRET_KEY}"
server:
host: "0.0.0.0"
port: 8080
workers: 4
timeout: 30
database:
host: "localhost"
port: 5432
name: "mydb"
pool:
min: 2
max: 10
cache:
backend: redis
host: "localhost"
port: 6379
ttl: 3600 # secondi
logging:
level: info # debug | info | warning | error
format: json
output: stdout
FAQ
YAML e JSON sono intercambiabili? ▾
In parte sì: ogni JSON valido è YAML valido (YAML 1.2 è un superset di JSON). Ma YAML ha commenti, anchor, alias e sintassi senza virgolette che JSON non ha. Per le API REST JSON è preferibile; per i file di configurazione YAML è più leggibile.
Come si scrivono i commenti in YAML? ▾
Con il simbolo #. Tutto ciò che segue # sulla stessa riga è un commento. YAML non ha commenti multiriga — ogni riga deve avere il suo #.
Cos'è un anchor YAML? ▾
Un anchor (&nome) definisce un blocco riutilizzabile. Un alias (*nome) lo include altrove. La merge key (<<: *nome) include tutte le chiavi dell'anchor nel mapping corrente, permettendo di sovrascriverne alcune.
Perché il mio YAML non viene parsato correttamente? ▾
I problemi più comuni: tab invece di spazi, indentazione inconsistente, mancanza di virgolette per stringhe con caratteri speciali (: - [ { #), o valori booleani non quotati (yes, no, on, off sono interpretati come booleani in YAML 1.1). Usa il YAML Formatter per individuare l'errore.