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.5

Multi-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}/data

Routes

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: letsencrypt

Reflang: 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: prod

Pró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.
By Borlot.com.br on 05/06/2026