Templates are directory-based. Each template directory contains template.json plus a required files/ directory with renderable content.
LibraryManager finds template directories containing template.json.Template loads and validates manifest metadata.needs constraints.files/ render through the custom-delimiter Jinja environment.Minimal template.json shape:
{
"slug": "my-template",
"kind": "compose",
"metadata": {
"name": "My Template",
"description": "A template description.",
"version": {
"name": "v1.0.0"
}
},
"variables": [
{
"name": "general",
"title": "General",
"items": [
{
"name": "service_name",
"type": "str",
"title": "Service name",
"default": "demo"
}
]
}
]
}
For 0.2.0+, templates use custom Jinja-like delimiters:
<< variable_name >><% if condition %> ... <% endif %><# comment #>Default Jinja delimiters such as {{ variable }} are intentionally left untouched so downstream tools like Ansible can use them literally.
Legacy .j2 behavior is no longer supported for new template.json templates. Renderable content lives under files/, and output paths match the relative paths under files/.
metadata.version is a structured object and may be partial. Supported fields include:
namesource_dep_namesource_dep_versionsource_dep_digestupstream_refnotesThis separates the user-facing template version label from tracked upstream dependency metadata.
Application/image versions should generally be hardcoded in template files, for example:
image: nginx:1.25.3
Do not create variables such as nginx_version unless there is a strong technical reason, such as multi-component version pinning. Hardcoding tested versions avoids mismatches between variables and validated template output.
Variable precedence, lowest to highest:
template.json--var overridesVariable types:
strintfloatboolemailurlhostnameenumsecretCommon variable properties:
default - default valuetitle - prompt/display titledescription - description/help textrequired - require non-empty valueneeds - conditional visibility constraintconfig.options - enum optionsconfig.placeholder - input placeholderconfig.autogenerated - secret autogeneration settingsVariable groups become sections. Sections can define:
toggle - auto-created boolean variable that enables/disables the sectionneeds - section dependency by section keyVariable-level needs constraints use this format:
var_name=valuevar_name!=valuevar1=value1;var2=value2network_mode=bridge,macvlan where comma means ORDependency validation detects missing dependencies, circular dependencies, and self-dependencies.
Template validation includes:
Generic semantic validation is provided by cli/core/validators.py, including YAML and Docker Compose-oriented checks where applicable.
Kind-specific validation lives under cli/core/validation/ and can be enabled with module validation options such as --kind or matrix validation where supported.
When using Traefik with Docker Compose and multiple networks, include the Traefik network label so Traefik routes through the intended network:
traefik.docker.network: << traefik_network >>
For Swarm/Compose-specific label placement, follow existing template patterns before introducing new ones.
Template descriptions may use emoji-style shortcodes such as :warning:, :info:, or :docker:. Display code maps these to Nerd Font icons. Add new shortcodes in the display/icon layer, not directly in template rendering code.