PlantUML 自部署:从 plantuml.jar 到 Docker 到企业内网

puml.online

当 plantuml.com 在线服务因为网络抖动/安全策略不可用时,可以自部署 PlantUML 渲染服务。这篇整理三种方案:本地 jar、Docker、企业自建。

三种部署方式

方案 适用 启动时长
plantuml.jar 本地 偶尔用、CI 临时 <2s
Docker 镜像 团队共享/CI 长期 <5s
plantuml-server 微服务 编辑器集成 / 服务调用 <10s

方案 1:plantuml.jar 本地

最简单,一次性下载一个 jar 文件就能用:

1
2
3
4
5
6
7
8
9
10
11
# 下载(约 19 MB)
curl -L -o plantuml.jar https://github.com/plantuml/plantuml/releases/download/v1.2026.7/plantuml-1.2026.7.jar

# 单文件渲染
java -jar plantuml.jar diagram.puml

# SVG 输出
java -jar plantuml.jar -tsvg diagram.puml

# 批量渲染
java -jar plantuml.jar -tsvg -failfast2 -nometadata docs/**/*.puml

优点

  • 0 配置,0 依赖(除了 Java)
  • 可以放进 Docker 镜像里
  • CI 直接调用

缺点

  • 启动慢(Java 冷启动 ~ 10s)
  • 不支持 HTTP API,需要 CLI
  • 1 个 jar 只能跑 1 件事

CI 集成

1
2
3
4
5
# GitHub Actions
- name: Render PlantUML
run: |
curl -L -o plantuml.jar https://github.com/plantuml/plantuml/releases/latest/download/plantuml.jar
java -jar plantuml.jar -tsvg -nometadata -o rendered/ source/**/*.puml

方案 2:Docker 镜像

最常见,最稳,团队可以共享:

1
2
3
4
docker run -d \
--name plantuml-server \
-p 8080:8080 \
plantuml/plantuml-server:latest

启动后访问 http://localhost:8080/,Web UI 自动展示。

API 端点

1
2
3
GET  http://localhost:8080/svg/<encoded>      # 同步 SVG
POST http://localhost:8080/form # 表单上传
GET http://localhost:8080/png/<encoded> # 同步 PNG

例子:

1
2
# encoded URL
curl http://localhost:8080/svg/SoWkIImgAStDuKh9IArEB-tWmyoStDpKiCLCmKeoZDGm7mwU5XH4e1NLWfG6S3U3AYXvDQG7WQpyLOqpCgN94fXAvuYAcd4oC8j4aIWfWGfGQUa_AvBlLf-4Ld4QbvWAm0

镜像 tag

1
2
3
4
5
6
7
8
# 跑最新
docker run plantuml/plantuml-server:latest

# 跑特定版本
docker run plantuml/plantuml-server:v1.2026.7

# 跑 jdk17(更小)
docker run plantuml/plantuml-server:jdk17

性能调优

1
2
3
4
5
6
7
docker run -d \
--name plantuml \
-p 8080:8080 \
-e PLANTUML_LIMIT_SIZE=4096 \
-e MAX_URL_LENGTH=4096 \
-e PLANTUML_SECURITY_PROFILE=INTERNET \
plantuml/plantuml-server:latest

-e 参数:

Env var 用途
PLANTUML_LIMIT_SIZE 限制请求 URL 长度
MAX_URL_LENGTH URL 字节数
PLANTUML_SECURITY_PROFILE 安全策略
JAVA_OPTS 调整 JVM

优点

  • 团队共享一个统一版本
  • HTTP API 容易集成
  • 镜像轻量 ~ 100MB

缺点

  • 默认 CORS 只允许同源
  • 容器在 K8s 里存活期管理需要 Readiness
  • 镜像更新要 restart

方案 3:Kubernetes 部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
apiVersion: apps/v1
kind: Deployment
metadata:
name: plantuml
spec:
replicas: 2
selector:
matchLabels:
app: plantuml
template:
metadata:
labels:
app: plantuml
spec:
containers:
- name: plantuml
image: plantuml/plantuml-server:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 10
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: plantuml
spec:
selector:
app: plantuml
ports:
- port: 80
targetPort: 8080

Ingress + CORS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: plantuml
annotations:
nginx.ingress.kubernetes.io/cors-allow-origin: "https://puml.online"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST"
spec:
rules:
- host: plantuml.puml.online
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: plantuml
port:
number: 80

