PlantUML est le plus ancien et le plus complet des trois outils de diagramme as code en UML (le langage de modélisation standard) : séquence, composants, déploiement, classes. Il est écrit en Java, la plateforme d'exécution qu'il faut donc avoir pour le lancer. Cette leçon est facultative : si vous débutez, Mermaid et D2 suffisent. PlantUML reste le bon choix pour un projet qui en possède déjà, pour un UML détaillé, ou pour une équipe sur GitLab, qui le rend nativement. Vous le lancerez en conteneur, écrirez quatre diagrammes de la boutique en ligne et une vue C4, puis le brancherez à la CI.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Choisir PlantUML en connaissance de cause, licence comprise.
- Rendre un fichier
.pumlen SVG avec une image épinglée. - Écrire contexte, séquence, composants, déploiement et une vue C4.
- Contrôler la syntaxe et lire un code de retour.
- Brancher l'ensemble dans un workflow de CI.
Le principe du diagramme as code, les chemins de rendu et le texte alternatif sont posés dans Diagrammes as code, que cette leçon ne répète pas. Le fil rouge est la boutique en ligne du modèle C4. Prérequis : Docker installé et un éditeur de texte.
Quand choisir PlantUML, et quand l'éviter ?
Section intitulée « Quand choisir PlantUML, et quand l'éviter ? »Choisissez PlantUML dans trois cas : un projet existant en contient déjà
des sources, vous voulez un UML détaillé (séquences riches, composants,
déploiement, classes), ou votre équipe héberge son code sur GitLab. Sur
GitLab.com, la documentation indique que PlantUML est actif « for all users,
and requires no additional configuration ». En auto-hébergé, « a GitLab
administrator must enable it » et la documentation GitLab recommande le
serveur plantuml/plantuml-server:tomcat. GitHub, lui, ne rend pas PlantUML :
il n'en figure pas parmi les quatre syntaxes qu'il affiche. Pour un nouveau
projet sans contrainte, Mermaid ou D2 demandent moins d'outillage.
La licence mérite un coup d'œil. Le projet indique que PlantUML est
distribué sous licence GPL par défaut (une licence libre qui impose de
redistribuer les modifications sous la même licence). Un jar, l'archive
Java exécutable de l'outil, existe aussi sous
d'autres licences : GPLv2, LGPL, ASL, BSD, EPL, MIT (artefacts
plantuml-asl-1.2026.8.jar, plantuml-bsd-1.2026.8.jar, etc.), plus un
plantuml-java8-1.2026.8.jar pour Java 8. Le site précise que ces versions
« miss few features (DITAA for example), but are 100% able to generate UML
diagrams ». Si la GPL pose problème à votre organisation, une variante peut convenir.
Une particularité compte pour la sécurité de la chaîne d'approvisionnement : les
jars sont signés (fichiers .asc), mais la release ne publie aucune somme
SHA à comparer (constaté le 2026-10-13). On ne peut donc pas épingler le jar
par empreinte comme on le fait pour D2. La parade est d'épingler l'image
Docker par son digest, ce que fait la section suivante.
Comment installer et lancer PlantUML ?
Section intitulée « Comment installer et lancer PlantUML ? »Le plus simple est l'image officielle, épinglée par tag et par digest
(l'empreinte SHA-256 qui désigne une image de façon immuable). Elle
embarque PlantUML, Java 21 et Graphviz, donc rien d'autre à installer. La
commande écrit le rendu à côté de la source, et -u évite que les fichiers
appartiennent à root.
docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/data" \ plantuml/plantuml:1.2026.8@sha256:d08610df482510844382caa4e016ba2bf7e3231f630f02ee12f250f3416c62b1 \ -tsvg contexte.pumlAvec cette commande, contexte.svg apparaît à côté de la source
(5 422 octets dans notre essai). L'option -tpng produit un PNG (1183 x 204 pour la
même source), et -o rendu envoie les images dans le sous-dossier rendu.
Pour vérifier l'installation, relancez la même commande en remplaçant la fin
par -version : elle affiche PlantUML version 1.2026.8, la mention
(GPL source distribution), un runtime OpenJDK, dot - graphviz version 14.0.1
et « Installation seems OK » (un avertissement sur libgvplugin_gd.so.8 peut
précéder, sans effet sur le rendu SVG). Le code de retour est 0. L'option -testdot teste Graphviz seul.
Le jar en local (java -jar plantuml.jar -tsvg contexte.puml) est l'autre
voie, mais elle n'a pas été testée sur le poste de rédaction, qui n'a pas
Java : si vous la choisissez, vérifiez-la avec -version. PlantUML propose en
outre une CLI bêta à doubles tirets (--svg, --check-syntax, --output-dir).
Les options historiques à simple tiret, utilisées ici, restent valides.
Pourquoi PlantUML a-t-il besoin de Graphviz ?
Section intitulée « Pourquoi PlantUML a-t-il besoin de Graphviz ? »La chaîne de rendu a une particularité : selon le type de diagramme, PlantUML
délègue la mise en page à Graphviz (programme dot) ou la calcule
lui-même (mise en page interne). Graphviz est un programme qui calcule la
position des boîtes et des flèches. Le schéma ci-dessous montre ce choix :
regardez les trois branches qui partent du jar vers l'image, et la voie
pointillée par Smetana.
La documentation de PlantUML liste ce qui exige Graphviz : les diagrammes de cas
d'usage, de classes, d'objets et de composants, puis le déploiement, les états et
les anciens diagrammes d'activité. Les séquences, absentes de cette liste,
passent par la mise en page interne. Quand
Graphviz manque, Smetana, une version de dot portée en Java, le remplace
(!pragma layout smetana dans la source, ou -Playout=smetana en ligne de
commande). Nous avons joué l'option en ligne de commande sur le diagramme de
composants : rendu réussi, sans Graphviz. Le pragma n'a pas été rejoué.
Comment écrire la vue contexte ?
Section intitulée « Comment écrire la vue contexte ? »La vue contexte de la boutique tient en cinq éléments : deux personnes, le
système, et deux services externes. Dans la source ci-dessous, actor dessine
une personne, rectangle "..." as alias un bloc nommé par un alias court,
et --> une flèche suivie de : libellé. L'instruction left to right direction aligne le
tout horizontalement.
@startumlleft to right directionactor "Client" as clientactor "Gestionnaire de boutique" as gestionnairerectangle "Boutique en ligne" as boutiquerectangle "Service de paiement\n(externe)" as paiementrectangle "Service de mail\n(externe)" as mailclient --> boutique : Consulte le catalogue et commande (HTTPS)gestionnaire --> boutique : Gère le catalogue et les stocks (HTTPS)boutique --> paiement : Débite la carte (JSON/HTTPS)boutique --> mail : Envoie les e-mails de commande (SMTP)@endumlVoici le rendu réel produit par PlantUML 1.2026.8 : lisez les flèches depuis le client et le gestionnaire vers la boutique, puis de la boutique vers les deux services externes.
Comment écrire une séquence ?
Section intitulée « Comment écrire une séquence ? »La séquence est le point fort de PlantUML : elle montre qui appelle qui, dans
quel ordre. Notre séquence « Passer une commande » compte neuf messages.
autonumber les numérote, participant, actor et database déclarent les
acteurs. La flèche -> est un appel plein, --> un retour en pointillé, ->>
une flèche à tête fine, que la convention UML réserve au message asynchrone
(l'émetteur n'attend pas de réponse). ++ après la
cible active celle-ci, et return ferme l'activation avec sa réponse.
@startumltitle Passer une commandeautonumberactor "Client" as clientparticipant "Interface web" as webparticipant "API" as apidatabase "Base de données" as baseparticipant "Service de paiement" as paiementparticipant "Service de mail" as mail
client -> web : Valide le panierweb -> api ++ : POST /commandes (JSON/HTTPS)api -> base : Enregistre la commande « en attente »api -> paiement ++ : Débite la cartereturn Paiement acceptéapi -> base : Passe la commande en « payée »api ->> mail : Envoie la confirmation (SMTP)return 201, commande crééeweb --> client : Affiche la confirmation@endumlDans le rendu, suivez les numéros de haut en bas. Les rectangles étroits sur les
lignes de vie sont les activations ouvertes par ++ et refermées par
return.
Ce n'est qu'un échantillon. La documentation des séquences ajoute alt /
else / end pour un choix, loop pour une répétition, note over pour une
remarque et activate / deactivate pour piloter les activations à la main.
Comment écrire les composants de l'API ?
Section intitulée « Comment écrire les composants de l'API ? »Un composant est un bloc de code cohérent à l'intérieur d'un conteneur ;
ce qu'il faut dessiner et où s'arrêter est expliqué dans
Composants et code C4. Ici, le
diagramme zoome dans le conteneur API. package regroupe les composants, [Nom] as alias en déclare un (un \n coupe le
libellé sur deux lignes), database dessine la base, --> trace un appel et
..> une dépendance en pointillé. Il demande Graphviz, ou Smetana.
@startumlleft to right directiontitle Composants du conteneur API
package "API (Node.js)" { [Contrôleur HTTP\n(Express)] as controleur [Service Catalogue] as catalogue [Service Commandes] as commandes [Client Paiement] as clientpaiement [Notifications] as notifications}database "Base de données\n(PostgreSQL)" as base[Service de paiement\n(externe)] as paiement[Service de mail\n(externe)] as mail
controleur --> catalogue : Transmet les demandes de cataloguecontroleur --> commandes : Transmet les commandescatalogue --> base : Lit (SQL/TCP)commandes --> base : Lit et écrit (SQL/TCP)commandes --> clientpaiement : Demande le débitcommandes --> notifications : Demande la confirmationclientpaiement --> paiement : Débite la carte (JSON/HTTPS)notifications --> mail : Envoie les e-mails (SMTP)@endumlLe rendu ci-dessous place le cadre « API (Node.js) » autour des cinq composants :
repérez que seuls Client Paiement et Notifications sortent vers l'extérieur. La
syntaxe offre aussi les interfaces (()) et les note, absentes de cet
exemple.
Comment écrire le déploiement ?
Section intitulée « Comment écrire le déploiement ? »Le diagramme de déploiement dit où tourne chaque morceau, ce que détaille
la vue de déploiement C4. Les node
s'imbriquent (un poste contient un navigateur, qui contient l'interface),
artifact désigne le livrable, database la base et cloud un service tiers.
L'imbrication se lit comme une arborescence : le premier niveau est la machine,
le suivant l'environnement d'exécution, le dernier ce qui y est installé.
@startumlleft to right directiontitle Déploiement en production
node "Poste du client" { node "Navigateur web" { artifact "Interface web" as web }}node "Serveur applicatif\n(Ubuntu 24.04, x2)" { node "Node.js 22" { artifact "API" as api }}node "Serveur de données\n(Ubuntu 24.04)" { node "PostgreSQL 17" { database "Base de données" as base }}cloud "Service de paiement\n(externe)" as paiementcloud "Service de mail\n(externe)" as mail
web --> api : Appelle (JSON/HTTPS)api --> base : Lit et écrit (SQL/TCP)api --> paiement : Débite la carte (JSON/HTTPS)api --> mail : Envoie les e-mails (SMTP)@endumlDans l'image, vérifiez que l'API est sur deux serveurs applicatifs (le x2 du
libellé) et que la base reste sur une machine dédiée.
Comment écrire du C4 avec C4-PlantUML ?
Section intitulée « Comment écrire du C4 avec C4-PlantUML ? »C4-PlantUML est une bibliothèque de macros qui fournit le vocabulaire du C4
(Person, System, Rel…). Elle est embarquée dans PlantUML : la commande
-stdlib y relève la version 2.13.0 (licence MIT), et
!include <C4/C4_Context>, avec des chevrons, la charge sans réseau. Person,
System et System_Ext déclarent les boîtes, Rel(from, to, label, techn) une
relation. Pour le niveau suivant, Container et ContainerDb prennent le relais.
@startuml!include <C4/C4_Context>title Contexte de la boutique en ligne
Person(client, "Client", "Parcourt le catalogue, passe commande")Person(gestionnaire, "Gestionnaire de boutique", "Met à jour le catalogue et les stocks")System(boutique, "Boutique en ligne", "Vend le catalogue et encaisse les commandes")System_Ext(paiement, "Service de paiement", "Encaisse les cartes bancaires")System_Ext(mail, "Service de mail", "Envoie les e-mails transactionnels")
Rel(client, boutique, "Consulte le catalogue et commande", "HTTPS")Rel(gestionnaire, boutique, "Gère le catalogue et les stocks", "HTTPS")Rel(boutique, paiement, "Débite la carte", "JSON/HTTPS")Rel(boutique, mail, "Envoie les e-mails de commande", "SMTP")@endumlLe rendu respecte la charte C4 : les boîtes externes sont grises, chaque flèche porte son libellé et sa technologie.
Kroki sait aussi rendre cette source sur son point d'entrée /c4plantuml/svg.
Cette bibliothèque décrit un fichier par vue, sans modèle partagé. Pour
garder plusieurs vues cohérentes, voir
C4 en code, qui compare Structurizr,
Mermaid C4 et C4-PlantUML.
Comment contrôler la syntaxe et lire une erreur ?
Section intitulée « Comment contrôler la syntaxe et lire une erreur ? »Avant de rendre, on vérifie la source. -checkonly contrôle la syntaxe sans
rien écrire : sur contexte.puml, il ne dit rien et rend le code 0. Les
codes de retour sont documentés : 0 pour un succès, 50 si aucun fichier n'est
trouvé, 100 si aucun diagramme n'est trouvé, 200 pour une erreur de syntaxe.
Voici une source volontairement cassée, casse.puml.
@startumlactor "Client" as clientparticipant "Interface web" as webclient -> web : Valide le panierweb -> api : POST /commandesclient ->web Affiche la confirmation@endumlSur ce fichier, -checkonly affiche Some diagram description contains errors
et rend le code 200. Un rendu normal (-tsvg casse.puml) signale
Error line 6, et la ligne 6 est bien la fautive : il
manque : avant le libellé de client ->web Affiche la confirmation.
Un piège compte pour la CI : malgré l'erreur, PlantUML écrit quand même
casse.svg (1 971 octets), une image d'erreur. Testez donc le code de
retour, jamais la présence du fichier. -failfast2 fait une passe de contrôle
avant tout rendu (No diagram found, aucune image produite), et -failfast
s'arrête à la première erreur.
Une limite : un package jamais fermé (accolade } oubliée) passe
-checkonly avec le code 0, car PlantUML tolère l'accolade manquante et ferme le
groupe tout seul. Aucun message ne signale l'oubli : seule la relecture de la
source et de l'image permet de voir quels éléments se retrouvent dans le
package. Passé par Kroki, le même casse.puml renvoie
Error 400: Syntax Error? (Assumed diagram type: sequence) (line: 5) : Kroki
compte sans la ligne @startuml, d'où 5 au lieu de 6.
Comment rendre le diagramme compréhensible sans l'image ?
Section intitulée « Comment rendre le diagramme compréhensible sans l'image ? »PlantUML n'écrit aucune balise de titre ni de description de schéma dans le
SVG : ni <title> ni <desc>. Le lecteur d'écran n'a donc rien à lire :
le texte alternatif de l'image et la phrase qui la précède portent toute
l'information. La méthode est exposée dans
Diagrammes as code et dans
Montrer, pas seulement décrire.
Comment brancher PlantUML dans la CI ?
Section intitulée « Comment brancher PlantUML dans la CI ? »Dans la CI, on rejoue les mêmes commandes sur l'image épinglée : d'abord
-checkonly, qui échoue sur une erreur, puis -tsvg. Voici l'étape PlantUML
d'un workflow GitHub Actions. Le workflow complet donne permissions: {} au
niveau global, contents: read au job, et persist-credentials: false au
checkout (action épinglée sur son commit, version en commentaire).
name: Diagrammeson: pull_request: paths: - "docs/**/*.puml"permissions: {}jobs: rendre: runs-on: ubuntu-24.04 permissions: contents: read steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: PlantUML, syntaxe puis rendu run: | docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/data" \ plantuml/plantuml:1.2026.8@sha256:d08610df482510844382caa4e016ba2bf7e3231f630f02ee12f250f3416c62b1 \ -checkonly docs/**/*.puml docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/data" \ plantuml/plantuml:1.2026.8@sha256:d08610df482510844382caa4e016ba2bf7e3231f630f02ee12f250f3416c62b1 \ -tsvg docs/**/*.pumlCe workflow a passé actionlint et zizmor (aucun constat). Les commandes
docker run ont été jouées sur le poste, mais le workflow lui-même n'a pas
été exécuté sur un runner GitHub. Le glob docs/**/*.puml est développé par le shell
du runner, bash par défaut, où ** équivaut à * tant que shopt -s globstar
n'a pas été activé : docs/**/*.puml devient docs/*/*.puml, qui ne trouve que
les fichiers d'un sous-dossier direct de docs/, ni ceux posés directement dans
docs/, ni ceux de niveaux plus profonds. Avec shopt -s globstar, tous sont
trouvés. Activez l'option ou listez les fichiers avec find, et
testez le résultat sur votre dépôt.
Sans Docker, un serveur peut rendre à la place du jar : Kroki (la requête
POST /plantuml/svg a répondu HTTP 200 sur les versions 0.30 et 0.33) ou
plantuml/plantuml-server (non testé). Le choix entre ces chemins est expliqué
dans Diagrammes as code.
Dans un projet AsciiDoc, Asciidoctor Diagram appelle PlantUML au moment de la
conversion, voir le guide AsciiDoc.
Exercice guidé : comment écrire la séquence « Annuler une commande » ?
Section intitulée « Exercice guidé : comment écrire la séquence « Annuler une commande » ? »À vous d'appliquer la syntaxe. Créez annulation.puml pour décrire ce scénario
dans l'ordre :
- Client → Interface web : « Demande l'annulation ».
- Interface web → API :
DELETE /commandes/{id}. - API → Base de données : « Passe la commande en annulée ».
- API → Service de paiement : « Rembourse la carte », réponse « Remboursement accepté ».
- API → Service de mail : « Envoie l'avis d'annulation », sans attendre de réponse.
- API → Interface web : « 200 ».
- Interface web → Client : « Affiche la confirmation ».
Avant de regarder le corrigé, vérifiez trois points : les messages sont
numérotés (autonumber), l'appel au service de paiement ouvre puis ferme une
activation (++ puis return), et l'envoi du mail est asynchrone (->>).
Rendez le fichier, puis lancez -checkonly.
@startumltitle Annuler une commandeautonumberactor "Client" as clientparticipant "Interface web" as webparticipant "API" as apidatabase "Base de données" as baseparticipant "Service de paiement" as paiementparticipant "Service de mail" as mail
client -> web : Demande l'annulationweb -> api ++ : DELETE /commandes/{id} (JSON/HTTPS)api -> base : Passe la commande en « annulée »api -> paiement ++ : Rembourse la cartereturn Remboursement acceptéapi ->> mail : Envoie l'avis d'annulation (SMTP)return 200web --> client : Affiche la confirmation@endumlSi le rendu échoue, relisez le message : il cite la ligne fautive, le plus
souvent un : oublié avant le libellé.
À retenir
Section intitulée « À retenir »- PlantUML couvre séquence, composants, déploiement et classes ; il est facultatif si Mermaid ou D2 suffisent.
- GitLab le rend nativement sur GitLab.com ; GitHub ne le rend pas.
- Licence GPL par défaut, jars aussi sous d'autres licences ; pas de somme SHA publiée, donc on épingle l'image Docker par digest.
- Graphviz est nécessaire pour composants, déploiement et classes, pas pour la séquence ; Smetana le remplace en secours.
- C4-PlantUML est embarquée (
!include <C4/C4_Context>) mais décrit un fichier par vue, sans modèle partagé. -checkonlycontrôle sans rendre : code 0 si tout va bien, 200 sur erreur de syntaxe.- Un rendu en erreur écrit quand même une image : en CI, lisez le code de retour, pas la présence du fichier.
- Un
packagenon fermé passe-checkonly: relisez l'image. - Le SVG n'a ni
<title>ni<desc>de schéma : le texte alternatif de la page porte tout.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Documentation as Code : pourquoi et comment
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications