Background

Level 2: Container

6 min read

We've drawn the country. Now we zoom in to the cities. In the System Context diagram, our entire E-Commerce platform was a single box. The Container diagram is where we open that box for the very first time and reveal the high-level technical building blocks inside it — and how they fit together.

First things first: a "container" is not a Docker container

This is the single most common source of confusion for newcomers, so let's clear it up before we go any further.

In the C4 model, a container is a general term that predates Docker. It means any separately runnable or deployable unit that executes code or stores data. Think of it as "something you can start up or shut down on its own."

Concretely, a container is things like:

  • A server-side web application or backend API (a Spring Boot app, a Node.js service, a Django app)
  • A single-page application running in the browser (a React or Angular app)
  • A mobile app (iOS or Android)
  • A desktop application
  • A database (PostgreSQL, MySQL, MongoDB)
  • A file system, blob store, or object store (e.g. Amazon S3)
  • A message bus or queue (RabbitMQ, Kafka)
  • A serverless function

A Docker container can be one of these, but so can a process that never goes anywhere near Docker. Don't let the naming collision trip you up: a C4 container is about deployability and runnability, not about any particular containerization technology.

What the Container diagram shows

The Container diagram answers the questions a developer or ops engineer asks on day one:

  1. What are the major moving parts? (The applications, services, and data stores.)
  2. What is each one built with? (The key technology choices — language, framework, database engine.)
  3. How do they communicate? (The protocols and connections between them — HTTPS, SQL, JSON/REST, etc.)

This is the first C4 level where real technology decisions appear. At Level 1 we deliberately said nothing about React or PostgreSQL; here, those choices are the whole point. You're drawing the high-level shape of the software architecture and showing how responsibilities are distributed across the deployable units.

Everything still lives inside your system's boundary — we're zoomed into that one box from Level 1 — but the people and external systems from the Context diagram usually reappear around the edges, so the diagram stays connected to the wider world.

Who is this diagram for?

The audience narrows compared to Level 1. The Container diagram is aimed at a technical audience: software developers, architects, support staff, and IT operations. It's the diagram you'd sketch on a whiteboard when explaining the system to a new engineer, or when the ops team needs to understand what actually gets deployed and how the pieces talk to each other. A non-technical stakeholder generally won't need to go this deep.

The building blocks

The Container diagram introduces one new element and reuses the familiar ones:

  • 📦 Container — a deployable/runnable unit, labelled with its name, its technology (in brackets or parentheses), and a short description of its responsibility. For data stores, it's conventional to draw them in a distinguishable shape (Mermaid uses ContainerDb).
  • 🧍 Person and 🏢 External System — carried over from the Context diagram, sitting outside your system's boundary.
  • A system boundary — a dashed box drawn around all your containers, making it visually obvious where "our system" starts and stops.

As always, relationships are labelled arrows — and here they gain extra value by naming the protocol or technology of the interaction ("Makes API calls to [JSON/HTTPS]").

A worked example: inside the E-Commerce platform

Let's open up the E-Commerce System box from Level 1. Inside, we find three containers: a browser-based web app, a backend API, and a database. The external Payment Gateway from the Context diagram is still here — but now we can see which specific container talks to it.

C4Container
title Container Diagram - E-Commerce Platform
Person(customer, "Customer", "A customer who browses and buys products online.")
System_Ext(payment_gateway, "Payment Gateway", "Processes credit card payments.")
System_Boundary(ecommerce_boundary, "E-Commerce System") {
  Container(web_app, "Web Application", "React", "Delivers the single page application.")
  Container(api, "Backend API", "Node.js", "Provides e-commerce functionality.")
  ContainerDb(db, "Database", "PostgreSQL", "Stores user profiles and products.")
}
Rel(customer, web_app, "Visits", "HTTPS")
Rel(web_app, api, "Makes API calls to", "JSON")
Rel(api, db, "Reads and writes to", "SQL")
Rel(api, payment_gateway, "Makes API calls to", "HTTPS")

Read it as a story again: the Customer visits the Web Application (a React SPA) over HTTPS. That web app makes JSON API calls to the Backend API (Node.js). The API reads and writes to the Database (PostgreSQL) using SQL, and makes HTTPS calls out to the external Payment Gateway when it's time to take payment.

Notice how much more a developer now understands than they did at Level 1 — the tech stack, the deployment units, the data flow — while the diagram still fits comfortably on one screen. That balance is the sweet spot of the Container diagram, and it's why many teams find Levels 1 and 2 together are all the architecture documentation they ever really need.

A note on microservices

If your system is built from microservices, each service is typically its own container, and each will usually have its own datastore. A Container diagram is an excellent way to show a microservices architecture at a glance — though if you have dozens of services, resist the urge to cram all of them onto one page. It's often clearer to show the key services relevant to the story you're telling, and lean on the System Landscape diagram for the enterprise-wide picture.

Common beginner mistakes

  • Confusing containers with Docker. Worth repeating one more time: it's about deployable/runnable units, not containerization tech.
  • Drawing components instead of containers. If you're tempted to show the internal classes or modules inside the Backend API, that's Level 3. Keep this diagram at the "deployable unit" altitude.
  • Omitting the technology. "Backend API" tells a reader less than "Backend API [Node.js]." The tech choice is a headline feature of this level — include it.
  • Unlabelled or protocol-less arrows. Say both what the interaction is and how it happens ("Reads and writes to [SQL]").

Where we're headed

We've now seen the cities of our system and the roads between them. But what happens inside one of those containers? How is the Backend API actually organized internally? To answer that, we zoom in one more level and walk the streets. That's the Component diagram.


Previous: ← Level 1: System Context · Next: Level 3: Component →