文章目录
- 1、前言
- 2、搜索PlantUML镜像#
- 3、下载PlantUML镜像
- 4、观察分析PlantUML镜像结构:
- 5、创建PlantUML的Docker卷:
- 6、运行PlantUML容器
- 7、搭建Gitlab
- 8、在Gitlab中集成PlantUML#
1、前言
这两天在继续学习使用Markdown绘图的过程中,无意中接触到了一个在线的UML工具:PlantUML。PlantUML是一个用来绘制UML图的Java类库。支持的UML图包括:时序图、用例图、类图、组件图、活动图等。它最大的优势就是通过解析纯文本化的脚本来生成图表,并且因其引擎的插件化设计,所以很容易集成在各种工具、网页、程序等中,这样一来通过编写脚本,就可以在各处显示,实在是非常方便好用,尤其适合习惯了写代码的程序员。最终研究了半天,几乎没有发现有封装的好用的独立工具,但它可以在eclipse中做插件。
没有单独好用的工具,我就暂时先把它放了放,接着研究怎么在Typora中使用Markdown文法来绘制UML图,但是Markdown文法的表达比PlantUML就差了一些。突然我灵机一动,既然这个东东是插件,那有没有可能被人直接搞成Docker容器化的服务器式的应用呢?于是我就发现这个东东不但有,而且可以和Gitlab无缝集成,这样就可以直接在代码文档中插入PlantUML的脚本,在Gitlab网页中直接嵌入式显示。下面就把整个过程记录下来,分享给大家。
当然与之前搭建Gitlab本地服务器一样,整个过程是在Docker For Windows Desktop版中进行的,linux下的部署就更简单了,也有热心网友已经分享了,我就不多啰嗦了,这里依然是围绕Windows Docker环境展开,同样的因为共享Windows目录进docker容器中的权限问题,所以直接共享目录的方法依然是失败的,因此还是需要创建Volume来运行容器。下面就简述这一过程:
2、搜索PlantUML镜像#
在Powershell中输入下面的命令来搜索PlantUML的各种镜像:
docker search plantuml
在我机器上搜索出如下的这些镜像,列在这里供大家参考:
NAME | DESCRIPTION | STARS | OFFICIAL | AUTOMATED |
plantuml/plantuml-server | PlantUML Online Server | 91 | ||
think/plantuml | plantuml usable from docker. | 21 | [OK] | |
neam/plantuml-server | 8 | [OK] | ||
kerhac/plantuml-markdown | PlantUML plugin for Python-Markdown stuffed … | 2 | [OK] | |
miy4/plantuml | Docker with Alpine Linux, Java and… | 1 | [OK] | |
saidsef/plantuml-server | The easiest and quickest way of testing Plan… | 1 | ||
gmitirol/plantuml | plantuml server on alpine linux 3.10 | 1 | ||
hrektts/plantuml | PlantUML diagram generator | 1 | [OK] | |
bitjourney/plantuml-service | PlantUML service used in Kibela | 1 | ||
e53e225/plantuml | PlantUML | 0 | [OK] | |
kubler/plantuml | plantuml server / size: ~268mb | 0 | ||
npalm/plantuml-server | Dockerized plantuml server to run plantuml i… | 0 | [OK] | |
gboston/plantuml-server | Plantuml Server | 0 | ||
dakue/plantuml | PlantUML based on Tomcat with Agent Bond | 0 | [OK] | |
datacore/plantuml-server | PlantUML Server | 0 | [OK] | |
jgraph/plantuml-server | 0 | |||
vaporio/plantuml-c4 | 0 | |||
bashkirtsevich/plantuml | Dockerized plantuml renderer | 0 | ||
marcelocorreia/plantuml | PlantUML | 0 | ||
banananetwork/plantuml | Docker Image with PlantUML and Make for GitL… | 0 | ||
wanix/plantuml | container for PlantUml batches | 0 | [OK] | |
hypoport/plantuml_server | plantuml_server | 0 | [OK] | |
frodeaa/plantuml | PlantUML diagram generator | 0 | ||
rado0x54/plantuml | PlantUML Server on Jetty | 0 |
3、下载PlantUML镜像
在这里我只是简单的选择了plantuml/plantuml-server的官方镜像,别的镜像理论上应该也可以,当然详细的有些什么差别或优点就要靠大家自己探索了。使用docker pull命令下载plantuml/plantuml-server镜像如下:
PS C:\ docker pull plantuml/plantuml-server
Using default tag: latest
latest: Pulling from plantuml/plantuml-server
376057ac6fa1: Already exists
5a63a0a859d8: Already exists
496548a8c952: Already exists
94b2daf7a1b5: Pull complete
d78caafebbc1: Pull complete
1b5add4df1a2: Pull complete
4933f513e7ea: Pull complete
de56e04b9841: Pull complete
5f48c16ba8b3: Pull complete
13e73ad72587: Pull complete
Digest: sha256:be359f0590ca898660c3e03c0f67367ae2a0c267d8f603c37cb61bc6d9f42d48
Status: Downloaded newer image for plantuml/plantuml-server:latest
docker.io/plantuml/plantuml-server:latest
4、观察分析PlantUML镜像结构:
为了搭建PlantUML-Server的容器,就需要知道这个镜像需要些什么配置参数,然后好组织docker run命令运行之。当然一般情况下,都可以直接百度得到别人已经写好的docker run命令,然后复制粘贴运行即可,但是这并不是万能的灵药,因为总有一些生僻的docker镜像无法搜到现成的run命令及用法,此时不要着急,可以使用这里介绍的方法,通过inspect大法直接通过查看镜像的信息来自行组织docker run命令。对于PlantUML在PowerShell中执行如下命令:
docker image inspect plantuml/plantuml-server
一般情况下docker image inspect命令可以解析出镜像构建的主要信息,比如对PlantUML-Server执行后,可以解析出下面的结构化信息:
[
{
"Id": "sha256:c2cbf4909cba8708621a4a17f4a3b8416bbedda5a1ac25fcd529da6c49dadc7c",
"RepoTags": [
"plantuml/plantuml-server:latest"
],
"RepoDigests": [
"plantuml/plantuml-server@sha256:be359f0590ca898660c3e03c0f67367ae2a0c267d8f603c37cb61bc6d9f42d48"
],
"Parent": "",
"Comment": "",
"Created": "2020-06-07T10:08:44.216424656Z",
"Container": "",
"ContainerConfig": {
"Hostname": "",
"Domainname": "",
"User": "jetty",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"8080/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/jetty/bin:/usr/local/openjdk-8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=C.UTF-8",
"JAVA_HOME=/usr/local/openjdk-8",
"JAVA_VERSION=8u252",
"JAVA_BASE_URL=https://github.com/AdoptOpenJDK/openjdk8-upstream-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jre_",
"JAVA_URL_VERSION=8u252b09",
"JETTY_VERSION=9.4.27.v20200227",
"JETTY_HOME=/usr/local/jetty",
"JETTY_BASE=/var/lib/jetty",
"TMPDIR=/tmp/jetty",
"JETTY_TGZ_URL=https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/9.4.27.v20200227/jetty-home-9.4.27.v20200227.tar.gz",
"JETTY_GPG_KEYS=AED5EE6C45D0FE8D5D1B164F27DED4BF6216DB8F \t2A684B57436A81FA8706B53C61C3351A438A3B7D \t5989BAF76217B843D66BE55B2D0E1FB8FE4B68B4 \tB59B67FD7904984367F931800818D9D68FB67BAC \tBFBB21C246D7776836287A48A04E0C74ABB35FEA \t8B096546B1A8F02656B15D3B1677D141BCF3584D \tFBA2B18D238AB852DF95745C76157BDF03D0DCD6 \t5C9579B3DB2E506429319AAEF33B071B29559E1E",
"GRAPHVIZ_DOT=/usr/bin/dot"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) COPY file:ae6546e175c6b413d38e15161474de970dcc382dc61e9b0a794afbf424dc7a3d in /var/lib/jetty/webapps/ROOT.war "
],
"ArgsEscaped": true,
"Image": "sha256:27c61de195bc3b15b4beb1918d2a54e90229bc9fd10b5141a51053eae11540ec",
"Volumes": null,
"WorkingDir": "/var/lib/jetty",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"DockerVersion": "18.06.0-ce",
"Author": "D.Ducatel",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "jetty",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"8080/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/jetty/bin:/usr/local/openjdk-8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=C.UTF-8",
"JAVA_HOME=/usr/local/openjdk-8",
"JAVA_VERSION=8u252",
"JAVA_BASE_URL=https://github.com/AdoptOpenJDK/openjdk8-upstream-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jre_",
"JAVA_URL_VERSION=8u252b09",
"JETTY_VERSION=9.4.27.v20200227",
"JETTY_HOME=/usr/local/jetty",
"JETTY_BASE=/var/lib/jetty",
"TMPDIR=/tmp/jetty",
"JETTY_TGZ_URL=https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/9.4.27.v20200227/jetty-home-9.4.27.v20200227.tar.gz",
"JETTY_GPG_KEYS=AED5EE6C45D0FE8D5D1B164F27DED4BF6216DB8F \t2A684B57436A81FA8706B53C61C3351A438A3B7D \t5989BAF76217B843D66BE55B2D0E1FB8FE4B68B4 \tB59B67FD7904984367F931800818D9D68FB67BAC \tBFBB21C246D7776836287A48A04E0C74ABB35FEA \t8B096546B1A8F02656B15D3B1677D141BCF3584D \tFBA2B18D238AB852DF95745C76157BDF03D0DCD6 \t5C9579B3DB2E506429319AAEF33B071B29559E1E",
"GRAPHVIZ_DOT=/usr/bin/dot"
],
"Cmd": [
"java",
"-jar",
"/usr/local/jetty/start.jar"
],
"ArgsEscaped": true,
"Image": "sha256:27c61de195bc3b15b4beb1918d2a54e90229bc9fd10b5141a51053eae11540ec",
"Volumes": null,
"WorkingDir": "/var/lib/jetty",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 403656329,
"VirtualSize": 403656329,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/233598cf55da444f237cc38dacbba23193a28f2768ccf962127a3f4c73a38df5/diff:/var/lib/docker/overlay2/6aee11ffd0086fc47efdf071e0f6e7b5f574c0ee80f6ce8e99cccad2f40715ce/diff:/var/lib/docker/overlay2/0a21cb126d497ee5ab862bd146df9679e0c8006c68fd6ecaf25f16bc73a09fa1/diff:/var/lib/docker/overlay2/9cc20c7e9a157f3705cdd84c43b4dd18a2761ec8aabeb40d7f1f6718c9f484af/diff:/var/lib/docker/overlay2/f3cfbf04bc96bd86052995e6b0ae3e31e519207a6ab2b939e0427d59bb852a74/diff:/var/lib/docker/overlay2/2dbbb0e3c113599f1c142d2ecb96fa22f2196c8e6ffe149a1e855d10b4243b24/diff:/var/lib/docker/overlay2/5e203aa76806b0e129d5160a2e5aa1dc2047e8c712518b5db6864ca4200bc993/diff:/var/lib/docker/overlay2/861beca071b665dacaa1e6d40562840f32eb62377db14103981db0106a5a56c8/diff:/var/lib/docker/overlay2/f2abaede559896555129c79bf360fbea6c2f222aa9d6a1015464c673ae166135/diff",
"MergedDir": "/var/lib/docker/overlay2/675c6a60e89e3114cb6b70ac43596da15a34b457a3fe422ec09412dbf4960832/merged",
"UpperDir": "/var/lib/docker/overlay2/675c6a60e89e3114cb6b70ac43596da15a34b457a3fe422ec09412dbf4960832/diff",
"WorkDir": "/var/lib/docker/overlay2/675c6a60e89e3114cb6b70ac43596da15a34b457a3fe422ec09412dbf4960832/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:8c02234b86056c009036ff0c31efb9a726412392d9872dacf95103767ac3b101",
"sha256:7cc1c2d7e744369899e8affd52f9be62076b1ef0205f02ed11547bb5327e5a43",
"sha256:760e8d95cf58e8696de9ba210ef58522750aee7a1f24c15695f493582002c08e",
"sha256:24ae30bb2901da72e5445e3ae525953cd356b138c033293ee8f5a2e76272bd34",
"sha256:a8b488a0e334c51c2bb1226f2051d88e7eb6889a77edae6cb507c8f75dad634f",
"sha256:c7ed915c011c9ebc3c397b2542fb872e4e9d5d7c77709f8da7e5ef73e46844b8",
"sha256:b4b6a5cfdc9d3a35ceebf150cb303a63dfb68474ebf75835b6f9aec41d8d7e0b",
"sha256:05543d4b308cbdcbb378b68ec0a8a41e9aaf7f510c4838d18f5a4e0f0fb5c733",
"sha256:0c2d1f32ccad525921167865212e7f2d19a31a1a760e27328962949b84cb5969",
"sha256:7ac2038b8ae23c2f97bab6a0c67ecc31d10c021b297f9c2cee23d7c4acbf070e"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
首先可以看到,这个镜像解析后的信息貌似很复杂,其实作为一般化初步的使用来说,重点的其实只需要关注“WorkingDir”、“Volumes”、“ExposedPorts”基本就够了,其中“WorkingDir”和“Volumes”参数就主要是设定镜像需要的持久化存储数据的docker卷或者目录的,一般为了持久化容器中的数据,那么都需要为这些参数在docker run命令中用-v参数来挂载相应的host中的卷或目录的。**这里郑重的提醒大家:**因为Windows Docker其实是运行在Hyperv虚拟机中的一个轻量级linux docker host环境,所以这里的host就指的是Hyperv中的虚拟机,而不是Windows系统本身,虽然可以使用-v参数将Windows本地目录挂进Docker 容器中,但是因为Windows 与 Linux毕竟是本质上极大不同的操作系统,往往因为镜像本身是纯linux运行环境的,所以在一些文件操作上会失败,尤其是权限操作失败的几率很高,导致镜像无法运行,容器无法启动,当然这是Windows Docker下特有的问题,目前我也没有找到根本原因及解决办法,所以对于挂载需要挂载目录的,都暂时只能通过创建docker volume的方法创建hyperv虚拟机docker容器中的卷,当然要做的就是保护好这个虚拟机文件本身,这个在搭建Gitlab的博文中已经提醒过大家了,就不赘述了。
另一个重要的参数就是“ExposedPorts”,也就是容器最终要暴露的端口,一般就是在docker run命令中用-p或-P参数导出端口即可。
作为一般镜像的使用,关注上面这些参数基本就够了,就可以写出docker run命令运行容器,并且通过浏览器或专用工具链接端口访问了,当然数据也是持久化的,重建,重启容器都不会丢数据了,windocker环境下最终条件依然是千万不要搞丢了docker虚拟机的硬盘文件!
5、创建PlantUML的Docker卷:
使用下面命令创建用于plantuml的卷:
docker volume create plantuml_data
查看卷信息:
C:\docker volume inspect plantuml_data
[
{
"CreatedAt": "2020-06-10T04:50:19Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/plantuml_data/_data",
"Name": "plantuml_data",
"Options": {},
"Scope": "local"
}
]
通过卷的挂载点属性就可以彻底明白,这里的卷还是存在linux的路径下,本质上其实就是在Windows Docker的虚拟机中,所以保护好虚拟机的硬盘文件是做好数据保护的有效途径。
6、运行PlantUML容器
经过分析镜像属性,并创建了卷之后,那么就可以通过运行下面的命令来启动PlantUml的容器了:
docker run --name plantuml -d -p 8888:8080 -v plantuml_data:/var/lib/jetty plantuml/plantuml-server
启动后可以通过下面命令查看PlantUml容器的日志,观察启动过程是否成功:
docker logs plantuml
启动成功后,在浏览器中输入下面网址:
http://localhost:8888
即可看到如下的页面:
可以在页面的脚本框中输入如下的plantuml脚本查看效果:
@startuml
Class01 <|-- Class02
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 -- Class10
@enduml
点击提交按钮后:
7、搭建Gitlab
参看《在Windows Docker Desktop中搭建Gitlab》
8、在Gitlab中集成PlantUML#
接着就可以在搭建好的Gitlab环境中按照下图所示的步骤,将刚才建好的PlantUml服务集成进去:
集成之后,在某个项目中新建一个如下的md文本文件,然后按图中所示输入脚本:
然后按图中所示点击预览按钮,就可以看到文本中的PlantUml脚本被图形化显示了出来,这样实质上也实现了将PlantUml脚本通过Gitlab集成进了Markdown格式的文本文档中,最终方便了代码相关专用UML文档的编辑,显示,查看,做到了本地编辑,线上线下都可以轻松浏览和修改的目的。
最后提交变更并退出编辑模式后,就可以直接在项目文件列表中轻松浏览PlantUML图形了: