Diagramsを使ってサクッとインフラ図を描く【Python】

Diagramsを使ってサクッとインフラ図を描く【Python】
Diagramsを使ってサクッとインフラ図を描く【Python】

Diagramsの基本

PythonライブラリのDiagramsを使うと、こんな感じのインフラ図がサクッと描ける。

Diagramsの基本
Diagramsの基本

ソースコード

sample1.py
from diagrams import Cluster, Diagram, Edge
from diagrams.generic.os import Raspbian
from diagrams.onprem.client import User
from diagrams.onprem.network import Nginx
from diagrams.programming.framework import Flask
from diagrams.programming.language import Python

with Diagram("基本", show=False, outformat="png", filename="../sample1"):
    user_request = User("User Request")
    
    with Cluster(label="Raspberry Pi"):

        nginx = Nginx("Nginx Server")

        with Cluster("REST API", direction="TB"):
            flask = Flask("Flask")
            python = Python("Application")

            user_request >> Edge(label="80 port") >> nginx  >> Edge(label="Proxy\n5000 port") >> flask

Diagramsをpipでインストールしておく

Diagramsはpipパッケージで配布されている。Python3で使うので、pip3でインストールする:

zsh
pip3 install Diagrams

画像の余白を狭くする

デフォルトの画像出力だと、余白が広すぎる。Graphviz がバックエンドとして使用されているので、Graphviz の属性を調整して余白を変更することができる:

余白なし
余白なし

ソースコード

sample2.py
from diagrams import Cluster, Diagram, Edge
from diagrams.generic.os import Raspbian
from diagrams.onprem.client import User
from diagrams.onprem.network import Nginx
from diagrams.programming.framework import Flask
from diagrams.programming.language import Python

with Diagram("基本", show=False, outformat="png", filename="../sample2", direction="LR", graph_attr={"pad":"0.2,0.2"}):
    user_request = User("User Request")
    
    with Cluster(label="Raspberry Pi"):

        nginx = Nginx("Nginx Server")

        with Cluster("REST API", direction="TB"):
            flask = Flask("Flask")
            python = Python("Application")

            user_request >> Edge(label="80 port") >> nginx  >> Edge(label="Proxy\n5000 port") >> flask

複雑なリレーション図もDiagramsで描ける

C4を使った複雑な図
C4を使った複雑な図

ソースコード

c4.py
from diagrams import Diagram
from diagrams.c4 import Person, Container, Database, System, SystemBoundary, Relationship

graph_attr = {
    "splines": "spline",
    "pad":"0.2,0.2",
}

with Diagram("複雑な図", show=False, outformat="png", filename="../c4", direction="TB", graph_attr=graph_attr):
    customer = Person(
        name="Personal Banking Customer", description="A customer of the bank, with personal bank accounts."
    )

    with SystemBoundary("Internet Banking System"):
        webapp = Container(
            name="Web Application",
            technology="Java and Spring MVC",
            description="Delivers the static content and the Internet banking single page application.",
        )

        spa = Container(
            name="Single-Page Application",
            technology="Javascript and Angular",
            description="Provides all of the Internet banking functionality to customers via their web browser.",
        )

        mobileapp = Container(
            name="Mobile App",
            technology="Xamarin",
            description="Provides a limited subset of the Internet banking functionality to customers via their mobile device.",
        )

        api = Container(
            name="API Application",
            technology="Java and Spring MVC",
            description="Provides Internet banking functionality via a JSON/HTTPS API.",
        )

        database = Database(
            name="Database",
            technology="Oracle Database Schema",
            description="Stores user registration information, hashed authentication credentials, access logs, etc.",
        )

    email = System(name="E-mail System", description="The internal Microsoft Exchange e-mail system.", external=True)

    mainframe = System(
        name="Mainframe Banking System",
        description="Stores all of the core banking information about customers, accounts, transactions, etc.",
        external=True,
    )

    customer >> Relationship("Visits bigbank.com/ib using [HTTPS]") >> webapp
    customer >> Relationship("Views account balances, and makes payments using") >> [spa, mobileapp]
    webapp >> Relationship("Delivers to the customer's web browser") >> spa
    spa >> Relationship("Make API calls to [JSON/HTTPS]") >> api
    mobileapp >> Relationship("Make API calls to [JSON/HTTPS]") >> api

    api >> Relationship("reads from and writes to") >> database
    api >> Relationship("Sends email using [SMTP]") >> email
    api >> Relationship("Makes API calls to [XML/HTTPS]") >> mainframe
    customer << Relationship("Sends e-mails to") << email

よく使うアイコン

ソースコード

favorite.py
from diagrams import Cluster, Diagram, Edge

from diagrams.onprem.client import User
from diagrams.onprem.client import Client
from diagrams.onprem.client import Users
from diagrams.onprem.database import Mysql
from diagrams.onprem.certificates import LetsEncrypt
from diagrams.onprem.network import Nginx
from diagrams.onprem.vcs import Github

from diagrams.firebase.base import Firebase

