YAML per Docker Compose: Pattern di Configurazione e Suggerimenti
Docker Compose usa YAML per definire applicazioni multi-container. Un docker-compose.yml ben strutturato fa la differenza tra un ambiente di sviluppo fluido e ore di debug dei problemi dei container. Questa guida copre i pattern essenziali e le insidie comuni.
Struttura di Base
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- api
api:
build: ./api
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://db:5432/myapp
depends_on:
- db
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: secret
volumes:
pgdata:
Variabili d'Ambiente
Inline
services:
api:
environment:
NODE_ENV: production
PORT: "3000"
DEBUG: "false"
Da File
services:
api:
env_file:
- .env
- .env.local # Sovrascrive i valori di .env
Sostituzione di Variabili
Referenzia variabili d'ambiente dell'host:
services:
api:
image: myapp:${TAG:-latest} # Default a "latest"
environment:
API_KEY: ${API_KEY} # Obbligatorio - fallisce se non impostato
LOG_LEVEL: ${LOG_LEVEL:-info} # Default a "info"
Rete
Reti Personalizzate
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:
internal: true # Nessun accesso esterno
I servizi sulla stessa rete possono raggiungersi tramite il nome del servizio. Il servizio db è raggiungibile solo da api, non da web.
Mappatura Porte
ports:
- "8080:80" # host:container
- "443:443"
- "127.0.0.1:3000:3000" # Binding solo su localhost
- "3000" # Porta host casuale
Volumi
Volumi con Nome (Persistenti)
services:
db:
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
driver: local
Bind Mount (Sviluppo)
services:
api:
volumes:
- ./src:/app/src # Codice sorgente
- /app/node_modules # Volume anonimo (previene sovrascrittura)
Il pattern del volume anonimo (/app/node_modules) impedisce che il bind mount dell'host sovrascriva le dipendenze installate nel container.
Controlli di Salute
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
api:
depends_on:
db:
condition: service_healthy
Questo assicura che api si avvii solo dopo che db supera i controlli di salute — non solo quando il container si avvia.
Campi di Estensione (Pattern DRY)
Usa campi con prefisso x- con anchor YAML per ridurre la ripetizione:
x-common: &common
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
x-env: &common-env
TZ: UTC
LOG_FORMAT: json
services:
api:
<<: *common
build: ./api
environment:
<<: *common-env
PORT: "3000"
worker:
<<: *common
build: ./worker
environment:
<<: *common-env
QUEUE: default
Per approfondimenti sugli anchor YAML, vedi la nostra guida ad anchor e alias YAML.
Compose Multi-Stage
Sviluppo vs Produzione
# docker-compose.yml (base)
services:
api:
build: ./api
environment:
DATABASE_URL: postgres://db:5432/myapp
# docker-compose.override.yml (dev - caricato automaticamente)
services:
api:
volumes:
- ./api/src:/app/src
environment:
NODE_ENV: development
DEBUG: "true"
ports:
- "3000:3000"
- "9229:9229" # Porta debug
# docker-compose.prod.yml
services:
api:
environment:
NODE_ENV: production
deploy:
replicas: 3
# Sviluppo (carica automaticamente l'override)
docker compose up
# Produzione
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
Insidie Comuni
1. Numeri di Porta Non Quotati
# RISCHIOSO - YAML interpreta 80:80 come un numero in base 60
ports:
- 80:80
# SICURO - usa sempre le virgolette
ports:
- "80:80"
2. Variabili d'Ambiente Booleane
# SBAGLIATO - YAML converte in booleano
environment:
DEBUG: true # Diventa Python True, non la stringa "true"
# CORRETTO - quota tutti i valori env
environment:
DEBUG: "true"
3. Tempistica depends_on
depends_on aspetta solo l'avvio del container, non la prontezza:
# Il container si avvia ma il DB potrebbe non essere pronto
depends_on:
- db
# Attendi il controllo di salute
depends_on:
db:
condition: service_healthy
Valida i tuoi file Docker Compose con il nostro Validatore YAML.
FAQ
Qual è la differenza tra docker-compose.yml e compose.yml?
Entrambi i nomi di file funzionano. compose.yml è la convenzione più recente raccomandata da Docker. docker-compose.yml è il nome legacy. Docker Compose v2+ cerca entrambi, preferendo compose.yml se entrambi esistono. Per i nuovi progetti, usa compose.yml.
Devo usare Docker Compose in produzione?
Docker Compose è eccellente per lo sviluppo e i deploy semplici. Per la produzione su scala, considera Docker Swarm (usa nativamente i file Compose) o Kubernetes. Il vantaggio di Compose è che la tua configurazione di sviluppo informa direttamente la produzione, riducendo le differenze tra ambienti.
Risorse Correlate
- Validatore YAML — Valida YAML Docker Compose
- Anchor e Alias YAML — Pattern di configurazione DRY
- Tutorial Sintassi YAML — Fondamenti YAML