Files
laboratori-cloud/labs/lab-03-compute/tutorial/03-dependencies-with-health.md
Luca Sacchi Ricciardi 23a9ffe443 feat(lab-03): complete Phase 4 - Compute & EC2 lab
Phase Plans (5 files):
- 04-RESEARCH.md: Domain research on Docker limits, healthchecks, EC2 parallels
- 04-VALIDATION.md: Success criteria and validation strategy
- 04-01-PLAN.md: Test infrastructure (RED phase)
- 04-02-PLAN.md: Diátxis documentation
- 04-03-PLAN.md: Infrastructure implementation (GREEN phase)

Test Scripts (6 files, 1300+ lines):
- 01-resource-limits-test.sh: Validate INF-03 compliance
- 02-healthcheck-test.sh: Validate healthcheck configuration
- 03-enforcement-test.sh: Verify resource limits with docker stats
- 04-verify-infrastructure.sh: Infrastructure verification
- 99-final-verification.sh: End-to-end student verification
- run-all-tests.sh: Test orchestration with fail-fast
- quick-test.sh: Fast validation (<30s)

Documentation (11 files, 2500+ lines):
Tutorials (3):
- 01-set-resource-limits.md: EC2 instance types, Docker limits syntax
- 02-implement-healthchecks.md: ELB health check parallels
- 03-dependencies-with-health.md: depends_on with service_healthy

How-to Guides (4):
- check-resource-usage.md: docker stats monitoring
- test-limits-enforcement.md: Stress testing CPU/memory
- custom-healthcheck.md: HTTP, TCP, database healthchecks
- instance-type-mapping.md: Docker limits → EC2 mapping

Reference (3):
- compose-resources-syntax.md: Complete deploy.resources reference
- healthcheck-syntax.md: All healthcheck parameters
- ec2-instance-mapping.md: Instance type mapping table

Explanation (1):
- compute-ec2-parallels.md: Container=EC2, Limits=Instance Type, Healthcheck=ELB

Infrastructure:
- docker-compose.yml: 5 services (web, app, worker, db, stress-test)
  All services: INF-03 compliant (cpus + memory limits)
  All services: healthcheck configured
  EC2 parallels: t2.nano, t2.micro, t2.small, t2.medium, m5.large
- Dockerfile: Alpine 3.19 + stress tools + non-root user

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 15:16:58 +02:00

8.2 KiB

Tutorial 3: Dipendenze tra Servizi con Healthchecks

In questo tutorial imparerai a configurare dipendenze tra servizi usando depends_on, assicurando che i servizi partano nell'ordine corretto.

Obiettivi di Apprendimento

Al termine di questo tutorial sarai in grado di:

  • Comprendere le dipendenze tra servizi in applicazioni multi-tier
  • Configurare depends_on con conditions
  • Implementare startup ordinato con healthchecks
  • Verificare l'ordine di avvio dei servizi

Prerequisiti

  • Completamento di Tutorial 1 e 2
  • Servizi configurati con resource limits e healthchecks
  • Comprensione base di architetture multi-tier

Parte 1: Dipendenze tra Servizi

Cos'è una Dipendenza?

In un'applicazione multi-tier, i servizi dipendono l'uno dall'altro:

Web → App → Database
  • Il Web server ha bisogno dell'App server
  • L'App server ha bisogno del Database
  • Il Database non dipende da nessuno (parte prima)

Perché sono Importanti?

  1. Prevenzione Errori: Evita connection error a servizi non pronti
  2. Startup Affidabile: Ogni servizio aspetta che le sue dipendenze siano pronte
  3. Zero-Downtime: Durante deployment, i nuovi servizi aspettano i vecchi
  4. Debugging: Problemi di connessione sono più facili da diagnosticare

Parte 2: Tipi di Dipendenze

depends_on: service_started (Default)

services:
  app:
    depends_on:
      - db

Comportamento: app parte quando db è avviato (non necessariamente healthy)

Problema: Il database potrebbe ancora essere inizializzando → connection errors

depends_on: service_healthy (Raccomandato)

services:
  app:
    depends_on:
      db:
        condition: service_healthy

Comportamento: app parte quando db è healthy (dopo healthcheck pass)

Vantaggio: Il database è completamente pronto → nessun connection error


Parte 3: Pratica - Architettura Multi-Tier

Creiamo un'applicazione a 3 tier con dipendenze:

Web (t2.micro) → App (t2.small) → DB (t2.medium)

Step 1: Configurare il Database (Primo)

version: "3.8"

services:
  # Tier 3: Database - nessuna dipendenza
  db:
    image: postgres:16-alpine
    container_name: lab03-db
    hostname: db

    environment:
      POSTGRES_DB: lab03_db
      POSTGRES_USER: lab03_user
      POSTGRES_PASSWORD: lab03_password

    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 4G

    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U lab03_user -d lab03_db || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

    volumes:
      - db-data:/var/lib/postgresql/data

    restart: unless-stopped

volumes:
  db-data:

Nota: Il database non ha depends_on - è il primo a partire.

