diagrams Custom 自定义节点指南:用任意图片快速绘制自定义架构图
【免费下载链接】diagrams:art: Diagram as Code for prototyping cloud system architectures项目地址: https://gitcode.com/GitHub_Trending/di/diagrams
diagrams 是一个「图即代码」(Diagram as Code)开源项目,你用几行 Python 就能画出云架构图。它的图标库覆盖了 AWS、Azure、GCP、Kubernetes 等主流组件,但总有一些自研中间件、内部系统找不到对应图标。Custom 自定义节点就是为此设计的:传入一张本地图片或网络下载的图片,它就能作为节点图标出现在你的架构图里,最终由 Graphviz 渲染成 PNG/SVG 等格式。
什么时候需要 Custom 自定义节点
内置节点库再全,也覆盖不了你的业务组件。想象一下这些场景:
- 你的公司有一套自研消息总线,图标库里根本没有它;
- 某个开源工具(比如某品牌的 Broker、网关)有官方 logo,但 diagrams 还没收录;
- 你给团队画内部服务拓扑,需要把「任务调度中心」「报表服务」这类业务系统画进图里。
这时你不需要等上游收录,diagrams.custom.Custom类允许你把任意一张图片直接作为节点图标,缺口立刻补上。它和内置节点一样继承自Node,能参与所有连线操作符,所以和现成节点混用时毫无违和感。
五分钟画出第一张自定义架构图
先备齐运行环境,三样东西缺一不可:
- Python 3.7 以上(当前版本声明为 ^3.9);
- 系统级的 Graphviz 程序(macOS 用 Homebrew、Windows 用 Chocolatey 均可);
- 库本体:
pip install diagrams。
假设你把图标放在./icons/目录下,写一个最小脚本first_diagram.py:
from diagrams import Diagram from diagrams.custom import Custom with Diagram("内部消息链路", show=False, filename="first_diagram"): gateway = Custom("API 网关", "./icons/gateway.png") consumer = Custom("消费服务", "./icons/consumer.png") gateway >> consumerpython first_diagram.py之后,当前目录会多出一张first_diagram.png。就这么简单,你已经画出了第一张含自定义图标的架构图。
三个值得留意的细节:
show=False表示只存图、不弹窗预览,适合脚本化产出;filename不带扩展名,默认输出 png,也可以用outformat换成 svg、pdf 等;- 节点创建在
with Diagram(...)块内,这个约束后面排查报错时还会用到。
原理一句话:Custom把图标路径原样写进 Graphviz 节点的image属性,同时给节点加上shape=none让图标取代默认方框;标签里每多一个换行\n,节点高度自动加 0.4,避免文字和图标叠在一起。真正的图片读取发生在with块退出、Graphviz 开始渲染的那一刻——所以图标只要在渲染前存在于磁盘上就行。
图标从哪来
本地图片:路径直接传给 Custom
这是最直接的用法。图标已经在你机器上(设计同事给的 logo、自己画的 png),把相对或绝对路径作为第二个参数传进去即可:
from diagrams import Diagram, Cluster from diagrams.custom import Custom with Diagram("数据平台依赖", show=False, filename="local_icons", direction="LR"): scheduler = Custom("任务调度\n中心", "./icons/scheduler.png") with Cluster("计算层"): workers = [Custom("Worker", "./icons/worker.png") - Custom("Worker", "./icons/worker.png") - Custom("Worker", "./icons/worker.png")] storage = Custom("对象存储", "./icons/storage.png") scheduler >> workers workers >> storage为什么强调路径?打个比方:你把文件放哪,Graphviz 就去哪找,它不会替你改路径。Custom不做任何路径拼接,所以相对路径是相对于「你运行脚本时所在的目录」,而不是脚本文件所在位置。把脚本拷到别处执行、或者在错误目录下跑,图标就会静默消失——这是新手踩坑最多的地方。
注意上面还顺带用了两种组合技巧:Cluster把三个 Worker 框成一个分组,-表示无向边(三者对等),而>>是带箭头的有向边。
网络图片:如何下载图标后再引用
如果图标托管在网站上,思路是「先下载成本地文件,再交给Custom」。Custom本身不发任何网络请求,网络下载只是把图标"本地化"的手段:
from urllib.request import urlretrieve from diagrams import Diagram from diagrams.custom import Custom # 先下载图标,渲染前文件必须就位 urlretrieve("https://example.com/icons/rabbitmq.png", "rabbitmq.png") urlretrieve("https://example.com/icons/consumer.png", "consumer.png") with Diagram("远程图标示例", show=False, filename="remote_icon"): broker = Custom("消息 Broker", "rabbitmq.png") worker = Custom("消费 Worker", "consumer.png") broker >> worker怎么做:调用urlretrieve(url, 文件名)把远程图片保存到当前目录,然后把本地文件名传给Custom。为什么必须这样:Graphviz 渲染时只认磁盘上的文件,image属性里写一个 http 地址它不会去下载。注意什么:下载动作要发生在渲染之前——放在with块之前(如示例)或块内、节点创建之前都可以;若脚本提前结束、文件还没落盘,图里对应的图标就会是空白。
官方文档中的远程图标示例渲染效果类似下面这张(用远程下载的图标拼出的节点架构):
让图更复杂:分组、扇出和混用
画到一定规模,光靠两个节点连线不够用了。三个进阶手段按使用频率排序。
用 Cluster 给节点分组
with Cluster("分组名"):块内的所有节点会被框进一个带标题的圆角矩形,视觉上表达"这些属于同一层/同一域"。上面的"计算层"就是例子。官方示例里也常用它把对等节点圈在一起:
列表扇出与聚合
连线算子支持列表,能一行替代 N 行重复代码:
a >> b:有向边,a 指向 b;a - b:无向边,无箭头;a >> [n1, n2, n3]:右侧是列表 =扇出,a 分别指向每个节点;[n1, n2, n3] >> b:左侧是列表 =聚合,每个节点分别指向 b。
前面scheduler >> workers(一个调度器连三个 Worker)和workers >> storage(三个 Worker 汇聚到存储)正好就是扇出 + 聚合的完整拓扑,两个表达式搞定。
与内置节点自由混用
Custom继承自Node,和Pod、Aurora等内置节点地位相同,可以无缝串进同一条连线链。比如"自定义消息队列 → 三个 K8s Worker":
from diagrams import Diagram, Cluster from diagrams.custom import Custom from diagrams.k8s.compute import Pod with Diagram("自定义与内置节点混用", show=False, filename="mixed"): with Cluster("消费集群"): consumers = [Pod("worker"), Pod("worker"), Pod("worker")] queue = Custom("消息队列", "rabbitmq.png") queue >> consumersqueue >> consumers一次扇出三条边,整张图里自定义图标和 Kubernetes 官方图标同台出现。官方文档的同类示例(Broker + Pod 消费集群)渲染效果如下:
常见报错与排查
遇到下面几种情况基本都能快速定位:
- 图标不显示,其他都正常:90% 是路径问题。
Custom相对路径基于"脚本运行目录",试试在图标所在目录执行脚本,或改用绝对路径确认。文件在磁盘上但路径拼错了,Graphviz 不报错,只是不画。 EnvironmentError: Global diagrams context not set up:节点跑到了with Diagram(...)块外面。Custom和所有节点一样必须在全局图上下文内创建,把节点创建语句挪回with块里即可。ValueError: "xxx" is not a valid direction:direction只接受TB/BT/LR/RL四种取值(对应 Graphviz 的 rankdir),outformat同理只认png/jpg/svg/pdf/dot。- 渲染完找不到
.dot中间文件:这是预期行为。Diagram在with块退出时渲染完图后会主动删除 Graphviz 中间文件,只留下最终图片,方便你直接分发产物。
参数速查
| 参数 | 所属 | 默认值 | 说明 |
|---|---|---|---|
name | Diagram | "" | 图标题;未指定filename时用它生成文件名 |
filename | Diagram | 由name生成 | 输出文件名,不带扩展名 |
direction | Diagram | LR | 布局方向:TB/BT/LR/RL |
show | Diagram | True | 渲染后是否打开图像预览 |
outformat | Diagram | png | 输出格式,可传列表一次出多格式 |
label | Custom | 必填 | 节点标签,\n换行,每换一行节点高度 +0.4 |
icon_path | Custom | 必填 | 图片路径,原样传给 Graphviz,相对运行目录 |
一句话总结
Custom 自定义节点是 diagrams 扩展图标库的标准入口:一张本地图片直接传路径,一张网络图片先urlretrieve落盘再传文件名,之后它就和内置节点一样能分组、扇出、聚合、连线。想动手试试,从官方文档 docs/nodes/custom.md 开始,实现源码在 diagrams/custom/init.py,更完整的组合玩法可继续翻 docs/getting-started/examples.md。
【免费下载链接】diagrams:art: Diagram as Code for prototyping cloud system architectures项目地址: https://gitcode.com/GitHub_Trending/di/diagrams
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考