Skip to content

Container diagram

Once you understand how your system fits in to the overall IT environment, a useful next step is to zoom in to the system boundary with a container diagram. In C4, a container is an application or a data store. For example, a server-side web application, a client-side single-page application, a desktop application, a mobile app, a database schema, a folder on a file system, an Amazon Web Services S3 bucket, etc.

The container diagram shows the high-level shape of the software architecture and how responsibilities are distributed across it. It also shows the major technology choices and how the containers communicate with one another. It’s a simple, high-level technology focussed diagram that is useful for software developers and support/operations staff alike.

Example

The following example demonstrates how to define a container diagram using the Python DSL.

from c4 import (
    Container,
    ContainerDb,
    ContainerDiagram,
    ContainerQueue,
    LayRight,
    Person,
    Rel,
    RelDown,
    RelUp,
    SystemBoundary,
)
from c4.renderers.plantuml import LayoutOptions


with ContainerDiagram() as diagram:
    customer = Person("customer", "Customer", "A customer")

    with SystemBoundary("c1", "Customer Information"):
        app = Container(
            "app",
            "Customer Application",
            "Javascript, Angular",
            "Allows customers to manage their profile",
        )
        customer_service = Container(
            "customer_service",
            "Customer Service",
            "Java, Spring Boot",
            "The point of access for customer information",
            tags="microService",
        )
        message_bus = ContainerQueue(
            "message_bus",
            "Message Bus",
            "RabbitMQ",
            "Transport for business events",
        )
        reporting_service = Container(
            "reporting_service",
            "Reporting Service",
            "Ruby",
            "Creates normalised data for reporting purposes",
            tags="microService",
        )
        audit_service = Container(
            "audit_service",
            "Audit Service",
            "C#/.NET",
            "Provides organisation-wide auditing facilities",
            tags="microService",
        )
        customer_db = ContainerDb(
            "customer_db",
            "Customer Database",
            "Oracle 12c",
            "Stores customer information",
            tags="storage",
        )
        reporting_db = ContainerDb(
            "reporting_db",
            "Reporting Database",
            "MySQL",
            "Stores a normalized version of all business data for ad hoc reporting purposes",
            tags="storage",
        )
        audit_store = Container(
            "audit_store",
            "Audit Store",
            "Event Store",
            "Stores information about events that have happened",
            tags="storage",
        )

        customer >> RelDown("Uses", "HTTPS") >> app
        app >> RelDown('Updates customer information using', 'async, JSON/HTTPS') >> customer_service  # fmt: off

        customer_service >> RelUp("Sends events to", "WebSocket") >> app
        customer_service >> RelUp('Sends customer update events to') >> message_bus  # fmt: off

        customer_service >> Rel("Stores data in", "JDBC") >> customer_db

        message_bus >> Rel('Sends customer update events to') >> [reporting_service, audit_service]  # fmt: off

        reporting_service >> Rel("Stores data in") >> reporting_db
        audit_service >> Rel("Stores events in") >> audit_store

    LayRight(reporting_service, audit_service)

    layout_options = (
        LayoutOptions()
        .add_element_tag(
            "microService",
            shape="EightSidedShape",
            bg_color="CornflowerBlue",
            font_color="white",
            legend_text="micro service\neight sided",
        )
        .add_element_tag(
            "storage",
            shape="RoundedBoxShape",
            bg_color="lightSkyBlue",
            font_color="white",
        )
        .show_person_outline()
        .show_legend()
    )

diagram_code = diagram.as_plantuml(layout_options=layout_options)
Generated PlantUML source
@startuml
' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally
!if %variable_exists("RELATIVE_INCLUDE")
    !include %get_variable_value("RELATIVE_INCLUDE")/C4_Container.puml
!else
    !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
!endif

AddElementTag("microService", $bgColor="CornflowerBlue", $fontColor="white", $shape=EightSidedShape(), $legendText="micro service\neight sided")
AddElementTag("storage", $bgColor="lightSkyBlue", $fontColor="white", $shape=RoundedBoxShape())

SHOW_PERSON_OUTLINE()

Person(customer, "Customer", "A customer")

System_Boundary(c1, "Customer Information") {
    Container(app, "Customer Application", "Javascript, Angular", "Allows customers to manage their profile")

    Container(customer_service, "Customer Service", "Java, Spring Boot", "The point of access for customer information", $tags="microService")

    ContainerQueue(message_bus, "Message Bus", "RabbitMQ", "Transport for business events")

    Container(reporting_service, "Reporting Service", "Ruby", "Creates normalised data for reporting purposes", $tags="microService")

    Container(audit_service, "Audit Service", "C#/.NET", "Provides organisation-wide auditing facilities", $tags="microService")

    ContainerDb(customer_db, "Customer Database", "Oracle 12c", "Stores customer information", $tags="storage")

    ContainerDb(reporting_db, "Reporting Database", "MySQL", "Stores a normalized version of all business data for ad hoc reporting purposes", $tags="storage")

    Container(audit_store, "Audit Store", "Event Store", "Stores information about events that have happened", $tags="storage")

    Rel_Down(customer, app, "Uses", "HTTPS")
    Rel_Down(app, customer_service, "Updates customer information using", "async, JSON/HTTPS")
    Rel_Up(customer_service, app, "Sends events to", "WebSocket")
    Rel_Up(customer_service, message_bus, "Sends customer update events to")
    Rel(customer_service, customer_db, "Stores data in", "JDBC")
    Rel(message_bus, reporting_service, "Sends customer update events to")
    Rel(message_bus, audit_service, "Sends customer update events to")
    Rel(reporting_service, reporting_db, "Stores data in")
    Rel(audit_service, audit_store, "Stores events in")
}

Lay_Right(reporting_service, audit_service)

SHOW_LEGEND()

@enduml

The PlantUML source can be rendered into the following diagram:

system context