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

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

ソースコード
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("User Request")
user_request
with Cluster(label="Raspberry Pi"):
= Nginx("Nginx Server")
nginx
with Cluster("REST API", direction="TB"):
= Flask("Flask")
flask = Python("Application")
python
>> Edge(label="80 port") >> nginx >> Edge(label="Proxy\n5000 port") >> flask
user_request
Diagramsをpipでインストールしておく
Diagramsはpipパッケージで配布されている。Python3で使うので、pip3
でインストールする:
pip3 install Diagrams
画像の余白を狭くする
デフォルトの画像出力だと、余白が広すぎる。Graphviz
がバックエンドとして使用されているので、Graphviz
の属性を調整して余白を変更することができる:

ソースコード
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("User Request")
user_request
with Cluster(label="Raspberry Pi"):
= Nginx("Nginx Server")
nginx
with Cluster("REST API", direction="TB"):
= Flask("Flask")
flask = Python("Application")
python
>> Edge(label="80 port") >> nginx >> Edge(label="Proxy\n5000 port") >> flask user_request
複雑なリレーション図もDiagramsで描ける

ソースコード
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):
= Person(
customer ="Personal Banking Customer", description="A customer of the bank, with personal bank accounts."
name
)
with SystemBoundary("Internet Banking System"):
= Container(
webapp ="Web Application",
name="Java and Spring MVC",
technology="Delivers the static content and the Internet banking single page application.",
description
)
= Container(
spa ="Single-Page Application",
name="Javascript and Angular",
technology="Provides all of the Internet banking functionality to customers via their web browser.",
description
)
= Container(
mobileapp ="Mobile App",
name="Xamarin",
technology="Provides a limited subset of the Internet banking functionality to customers via their mobile device.",
description
)
= Container(
api ="API Application",
name="Java and Spring MVC",
technology="Provides Internet banking functionality via a JSON/HTTPS API.",
description
)
= Database(
database ="Database",
name="Oracle Database Schema",
technology="Stores user registration information, hashed authentication credentials, access logs, etc.",
description
)
= System(name="E-mail System", description="The internal Microsoft Exchange e-mail system.", external=True)
email
= System(
mainframe ="Mainframe Banking System",
name="Stores all of the core banking information about customers, accounts, transactions, etc.",
description=True,
external
)
>> Relationship("Visits bigbank.com/ib using [HTTPS]") >> webapp
customer >> Relationship("Views account balances, and makes payments using") >> [spa, mobileapp]
customer >> Relationship("Delivers to the customer's web browser") >> spa
webapp >> Relationship("Make API calls to [JSON/HTTPS]") >> api
spa >> Relationship("Make API calls to [JSON/HTTPS]") >> api
mobileapp
>> Relationship("reads from and writes to") >> database
api >> Relationship("Sends email using [SMTP]") >> email
api >> Relationship("Makes API calls to [XML/HTTPS]") >> mainframe
api << Relationship("Sends e-mails to") << email customer
よく使うアイコン

ソースコード
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("User")
user_request = Users("Users")
users = Client("Client")
client = Mysql("MySQL")
mysql = Nginx("Nginx")
nginx = LetsEncrypt("LetsEncrypt")
letsEncrypt = Github("Github")
github
- users - client - mysql - nginx - letsEncrypt - github
user_request
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
- tablet - raspbian - ubuntu - windows - ios - android - datacenter - storage - router - firewall - vpn
mobile
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("C++")
cpp = Java("Java")
java = Javascript("Javascript")
javascript = Kotlin("Kotlin")
kotlin = Latex("Latex")
latex = Nodejs("Nodejs")
nodejs = Php("PHP")
php = Python("Python")
python = Swift("Swift")
swift
- database - decision - flask - laravel - bash - c - cpp - java - javascript - kotlin - latex - nodejs - php - python - swift
action
with Cluster("SaaS"):
= Cloudflare("Cloudflare")
cloudflare = Discord("Discord")
discord = Line("Line")
line = Slack("Slack")
slack
- discord - line - slack cloudflare
他にもたくさんアイコン画像が公開されている: - Diagrams Docs
オリジナル画像を入れる

https://github.com/mingrammer/diagrams/
ソースコード
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】OpenCVで画像をアフィン変換【移動・拡大・回転・剪断】
- fdupes で内容が重複しているファイルを見つける|シェル
- ImageMagickで画像加工|シェル
- 【Pythonでサムネ制作②】PILで画像の上に透過画像を重ねる
- 【Pythonでサムネ制作①】PILで画像の上に文字を重ねて中央表示