Diagramma di Container C4: guida completa con esempi - Archyl Blog

Il diagramma di container C4 (livello 2 del modello C4) mostra i blocchi costitutivi deployabili del tuo sistema: web app, API, database, code. Questa guida spiega cos'è un diagramma di container, cosa deve contenere, un esempio completo svolto, gli errori comuni e come mantenerlo sincronizzato con il tuo codice.

Diagramma di Container C4: guida completa con esempi

Se devi disegnare un solo diagramma di architettura per il tuo sistema, scegli il diagramma di container. È il livello 2 del modello C4, e in pratica è il più usato dei quattro livelli -- perché si mappa direttamente sulle cose che i team di ingegneria realmente costruiscono, distribuiscono e gestiscono: web app, API, database, message broker.

Questa guida copre tutto ciò che ti serve per creare un buon diagramma di container C4: cos'è (e cosa non è -- no, un container C4 non è un container Docker), cosa deve contenere, un esempio completo svolto per un tipico prodotto SaaS, gli errori che rovinano la maggior parte dei diagrammi di container e come crearne uno manualmente o generarlo dal tuo codice.

Se sei completamente nuovo al modello C4, inizia dalla nostra guida completa al modello C4, poi torna qui.

Che cos'è un diagramma di container C4?

Il diagramma di container è il livello 2 del modello C4, creato da Simon Brown. Zooma nell'unica scatola che rappresenta il tuo sistema nel diagramma di Contesto di Sistema e rivela i blocchi costitutivi tecnici di alto livello al suo interno.

Nella terminologia C4, un container è qualsiasi unità deployabile o eseguibile separatamente: qualcosa che esegue codice o memorizza dati, gira in un proprio processo (o ha un proprio ciclo di vita di storage) e che in linea di principio potrebbe essere distribuito indipendentemente dal resto del sistema.

Quella definizione copre cose come:

  • Una single-page application (React, Vue, Angular) in esecuzione nel browser dell'utente
  • Una web application lato server (Next.js, Rails, Django)
  • Una applicazione mobile (app iOS, app Android)
  • Un servizio API backend (API in Go, server Node.js, servizio Spring Boot)
  • Un database (PostgreSQL, MongoDB, MySQL)
  • Una cache (Redis, Memcached)
  • Un message broker o coda (Kafka, RabbitMQ, SQS)
  • Un worker in background o un processo di job pianificato
  • Un file o blob store (bucket S3, MinIO)
  • Una funzione serverless (AWS Lambda, Cloud Functions)

Il criterio di prova è semplice: gira in un proprio processo o detiene dati propri? Due package Go compilati in un unico binario appartengono allo stesso container. Due servizi distribuiti indipendentemente sono due container -- anche se condividono un repository.

Per una definizione di riferimento sintetica, vedi la voce sul diagramma di container nel nostro glossario.

Un container C4 non è un container Docker

Questo è il singolo punto di confusione più comune, quindi mettiamolo in chiaro esplicitamente.

Il modello C4 precede l'adozione mainstream di Docker, e la parola "container" in C4 significa qualcosa di più ampio: un blocco costitutivo del tuo sistema a livello di runtime. La sovrapposizione con Docker è casuale e parziale:

  • Un container C4 potrebbe girare dentro un container Docker. La tua API in Go probabilmente lo fa.
  • Un container C4 potrebbe girare come un semplice processo del sistema operativo, una scheda del browser, un'app mobile o un servizio cloud gestito. Nessuno di questi è un container Docker.
  • Un singolo container Docker potrebbe persino ospitare più container C4 (un'app più un database incorporato in un'immagine di sviluppo), anche se è insolito.

Detto altrimenti: i container Docker sono una tecnologia di packaging e deployment. I container C4 sono un'astrazione architetturale. Una SPA React in esecuzione in Chrome è un container C4 e non sarà mai un container Docker. Un'istanza PostgreSQL su RDS è un container C4 e Docker non si vede da nessuna parte.

