Templates
Um template é a especificação declarativa de um serviço — descreve a imagem, as rotas, o armazenamento, as dependências, os segredos, a configuração e o ciclo de vida em um único YAML. Todo deploy do DeployAlly parte de um template.
O autor escreve o archetype primeiro; tudo que vem depois são decorações tipadas dele. Os defaults vêm do archetype, e o template só sobrescreve o que é específico do serviço.
Estrutura
Um template é organizado em blocos. Os obrigatórios são poucos; o resto é opcional e gerado/derivado pelo archetype quando omitido.
spec: "3"
identity: # quem é o serviço
slug: memos
name: Memos
archetype: application
app_version: "0.22.0"
family: notes
image: # qual imagem e quais variantes
base: neosmemo/memos
variants:
- { id: stable, tag: "0.22.0", default: true }
- { id: latest, tag: stable }
routes: # exposição HTTP / TCP
- id: web
kind: http
port: 5230
host: ${input.WEB_HOSTNAME}
tls: { cert_resolver: letsencrypt }
storage: # volumes, binds, config files
- id: data
kind: volume
mount: /var/opt/memos
secrets: {} # credenciais geradas/persistidas
config: # inputs do usuário
required:
WEB_HOSTNAME:
type: hostname
help: "Hostname público (ex: memos.example.com)."
runtime: # env, network, restart policy
env:
MEMOS_MODE: ${input.MEMOS_MODE}
healthcheck: # como medir saúde
mode: external_http
path: /healthz
actions: # operações sob demanda
- { slug: restart, type: docker_op, operation: restart }Blocos Obrigatórios
| Bloco | Função |
|---|---|
spec |
Versão do schema. Sempre "3". |
identity |
Slug, nome, archetype, family e versão. |
image |
Imagem base e variantes (tags suportadas). |
config |
Inputs que o usuário fornece no deploy. |
healthcheck |
Como o DeployAlly mede se o serviço está vivo. |
Os blocos routes e storage são obrigatórios para a maioria dos archetypes (uma aplicação web precisa de rota, um banco precisa de volume), mas o archetype worker aceita ambos vazios.
Blocos Opcionais
| Bloco | Função |
|---|---|
secrets |
Credenciais geradas e persistidas localmente (senhas, hex, tokens). |
needs |
Dependências de outros serviços (ver Ecologia). |
provides |
O que este serviço oferece a outros (functions, exports). Usado por assets. |
runtime |
Env vars, restart policy, modo de rede. |
resources |
Limites e requests de memória/CPU. |
actions |
Operações sob demanda (restart, dump, etc.). |
lifecycle |
Hooks post_deploy e pre_decommission. |
profiles |
Variações declarativas (development, production, etc.). |
Archetypes
O identity.archetype é um enum fechado — apenas seis valores são válidos. Cada archetype carrega defaults próprios e regras de exposição/escopo.
| Archetype | Uso típico | Default healthcheck | Default scope |
|---|---|---|---|
application |
App único com rota HTTP (CMS, painel, ferramenta web) | external_http |
shared |
asset |
Serviço de infraestrutura compartilhado (banco, cache, fila) | external_tcp |
singleton |
static |
Site estático servido por nginx/caddy | external_http em / |
shared |
worker |
Processo headless sem HTTP (filas, jobs, cron) | stable_state (settle 30s) |
shared |
multi_component_saas |
App com múltiplos containers (web + worker + …) | por componente | shared |
network_appliance |
Proxy/ingress de rede (traefik) | exit ou external_tcp |
singleton |
Detalhes de cada archetype e como eles se relacionam estão em Ecologia.
Image: Single ou Multi-Variant
O bloco image aceita duas formas:
Single ref — o serviço só tem uma imagem fixa:
image: traefik:v3.5Multi-variant — o serviço oferece várias versões (LTS, latest, alpine, etc.) e o usuário escolhe uma no deploy:
image:
base: mariadb
variants:
- { id: "11.4", tag: "11.4", default: true, description: "11.4 LTS (recomendado)" }
- { id: "10.11", tag: "10.11", description: "10.11 LTS (legado)" }
- { id: latest, tag: latest, description: "Rolling release" }A variant marcada com default: true vence quando nenhuma é especificada. O CLI aceita --variant <id> para escolher explicitamente.
Storage: Tipos
O bloco storage declara onde o serviço persiste dados. Os tipos suportados:
| Kind | Descrição | Exemplo de uso |
|---|---|---|
volume |
Bind mount gerenciado, resolvido automaticamente pelo engine em /data/ (ver abaixo) |
Banco de dados, uploads |
bind |
Bind mount de um path de sistema fixo (ex: /var/run/docker.sock, /etc/...) |
Socket do Docker, configs vivas do host |
config_file |
Arquivo único renderizado a partir de template + bind-mount, dentro do mesmo base resolvido do volume |
nginx.conf, redis.conf |
tmpfs |
Volume em memória, descartado no stop | Caches efêmeros, sockets |
Resolução de `kind: volume` (client >= 0.45.0)
Templates não declaram o path no host — só o id e o mount (ponto de montagem
dentro do container). O client resolve o bind automaticamente a partir da taxonomia
do template:
identity.archetype: application→/data/apps/{instance_uid}/{id}- Qualquer outro archetype (
asset,infrastructure,network_appliance, etc.) →/data/assets/{species}/{instance_uid}/{id}
O diretório é criado pelo client no momento do deploy. Se o volume declarar owner:
(uid/gid), o client tenta aplicar chown — falha de chown gera apenas um warning,
não interrompe o deploy.
kind: config_file segue a mesma base resolvida do volume: o arquivo renderizado
fica em {base}/config/{filename} (ex: /data/assets/mysql/{instance_uid}/config/custom.cnf).
Nada é escrito em disco quando o deploy roda com --dry-run.
kind: bind continua reservado a paths de sistema — o validador rejeita
qualquer host_path declarado sob /opt/ (reservado às ferramentas CCS: runner,
deployally, backupally, etc.).
Volumes Docker nomeados (named volumes): templates atuais não criam mais volumes nomeados. Deploys antigos (anteriores ao client 0.45.0) que ainda usam named volumes continuam funcionando até o próximo redeploy — o client não migra os dados automaticamente. Migração é manual: copiar os dados do volume nomeado para o path
/data/...resolvido antes de redeployar com o template atualizado.
Exemplo combinando volume e config file:
storage:
- id: data
kind: volume
mount: /var/lib/mysql
owner:
uid: 999
gid: 999
- id: my-cnf
kind: config_file
mount: /etc/mysql/conf.d/custom.cnf
content: |
[mysqld]
max_connections = ${input.MAX_CONNECTIONS}Antes (era de volume nomeado, obsoleto) / Depois (resolução em /data/):
# ANTES — volume Docker nomeado declarado direto no compose (não usar em templates novos)
volumes:
- mysql_data:/var/lib/mysql
# DEPOIS — kind: volume, path resolvido pelo engine
storage:
- id: data
kind: volume
mount: /var/lib/mysql
# archetype: asset, species: mysql → resolve para:
# /data/assets/mysql/{instance_uid}/dataRoutes
Rotas declaram como o serviço é alcançado. kind: http faz o DeployAlly emitir labels Traefik com TLS via Let's Encrypt; kind: tcp expõe uma porta L4. Assets normalmente têm routes: [] (só são acessíveis por outros containers via rede dedicada).
routes:
- id: web
kind: http
port: 80
host: ${input.WEB_HOSTNAME}
tls:
cert_resolver: letsencryptReflang: Referências Tipadas
Todo valor dinâmico em um template usa a sintaxe ${namespace.path}. Os namespaces:
| Namespace | Origem | Exemplo |
|---|---|---|
${input.X} |
Input fornecido pelo usuário | ${input.WEB_HOSTNAME} |
${secrets.X} |
Secret gerado/persistido | ${secrets.WP_DB_PASSWORD} |
${self.X} |
Auto-referência ao próprio container | ${self.container.name} |
${instance.X} |
Metadados da instância | ${instance.uid} |
${needs.X} |
Output de um asset dependente | ${needs.database.host} |
${asset.X.Y} |
Introspecção de asset por classe | ${asset.database.host} |
${tenant.X} |
Contexto multi-tenant | ${tenant.slug} |
${context.X} |
Estado do host (containers, portas) | ${context.port_in_use} |
${system.X} |
Informação do sistema | ${system.ip}, ${system.memory_mb} |
${env.X} |
Variável de ambiente do host | ${env.DOCKER_HOST} |
A resolução é tipada e checada em preflight — um ${needs.database.host} quebra se o asset não declarar esse export.
Profiles
profiles permite variações declarativas do mesmo template. O usuário escolhe um profile no deploy (--profile development) e o template aplica overrides:
profiles:
development:
description: "Memória reduzida + modo dev."
overrides:
resources.memory.limit: 128M
config.optional.MEMOS_MODE.default: dev
production:
description: "Sizing padrão para produção."
overrides:
resources.memory.limit: 256M
config.optional.MEMOS_MODE.default: prodPróximos Passos
- Ecologia — Os seis archetypes em detalhe e como eles se relacionam.
- Taxonomia — Como kingdom/family/species organizam o catálogo.
- Definitions e Instances — Como um template vira um container rodando.
- Manifestos — Onde a instância persiste estado e segredos.