from diagrams.generic.device import Mobile
from diagrams.generic.device import Tablet
from diagrams.generic.network import Firewall
from diagrams.generic.network import Router
from diagrams.generic.network import VPN
from diagrams.generic.os import Android
from diagrams.generic.os import IOS
from diagrams.generic.os import Raspbian
from diagrams.generic.os import Ubuntu
from diagrams.generic.os import Windows
from diagrams.generic.place import Datacenter
from diagrams.generic.storage import Storage

from diagrams.programming.flowchart import Action
from diagrams.programming.flowchart import Database
from diagrams.programming.flowchart import Decision
from diagrams.programming.framework import Flask
from diagrams.programming.framework import Laravel
from diagrams.programming.language import Bash
from diagrams.programming.language import C
from diagrams.programming.language import Cpp
from diagrams.programming.language import Java
from diagrams.programming.language import Javascript
from diagrams.programming.language import Kotlin
from diagrams.programming.language import Latex
from diagrams.programming.language import Nodejs 
from diagrams.programming.language import Php
from diagrams.programming.language import Python
from diagrams.programming.language import Swift

from diagrams.saas.cdn import Cloudflare 
from diagrams.saas.chat import Discord
from diagrams.saas.chat import Line
from diagrams.saas.chat import Slack

with Diagram("よく使うノードアイコン", show=False, outformat="png", filename="../favorite", direction="LR", graph_attr={"pad":"0.2,0.2"}):

    with Cluster("OnPrem"):
        user_request = User("User")
        users = Users("Users")
        client = Client("Client")
        mysql = Mysql("MySQL")
        nginx = Nginx("Nginx")
        letsEncrypt = LetsEncrypt("LetsEncrypt")
        github = Github("Github")

        user_request - users - client - mysql - nginx - letsEncrypt - github

    with Cluster("Firebase"):
        firebase = Firebase("Firebase")

    with Cluster("Generic"):
        mobile = Mobile("Mobile")
        tablet = Tablet("Tablet")
        raspbian = Raspbian("Raspbian")
        ubuntu = Ubuntu("Ubuntu")
        windows = Windows("Windows")
        ios = IOS("iOS")
        android = Android("Android")
        datacenter = Datacenter("Datacenter")
        storage = Storage("Storage")
        router = Router("Router")
        firewall = Firewall("Firewall")
        vpn = VPN("VPN")

        mobile - tablet - raspbian - ubuntu - windows - ios - android - datacenter - storage - router - firewall - vpn

    with Cluster("Programming"):
        action = Action("Action")
        database = Database("Database")
        decision = Decision("Decision")
        flask = Flask("Flask")
        laravel = Laravel("Laravel")
        bash = Bash("Bash")
        c = C("C")
        cpp = Cpp("C++")
        java = Java("Java")
        javascript = Javascript("Javascript")
        kotlin = Kotlin("Kotlin")
        latex = Latex("Latex")
        nodejs = Nodejs("Nodejs")
        php = Php("PHP")
        python = Python("Python")
        swift = Swift("Swift")

        action - database - decision - flask - laravel - bash - c - cpp - java - javascript - kotlin - latex - nodejs - php - python - swift

    with Cluster("SaaS"):
        cloudflare = Cloudflare("Cloudflare")
        discord = Discord("Discord")
        line = Line("Line")
        slack = Slack("Slack")

        cloudflare - discord - line - slack

他にもたくさんアイコン画像が公開されている:

オリジナル画像を入れる

オリジナル画像を入れる
オリジナル画像を入れる

GitHub - mingrammer/diagrams: :art: Diagram as Code for prototyping cloud system architectures

ソースコード

original.py
import os
from diagrams import Diagram, Edge
from diagrams.custom import Custom

# 現在のファイルのディレクトリを取得
current_dir = os.path.dirname(__file__)

# 画像ファイルへのパスを組み立てる
arduino_image_path = os.path.join(current_dir, "computer_one-board_microcomputer.png")
watering_image_path = os.path.join(current_dir, "watering-can.png")
plant_image_path = os.path.join(current_dir, "plant.png")

with Diagram("オリジナル画像を表示する", show=False, outformat="png", filename="../original", direction="LR", graph_attr={"pad":"0.2,0.2"}):
    arduino = Custom("Arduino", arduino_image_path)
    watering = Custom("Watering", watering_image_path)
    plant = Custom("Plant", plant_image_path)
    

    watering << Edge(label="Control") << arduino

    plant >> Edge(label="Notification") >> arduino

【注意】 画像を上の階層へ出力する場合、絶対パスでないと画像が表示されなかったため気をつけること。

関連記事

最後までご覧いただきありがとうございます!

▼ 記事に関するご質問やお仕事のご相談は以下よりお願いいたします。
お問い合わせフォーム

Python学習にオススメの本をご紹介!
Pandasでデータサイエンスはじめよう!
スクレイピングにオススメの書籍

▼ Beautiful Soup4を使ったWebクローリングをはじめ、表データをpandasやOpenPyXL、matplotでデータ解析、グラフ表示などのスクレイピングのやり方が分かりやすく説明されてます。図解が多いのでPython初心者の方でも読み進められる内容となってます。