Quando etichetti una scatola come "container" in un diagramma C4, stai dicendo "questa è una parte del mio sistema eseguibile o deployabile separatamente" -- niente di più.

Cosa deve contenere un diagramma di container

Un buon diagramma di container mostra esattamente tre categorie di informazioni:

1. I container stessi

Ogni unità deployabile o eseguibile all'interno del perimetro del tuo sistema, ciascuna etichettata con il suo nome, la sua responsabilità e la sua scelta tecnologica: "Order Service (Go)", "Session Cache (Redis)", "Web App (React SPA)". L'etichetta tecnologica non è una decorazione -- è metà del valore del diagramma. È ciò che permette a un nuovo ingegnere o a un team di piattaforma di ragionare sul sistema senza aprire dodici repository.

2. Le relazioni e i protocolli

Frecce tra i container, ciascuna etichettata con ciò che scorre e come: "legge/scrive ordini (SQL)", "pubblica eventi (AMQP)", "effettua chiamate API (HTTPS/JSON)". I protocolli di comunicazione contano a questo livello perché guidano gli aspetti operativi -- policy di rete, budget di latenza, semantica dei retry, modalità di guasto.

3. Il contesto immediato

Gli utenti e i sistemi esterni dal tuo diagramma di contesto, tenuti ai bordi così che il lettore possa vedere come le richieste entrano ed escono dal sistema. Non li ridocumenti in dettaglio; sono ancoraggi.

A chi è destinato questo diagramma?

Il pubblico del diagramma di container è tecnico: sviluppatori che entrano nel team, architetti che prendono decisioni strutturali e ingegneri operations/piattaforma che pianificano deployment, monitoraggio e capacità. È il livello in cui conversazioni come "questi due servizi dovrebbero condividere un database?" o "cosa si rompe se Redis va giù?" accadono davvero. Gli stakeholder non tecnici dovrebbero invece guardare il diagramma di contesto.

Cosa NON deve contenere

  • Moduli, classi o package interni -- quelli vivono nel diagramma di componenti (livello 3)
  • Dettagli infrastrutturali come load balancer, VPC, nodi Kubernetes -- quelli appartengono a un diagramma di deployment
  • Ogni micro-interazione -- se una relazione non è architetturalmente significativa, lasciala fuori

Esempio di diagramma di container: un prodotto web SaaS

Costruiamo un esempio completo di diagramma di container per un prodotto SaaS fittizio -- "InvoiceHub", uno strumento di fatturazione web. Questa forma (SPA + API + database + cache + worker + coda) descrive una grossa fetta dei prodotti web reali, quindi probabilmente puoi adattarla direttamente.

I container

Container Tecnologia Responsabilità
Web Application React SPA L'interfaccia che i clienti usano per creare e inviare fatture
API Application Go (Fiber) Logica di business, autenticazione, API REST consumata dalla SPA
Database PostgreSQL Sistema di registrazione per account, fatture, pagamenti
Cache Redis Memorizzazione delle sessioni e caching sul percorso caldo dei riepiloghi fatture
Message Queue RabbitMQ Disaccoppia il lavoro lento (rendering PDF, email) dalle richieste API
Background Worker Go Consuma i messaggi dalla coda: genera PDF, invia email, sincronizza gli stati di pagamento

Le relazioni

[Customer] --> [Web Application (React SPA)] : Uses (HTTPS)
[Web Application] --> [API Application (Go)] : Makes API calls (HTTPS/JSON)
[API Application] --> [Database (PostgreSQL)] : Reads/writes invoices and accounts (SQL/TCP)
[API Application] --> [Cache (Redis)] : Reads/writes sessions and cached summaries (RESP)
[API Application] --> [Message Queue (RabbitMQ)] : Publishes invoice.created, email.requested (AMQP)
[Background Worker (Go)] --> [Message Queue] : Consumes jobs (AMQP)
[Background Worker] --> [Database (PostgreSQL)] : Updates job and payment status (SQL/TCP)
[Background Worker] --> [Email Service (SendGrid)] : Sends invoice emails (HTTPS/REST)
[API Application] --> [Payment Gateway (Stripe)] : Creates payment links, receives webhooks (HTTPS/REST)

