Diagramsとは
DiagramsはDiagram as Codeの思想に基づいて開発されたツールで、アーキテクチャ図をコードによって表現することを目指しています。
特長としては
- コードベースなのでバージョン管理システムでの追跡が可能
- 主要なプロバイダーに対応
といった点があります。
準備
今回は以下の環境で実施しています
- wsl2(Ubuntu 22.04.4 LTS)
- python 3.12.11
- uv 0.7.19
開発環境の管理にmiseを利用しているため、mise.tomlに以下のように記述します。
[tools]
python = "3.12.11"
uv = "0.7.19"
mise installコマンドで必要なツールをインストールし、uv initコマンドでpythonプロジェクトを初期化、uv add diagramsコマンドで今回用いるdiagramsのパッケージをインストールします。
システムにGraphvizパッケージを導入するため、以下のコマンドを実行します。
sudo apt update && sudo apt install -y graphviz
Diagramsの使い方
Diagrams
Diagramはアーキテクチャ図のダイアグラム全体を表すコンテキストです。
Diagramには引数に以下のような値を指定できます。
- ダイアグラム名:第一引数にダイアグラム名を指定します。
-
show:実行時に作成された画像をシステムの画像ビューワーで自動的に開くかの設定。デフォルトでは
Trueです - filename:実行時に作成される画像のファイルの名前を指定します。拡張子は含みません
- outformat:実行時に作成される画像のファイル形式を指定します。png、jpg、svg、pdf、dot形式に対応しています
- graph_attr、node_attr、edge_attr:Graphvizの属性オプションをサポートしています
from diagrams import Diagram
from diagrams.gcp.compute import ComputeEngine
def main():
with Diagram("Basic Diagram", show=False, filename="basic_diagram", outformat="jpg"):
web_server = ComputeEngine("Web Server")
web_server
print("完了: 00_basic_diagram.jpg が生成されました")
if __name__ == "__main__":
main()
Nodes
Node
Node(ノード)とはシステムのコンポーネントを表す単位です。
1つのノードは1つのコンポーネントを抽象的に表します。例えば、Compute Engineはノードとして表現されます。
Diagramsは主要なクラウドプロバイダーのノードが用意されており、公式ページから参照することが可能です。主要な3サービスのリンクが以下です。リンク先の情報を参考にしてfrom diagrams.gcp.compute import ComputeEngineのように記述することで、この場合だと「ComputeEngine」をノードとして利用できます。
Data Flow
ノード間はデータフローによって接続を表現することができます。コードでusers >> web_server >> databaseとなっている部分がそれに相当し、次のような記号を用いることができます。
- >>:左から右方向への接続。イメージは「→」
- <<:右から左方向への接続。イメージは「←」
- -:無方向の接続。イメージは「-」
"""
基本的なNodes(ノード)の使用
"""
from diagrams import Diagram
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.onprem.client import Users
def main():
with Diagram("Basic Nodes", show=False, filename="01_basic_nodes"):
users = Users("Users")
web_server = ComputeEngine("Web Server")
database = SQL("Database")
users >> web_server >> database
print("完了: 01_basic_nodes.png が生成されました")
if __name__ == "__main__":
main()
またDiagram()にdirectionオプションを指定することで、アーキテクチャ図全体のデータフローの流れる向きを指定することができます。デフォルトではLRになっています。指定できるパラメータは次の通りです。
- TB:上から下への向き
- BT:下から上への向き
- LR:左から右への向き
- RL:右から左への向き
上記のコードのDiagram部分を一部修正し、TB向きのアーキテクチャ図を作成してみると以下のようになります。
with Diagram("Basic Nodes", show=False, filename="01_basic_nodes_TB", direction="TB"):
データフロー全体の流れる向きが変わっていることがわかります。
Data Flow(グループ)
データフローは、複数のノードを[]で囲むことによってグループ化することが可能です。サンプルのコードを少し修正してグループの例を示します。
この例では、ComputeEngineのWeb Serverが3台に増えてグループ化されています。
出力されたアーキテクチャ図を見てみると、Usersからグループ化された3つのWeb Serverに対してデータフローが繋がっており、それぞれのWeb Serverからデータベースにデータフローが繋がっていることがわかります。
このように複数のリソースをグループとして扱うことが可能です。
"""
基本的なNodes(ノード)の使用
"""
from diagrams import Diagram
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.onprem.client import Users
def main():
with Diagram("Basic Nodes", show=False, filename="01_basic_nodes"):
users = Users("Users")
web_server1 = ComputeEngine("Web Server")
web_server2 = ComputeEngine("Web Server 2")
web_server3 = ComputeEngine("Web Server 3")
database = SQL("Database")
users >> [web_server1, web_server2, web_server3] >> database
print("完了: 01_basic_nodes.png が生成されました")
if __name__ == "__main__":
main()
Clusters
Cluster(クラスター)はノードをまとめてクラスター化するための仕組みです。データフローのグループ化がデータの流れ(矢印・線)をまとめるものだったのに対し、クラスターはそこに含まれるノードを視覚的にグルーピングし、複数のノードが含まれた箱のような表現を提供します。
クラスターはwith Cluster("<ラベル名>"):のように記述します。
このクラスター以下に書かれたノードがそのクラスターに所属し、クラスターはネストすることもできます。
"""
クラスターを使ったグループ化
"""
from diagrams import Diagram, Cluster
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.gcp.network import LoadBalancing
from diagrams.gcp.storage import Storage
from diagrams.onprem.client import Users
def main():
with Diagram("Clusters with Grouping", show=False, filename="02_clusters"):
users = Users("Users")
# クラスターでグループ化
with Cluster("Google Cloud"):
load_balancer = LoadBalancing("Load Balancer")
with Cluster("Web Tier"):
web_servers = [
ComputeEngine("Web1"),
ComputeEngine("Web2")
]
with Cluster("Data Tier"):
database = SQL("Database")
storage = Storage("Storage")
# 接続の定義
users >> load_balancer
load_balancer >> web_servers
web_servers >> database
web_servers >> storage
print("完了: 02_clusters.png が生成されました")
if __name__ == "__main__":
main()
Edges
Edge(エッジ)はノード間の接続に関する表現を拡張する機能です。
ノード間の接続に対して次のような属性を拡張します
- ラベル
- 色
- スタイル
エッジは次のような書き方で表現します。>> Edge(label="HTTPS", color="blue", style="bold") >>
エッジの接続には>> Edge(~~) <<のように双方向の接続などを作成することも可能です。
"""
接続線の色、スタイル、ラベルを変更する例
"""
from diagrams import Diagram, Cluster, Edge
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.gcp.storage import Storage
from diagrams.onprem.client import Users
def main():
with Diagram("Custom Edges", show=False, filename="03_custom_edges"):
users = Users("Users")
with Cluster("System"):
web = ComputeEngine("Web Server")
db = SQL("Database")
cache = ComputeEngine("Cache")
storage = Storage("Files")
# 様々なエッジのスタイル
users >> Edge(label="HTTPS", color="blue", style="bold") >> web
web >> Edge(label="SQL", color="red") >> db
web >> Edge(label="Cache", color="green", style="dashed") >> cache
web >> Edge(label="Files", color="orange") >> storage
# 双方向のエッジ
cache << Edge(label="Sync", color="purple") >> db
print("完了: 03_custom_edges.png が生成されました")
if __name__ == "__main__":
main()
複合的なアーキテクチャ図
今までに説明したノード、クラスター、エッジを複合してアーキテクチャ図を作ってみます。
実際にクラウドアーキテクチャを設計する際にはこの例のように様々な要素を組み合わせることが想定されます。
"""
統合例: Nodes、Clusters、Edgesを全て活用
学習目的のためのシンプルなアーキテクチャ図
"""
from diagrams import Diagram, Cluster, Edge
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.gcp.network import LoadBalancing
from diagrams.gcp.storage import Storage
from diagrams.onprem.client import Users
def main():
with Diagram("Simple Architecture", show=False, filename="04_comprehensive"):
# 外部ユーザー
users = Users("Users")
# Google Cloudプラットフォーム
with Cluster("Google Cloud"):
# ロードバランサー
lb = LoadBalancing("Load Balancer")
# アプリケーション層
with Cluster("Web Layer"):
web1 = ComputeEngine("Web-1")
web2 = ComputeEngine("Web-2")
# データ層
with Cluster("Data Layer"):
database = SQL("Database")
storage = Storage("Storage")
# 基本的な接続(Nodes学習)
users >> lb
lb >> [web1, web2]
# カスタムエッジでの接続(Edges学習)
web1 >> Edge(label="SQL", color="red") >> database
web2 >> Edge(label="SQL", color="red") >> database
web1 >> Edge(label="Files", color="blue", style="dashed") >> storage
web2 >> Edge(label="Files", color="blue", style="dashed") >> storage
print("完了: 04_comprehensive.png が生成されました")
print("\nこの例では以下を学習できます:")
print("- Nodes: Users, LoadBalancing, ComputeEngine, SQL, Storage")
print("- Clusters: Google Cloud内のWeb LayerとData Layer")
print("- Edges: SQLとFilesの接続を色とスタイルで区別")
if __name__ == "__main__":
main()
この例では「users」と「Load Balancer」が単純なノードで接続されていることがわかります。
各種リソースはGoogle Cloudのプラットフォーム上に存在するため、「Google Cloud」クラスターを最上位レベルに記述しています。また、アーキテクチャで「Web Layer」レベルと「Data Layer」レベルのリソースをそれぞれクラスター化して記述しており、これらのクラスターは「Google Cloud」クラスター内にネストされた構造になっています。このようにクラスターはネストすることができ、これを活用することで見やすいアーキテクチャ設計の助けになります。
それぞれのサーバーがどのデータリソースに接続しているかを視覚的にわかりやすく表現するためにエッジ機能を活用しています。エッジのオプションを用いることで、接続の色や線の種類などがカスタムされ、より理解しやすいアーキテクチャ図になっています。
まとめ
今回はアーキテクチャ図を作成する手段として、Diagramsという例を紹介しました。
このツールの特長としては、主要なクラウドプロバイダーに対応していること、コードベースでアーキテクチャ図の記述ができることかと思います。
コードベースなのでGitHubなどのバージョン管理システムとの親和性が良く、変更差分も理解しやすいです。また、pythonベースですので多くのエンジニアにとって習得コストがそれほど大きくないかもしれないこともメリットになりそうです。
私も実務で活用していきたいと思います!最後までお読みいただきありがとうございました!
参考文献






