C4 Model na prática: Container Diagram (Parte 2)
No post anterior vimos o Context Diagram: o sistema como caixa preta, mostrando só quem usa e com o que ele se comunica. Agora vamos abrir essa caixa.
O que é o Container Diagram
O Container Diagram responde: como o sistema é composto tecnicamente?
Aqui “container” não tem nada a ver com Docker. No C4 Model, container é qualquer coisa que precisa estar rodando pra o sistema funcionar: uma aplicação web, uma API, um banco de dados, uma fila de mensagens, um serviço mobile. O diagrama mostra:
- Containers que compõem o sistema (aplicações, serviços, bancos, filas)
- Tecnologia de cada container (linguagem, framework, protocolo)
- Relações entre eles, incluindo a tecnologia de comunicação
- Os atores e sistemas externos do Context Diagram, agora se conectando a containers específicos em vez de ao sistema como um todo
É o diagrama mais útil no dia a dia de um time técnico. Onboarding de um novo engenheiro, discussão de uma mudança de infraestrutura, revisão de arquitetura: o Container Diagram costuma ser o ponto de partida.
As macros do Container Diagram
A biblioteca C4-PlantUML usa C4_Container.puml em vez do C4_Context.puml visto na Parte 1. Person, System_Ext e Rel continuam do jeito que já vimos. Três coisas novas entram em cena.
Container
Container(alias, "Label", "Technology", "Description")
Representa uma aplicação ou serviço: um frontend, uma API, um worker.
alias: identificador interno, sem espaços"Label": nome exibido"Technology": stack usada (ex:"Vue.js","PHP / Symfony")"Description": o que esse container faz
Container(api, "API Service", "PHP / Symfony", "Endpoints REST pro frontend e pro CMS")
ContainerDb
ContainerDb(alias, "Label", "Technology", "Description")
Mesma coisa que Container, mas renderizado com o ícone de cilindro: a convenção visual pra banco de dados ou qualquer armazenamento persistente.
ContainerDb(content_db, "Content Database", "PostgreSQL", "Artigos, posts, categorias e comentários")
Existe também
ContainerQueue, pro caso de fila de mensagens (Kafka, RabbitMQ, SQS). Mesma sintaxe, ícone diferente.
System_Boundary
System_Boundary(alias, "Label") {
' containers aqui dentro
}
Agrupa visualmente os containers que pertencem ao seu sistema, desenhando uma borda ao redor deles. Não é obrigatório, mas ajuda a deixar claro onde termina o seu sistema e onde começam as dependências externas, principalmente quando o diagrama tem vários containers.
System_Boundary(sb, "Blog Platform") {
Container(frontend, "Frontend SPA", "Vue.js", "Interface pública de leitura")
ContainerDb(content_db, "Content Database", "PostgreSQL", "Artigos e comentários")
}
Rel, de novo
Rel já foi coberto na Parte 1, mas aqui o parâmetro de tecnologia importa de verdade:
Rel(frontend, api, "Busca artigos e comentários", "HTTPS/REST JSON")
No Context Diagram, tecnologia era ruído. No Container Diagram, é a informação mais importante da relação: é o que diz pra um engenheiro como as peças conversam entre si.
Exemplo completo: Blog
Pegando o mesmo sistema da Parte 1 e abrindo a caixa:
@startuml blog
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
title "Blog Platform - Container Diagram"
Person(reader, "Reader", "Pessoa que lê os posts do blog")
Person(author, "Author", "Pessoa que escreve os posts")
System_Boundary(sb, "Blog Platform") {
Container(frontend, "Frontend SPA", "Vue.js", "Interface pública onde leitores navegam pelos artigos")
Container(cms, "CMS Admin", "Vue.js / Nuxt", "Painel administrativo onde autores criam e gerenciam conteúdo")
Container(api, "API Service", "PHP / Symfony", "Endpoints REST pro frontend e pro CMS")
Container(cdn, "CDN", "Cloudflare", "Serve assets estáticos e mídia em cache pros leitores")
ContainerDb(content_db, "Content Database", "PostgreSQL", "Artigos, posts, categorias e comentários")
ContainerDb(storage, "File Storage", "Amazon S3", "Imagens e arquivos de mídia")
}
System_Ext(email, "SendGrid", "Serviço de envio de e-mails de notificação")
Rel(reader, frontend, "Lê artigos e posts", "HTTPS")
Rel(author, cms, "Cria e gerencia conteúdo", "HTTPS")
Rel(frontend, api, "Busca artigos e comentários", "HTTPS/REST JSON")
Rel(cms, api, "Cria, atualiza e publica conteúdo", "HTTPS/REST JSON")
Rel(api, content_db, "Lê e escreve artigos, posts e comentários", "TCP/SQL")
Rel(api, storage, "Envia e busca arquivos de mídia", "HTTPS/AWS SDK")
Rel(api, email, "Envia e-mails de notificação de comentários", "HTTPS/REST")
Rel(cdn, storage, "Busca e cacheia arquivos de mídia da origem", "HTTPS")
Rel(frontend, cdn, "Carrega assets estáticos e mídia via CDN", "HTTPS")
@enduml
O que era uma caixa única no Context Diagram virou seis containers: dois frontends, uma API, uma CDN e dois armazenamentos. Reader e Author continuam presentes, mas agora cada um fala com um container específico, não com “o Blog” genericamente. E aparece um detalhe que não existia antes: o SendGrid, que na Parte 1 nem chegou a aparecer, porque quem se comunica com ele é a API, um detalhe interno demais pro nível de Context.
O que colocar e o que deixar de fora
Coloca:
- Todo container que roda de forma independente (aplicação, serviço, banco, fila)
- A tecnologia de cada container
- A tecnologia/protocolo de cada relação
- Sistemas externos que se conectam a containers específicos (agora fica claro qual container conversa com eles)
Não coloca:
- Múltiplas instâncias do mesmo container (load balancer com 5 réplicas da API é 1
Containerno diagrama, não 5) - Classes, funções, estrutura interna de um container (isso é nível de Component)
- Detalhes de infraestrutura de deploy (Kubernetes, VPC, região): isso não é C4, é diagrama de infraestrutura
A regra prática: se a resposta pra “isso precisa rodar separado dos outros?” for sim, é um container. Se não, é detalhe demais pra esse nível.
O que vem a seguir
No próximo post entro no Component Diagram, abrindo um container específico (a API, por exemplo) e mostrando como ele é organizado por dentro: controllers, services, repositories.
Os exemplos desse post estão no repositório github.com/wander4747/c4model, na pasta container/.
Container Diagram é onde a maioria das conversas técnicas realmente acontece. Não é abstrato demais pra perder o ponto, nem detalhado demais pra virar código. É o meio-termo que funciona.