Cosa ti dice questo diagramma

Rileggi quell'elenco e nota quante domande concrete di ingegneria risponde:

  • Dove vive lo stato? In due posti: PostgreSQL (durevole) e Redis (effimero). Se ti sei mai chiesto se le sessioni sopravvivono a un riavvio di Redis, il diagramma rende visibile la domanda.
  • Qual è il raggio d'impatto di un guasto? Il worker e l'API condividono il database. Se RabbitMQ va giù, le fatture vengono comunque create ma le email si accodano -- per design.
  • Quali sono i confini di fiducia? La SPA gira su dispositivi client non attendibili; tutto ciò che può fare passa per l'autenticazione dell'API.
  • Cosa serve far girare a ops? Sei cose, con i loro protocolli. È la tua checklist di monitoraggio e all'incirca il tuo file docker-compose.

Un nuovo sviluppatore può assimilare tutto questo in due minuti. È l'intero senso del livello 2 del modello C4.

Errori comuni nei diagrammi di container

La maggior parte dei diagrammi di container fallisce in uno di pochi modi prevedibili.

Confondere i container con i componenti

Se il tuo diagramma di container mostra "OrderController", "InvoiceRepository" o "AuthMiddleware", hai zoomato un livello troppo in profondità. Quelli sono componenti -- blocchi costitutivi interni dentro un container -- e appartengono a un diagramma di componenti di livello 3. Il test: può essere distribuito o eseguito da solo? Una classe repository non può. Mantieni ogni diagramma a un solo livello di zoom; mescolare i livelli è il modo più rapido per produrre un diagramma illeggibile.

Omettere i data store

I team spesso disegnano solo le cose per cui hanno scritto codice e dimenticano che anche database, cache e code sono container. Un diagramma di container senza i suoi data store nasconde esattamente l'informazione di cui architetti e ingegneri ops hanno più bisogno: dove vive lo stato, cosa è condiviso, cosa è un single point of failure. Se il tuo sistema usa PostgreSQL, Redis e S3, tutti e tre vanno nel diagramma.

Disegnare il deployment invece della struttura di runtime

Un diagramma di container non è un diagramma di infrastruttura. Load balancer, pod Kubernetes, auto-scaling group, availability zone e il numero di repliche sono questioni di deployment -- C4 ha un diagramma di deployment supplementare separato per quelle. Il diagramma di container risponde a "quali sono i pezzi logici di runtime e come dialogano?", non a "quante istanze girano e dove?". Disegnare tre scatole "API" identiche perché esegui tre repliche aggiunge rumore, non informazione.

Relazioni senza etichetta o vaghe

Una freccia che dice solo "usa" spreca il potenziale del diagramma. "Effettua chiamate API (HTTPS/JSON)", "pubblica eventi ordine (AMQP)", "legge/scrive sessioni (RESP)" -- il verbo e il protocollo trasformano un'immagine in documentazione.

Lasciarlo marcire

L'errore più dannoso non è affatto sul diagramma. Un diagramma di container disegnato diciotto mesi fa che mostra ancora il monolite che da allora hai suddiviso in quattro servizi fuorvia attivamente ogni nuovo lettore. Una documentazione di architettura obsoleta è peggio di nessuna -- ecco perché mantenere il diagramma sincronizzato con il codice conta più di quanto sia bello.

Come creare un diagramma di container

Manualmente

Puoi costruire un solido diagramma di container in meno di un'ora:

  1. Parti dal tuo diagramma di contesto. Tieni utenti e sistemi esterni ai bordi.
  2. Elenca le tue unità deployabili. Passa in rassegna i tuoi repository, il tuo file docker-compose, la tua console cloud. Tutto ciò che gira come proprio processo o memorizza dati è un candidato.
  3. Aggiungi i data store esplicitamente. Database, cache, code, blob storage.
  4. Disegna le relazioni. Per ogni coppia di container che comunica, aggiungi una freccia con una locuzione verbale e un protocollo.
  5. Etichetta le tecnologie. Nome e tecnologia in ogni scatola.
  6. Rivedi con il team. La discussione che questo innesca ("aspetta, il worker parla con Stripe direttamente?") di solito vale più del diagramma stesso.