Step 2: Configurare l'App Server

  # Tier 2: Application - dipende dal database
  app:
    image: nginx:alpine
    container_name: lab03-app
    hostname: app

    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 2G

    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 5s

    ports:
      - "127.0.0.1:8081:80"

    # Dipende dal database healthy
    depends_on:
      db:
        condition: service_healthy

    restart: unless-stopped

Nota: app parte SOLO quando db è healthy.

Step 3: Configurare il Web Server

  # Tier 1: Web - dipende dall'app
  web:
    image: nginx:alpine
    container_name: lab03-web
    hostname: web

    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1G

    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 5s

    ports:
      - "127.0.0.1:8080:80"

    # Dipende dall'app healthy
    depends_on:
      app:
        condition: service_healthy

    restart: unless-stopped

Nota: web parte SOLO quando dbapp sono entrambi healthy.


Parte 4: Avvio e Verifica

Step 1: Avviare tutti i servizi

cd labs/lab-03-compute
docker compose up -d

Step 2: Osservare l'ordine di avvio

# Monitora lo stato in tempo reale
watch -n 2 'docker ps --format "table {{.Names}}\t{{.Status}}"'

Sequenza prevista:

  1. lab03-db parte → starting(healthy) dopo ~10-20s
  2. lab03-app parte → starting(healthy) dopo che db è healthy
  3. lab03-web parte → starting(healthy) dopo che app è healthy

Step 3: Verificare l'ordine nei log

docker compose logs --tail=50

Cerca messaggi tipo:

lab03-db  | database system is ready to accept connections
lab03-app | Waiting for db to be healthy...
lab03-web | Waiting for app to be healthy...

Parte 5: Testare le Dipendenze

Test 1: Riavviare il database

# Ferma il database
docker compose stop db

# Guarda lo stato di app e web
docker ps

Risultato: app e web rimangono in esecuzione (non dipendono dal runtime di db, solo dall'avvio iniziale)

Test 2: Ferma e riavvia l'app

# Ferma l'app
docker compose stop app

# Guarda lo stato del web
docker ps

Risultato: web continua a funzionare (stessa logica)

Test 3: Riavvio completo

# Ferma tutto
docker compose down

# Riavvia
docker compose up -d

# Osserva l'ordine di startup
docker compose up -d && docker compose logs -f

Vedrai: dbappweb in ordine.


Parte 6: Parallelismo AWS

ECS Task Definitions

In AWS ECS, le dipendenze si configurano nel Task Definition:

{
  "containerDefinitions": [
    {
      "name": "db",
      "essential": true,
      "healthCheck": {
        "command": ["CMD-SHELL", "pg_isready -U postgres"],
        "interval": 10,
        "timeout": 5,
        "retries": 5
      }
    },
    {
      "name": "app",
      "essential": true,
      "dependsOn": [
        {
          "containerName": "db",
          "condition": "HEALTHY"
        }
      ]
    },
    {
      "name": "web",
      "essential": true,
      "dependsOn": [
        {
          "containerName": "app",
          "condition": "HEALTHY"
        }
      ]
    }
  ]
}

Condizioni di Dipendenza ECS

Condizione Docker Equivalente Descrizione
START depends_on (default) Container avviato
HEALTHY condition: service_healthy Healthcheck passing
COMPLETE - Container exit code 0
SUCCESS - Container exit code 0

Parte 7: Best Practices

1. Usa Sempre service_healthy

# ✓ GOOD
depends_on:
  db:
    condition: service_healthy

# ✗ AVOID (se possibile)
depends_on:
  - db

2. Configura healthcheck appropriati

# Database - startup più lento
healthcheck:
  retries: 5
  start_period: 10s

# Web server - startup veloce
healthcheck:
  retries: 3
  start_period: 5s

3. Previeni loop di dipendenze

# ✗ WRONG - circular dependency
web:
  depends_on:
    app: {condition: service_healthy}
app:
  depends_on:
    web: {condition: service_healthy}  # LOOP!

# ✓ GOOD - directional dependency
web:
  depends_on:
    app: {condition: service_healthy}
app:
  depends_on:
    db: {condition: service_healthy}  # OK
db:
  # No dependencies - base tier

In questo tutorial hai imparato:

Concetto: Dipendenze tra servizi per startup ordinato ✓ Sintassi: depends_on con condition: service_healthyPratica: Architettura multi-tier Web → App → DB ✓ Verifica: Osservare l'ordine di startup ✓ Parallelismo: ECS dependsOn con condizione HEALTHY


Complimenti!

Hai completato i tutorial di Lab 03 - Compute & EC2!

Competenze Acquisite:

  • Configurare limiti delle risorse (EC2 instance types)
  • Implementare healthchecks (ELB health checks)
  • Gestire dipendenze tra servizi (ECS task definitions)

Prossimi Passi:

  • Esegui i test di verifica: bash tests/run-all-tests.sh
  • Esplora le guide How-to per procedure specifiche
  • Consulta i documenti Reference per sintassi completa
  • Leggi Explanation per approfondire i parallelismi cloud