只允许自己域名 puml.online 的页面访问。

集成编辑器

VS Code

1
2
3
4
5
// .vscode/settings.json
{
"plantuml.server": "https://plantuml.puml.online",
"plantuml.render": "PlantUMLServer"
}

装 PlantUML 扩展,把 server URL 指向自部署实例。

Vim / Neovim

1
2
3
" ~/.vimrc
let g:plantuml_server = 'https://plantuml.puml.online'
let g:plantuml_render = 'plantuml-server'

装 vim-plantuml 插件。

IntelliJ IDEA

装 PlantUML Integration 插件:

1
2
Settings → Plugins → PlantUML integration
Set PlantUML server URL to https://plantuml.puml.online

CI / 编辑器共享

1
2
3
Local editor ──→ https://plantuml.puml.online ──→ K8s Deployment

└─→ CI (GitHub Actions)

单一服务,所有工具走同一 URL:

  1. 编辑器开发时拉取的预览
  2. CI 文档渲染
  3. 团队 wiki 静态嵌入

自部署的完整工作流

1
2
3
4
5
6
7
8
9
10
11
12
13
+----------------------------------------------------------------+
| |
| +-----+ +--------------------------------+ |
| | Editor → | plantuml.puml.online | |
| +-----+ | (K8s Service + CORS Ingress) | |
| +-----+ | ↓ | |
| | CI | → | +----------------------+ | |
| +-----+ | | Deployment: 2 pods | | |
| +-----+ | | image: plantuml/ | | |
| | Wiki | → | | plantuml-server | | |
| +-----+ | +----------------------+ | |
| +--------------------------------+ |
+----------------------------------------------------------------+

监控 / 日志

1
2
3
# 自定义指标暴露
- name: PLANTUML_METRICS
value: "true"

暴露 Prometheus 指标:

1
2
3
plantuml_render_total_diagrams
plantuml_render_time_seconds
plantuml_render_errors_total

日志:

1
docker logs -f plantuml-server

输出请求 URL、状态、耗时。

升级流程

1
2
3
4
5
6
7
8
# 1) 拉新版本
docker pull plantuml/plantuml-server:latest

# 2) 滚动重启(K8s 自动)
kubectl rollout restart deployment/plantuml

# 3) 验证
curl http://plantuml.puml.online/svg/SoWkIImgAStDuNc9LMqDBiLImiBeTWbG

K8s 滚动重启无宕机。

数据备份 / 状态

PlantUML server 是无状态服务,pod 重建不影响数据。

如果要做离线模式(断网用),镜像里就把 font 包好:

1
2
FROM plantuml/plantuml-server:latest
RUN apt-get install -y fonts-noto-cjk

常见配置陷阱

1. CORS 报错

1
Access to fetch at 'https://plantuml...' from origin 'https://editor...' has been blocked by CORS

要修:

  • 容器上加 PLANTUML_SECURITY_PROFILE=INTERNET
  • 或者 Ingress/反向代理层加 CORS headers

2. URL 长度限制

默认 MAX_URL_LENGTH 是 4096 字节,复杂图可能超:

1
-e MAX_URL_LENGTH=8192

或者改用 POST 提交 form。

3. Java 内存溢出

大型图可能 OOM。给容器多一点内存:

1
2
3
resources:
limits:
memory: "1Gi"

JVM:

1
-e JAVA_OPTS="-Xmx1g"

4. 中文字体

默认 OpenJDK 字体,CJK 显示成方块。镜像里:

1
RUN apt-get update && apt-get install -y fonts-noto-cjk

然后容器自带字体。

与 plantuml.com 在线版的对比

维度 自部署 plantuml.com
网络依赖 内部网络 外网
性能 内网微秒级 受公网抖动影响
数据隐私 完全私有 提交到第三方
稳定性 自己控制 SLA 看第三方故障
版本锁定 自己决定 跟随官方
维护成本 1 个 K8s 服务 0

一句话总结

自部署 PlantUML server 是 CI/CD/编辑器/团队 wiki 的「渲染层公共底座」。镜像标准化、K8s 自动扩缩,企业内网 + CORS 配置 + 字体支持三件套到位,就能跑生产。

  • 标题: PlantUML 自部署:从 plantuml.jar 到 Docker 到企业内网
  • 作者: puml.online
  • 创建于 : 2026-07-29 16:15:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-self-host/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。