Qualsiasi strumento va bene -- Structurizr, PlantUML con l'estensione C4, draw.io, persino una lavagna. La notazione conta molto meno del contenuto e della disciplina di mantenerlo aggiornato.

Con Archyl

L'approccio manuale ha una debolezza strutturale: cattura un'istantanea, e il software non sta fermo. Archyl affronta il diagramma di container dalla direzione opposta -- deriva il modello dal codice:

  • AI discovery dal tuo codice. Collega un repository e la AI discovery di Archyl analizza la struttura del codice, la configurazione e i manifest delle dipendenze per proporre una bozza di modello C4 -- sistemi, container, componenti e le relazioni tra di essi. Tu rivedi e approvi i suggerimenti invece di disegnare scatole a memoria.
  • La drift detection mantiene l'onestà. Una volta che il modello esiste, Archyl confronta di continuo i container documentati con ciò che il codice mostra realmente e fa emergere un punteggio di drift. Quando qualcuno suddivide un servizio o sostituisce RabbitMQ con Kafka, lo scopri dalla dashboard, non da una sessione di onboarding confusa sei mesi dopo.
  • Architecture as Code. Preferisci il testo? Puoi definire il tuo modello C4 completo -- container, tecnologie, relazioni -- in YAML, versionarlo insieme al codice e lasciare che Archyl generi i diagrammi interattivi. Le modifiche ai diagrammi passano per le pull request come tutto il resto.

In entrambi i casi, l'obiettivo è lo stesso: un diagramma di container che sia accurato oggi e ancora accurato il prossimo trimestre.

FAQ

Un container C4 è la stessa cosa di un container Docker?

No. Un container C4 è un'astrazione architetturale: qualsiasi unità deployabile o eseguibile separatamente di un sistema, come una web app, un'API, un database o un message broker. Un container Docker è una tecnologia di packaging. Molti container C4 vengono distribuiti come container Docker, ma molti no -- una SPA React gira in un browser, un'app mobile gira su un telefono e un database gestito gira come servizio cloud. Il nome condiviso è uno sfortunato incidente della storia.

Cos'è il livello 2 del modello C4?

Il livello 2 del modello C4 è il diagramma di container. Zooma in un singolo sistema software (l'unica scatola del diagramma di contesto di livello 1) e mostra le unità deployabili/eseguibili al suo interno, le loro scelte tecnologiche e i protocolli che usano per comunicare. Si colloca tra il diagramma di contesto (livello 1) e il diagramma di componenti (livello 3).

Quanti container dovrebbe mostrare un diagramma di container?

Non esiste una regola rigida, ma la leggibilità degrada rapidamente oltre i 15-20 container. Se il tuo sistema ne ha genuinamente di più, suddividi la vista: un diagramma di container per sottosistema, oppure raggruppa visivamente i container correlati. Se ne hai centinaia, probabilmente stai documentando più sistemi e ti servono modelli C4 separati collegati a livello di contesto.

Ogni microservizio dovrebbe essere un container separato?

Sì -- per definizione. Ogni servizio distribuibile indipendentemente è un proprio container, insieme al database di ciascun servizio se segui il pattern database-per-service. È anche un utile test del cattivo odore: se i tuoi "microservizi" non possono essere disegnati come container separati perché condividono un processo o non possono essere distribuiti indipendentemente, potrebbero essere un monolite distribuito.


Pronto a generare il tuo diagramma di container invece di disegnarlo? Prova Archyl gratis e ottieni un modello C4 dal tuo codice in pochi minuti. Continua a esplorare la serie C4: Cos'è il modello C4? Una guida completa | Guida al diagramma di Contesto di Sistema C4 | Guida al diagramma di Componenti C4.