Ecologia de Serviços

O DeployAlly organiza serviços em um ecossistema onde cada componente tem seu papel e se relaciona com outros através de dependências e networks.

Modelo de Camadas

Serviços são organizados em três camadas:

┌─────────────────────────────────────────────────┐
│              APPLICATIONS (Camada 2)            │
│         WordPress, n8n, Mautic, Chatwoot        │
│                   Priority: 20+                 │
└─────────────────────────────────────────────────┘
                        │
                        ▼ Dependem de
┌─────────────────────────────────────────────────┐
│                ASSETS (Camada 1)                │
│           MySQL, PostgreSQL, Redis              │
│               Priority: 5-10                    │
└─────────────────────────────────────────────────┘
                        │
                        ▼ Dependem de
┌─────────────────────────────────────────────────┐
│            INFRASTRUCTURE (Camada 0)            │
│          Traefik, Prometheus, Networks          │
│                Priority: 1-4                    │
└─────────────────────────────────────────────────┘

Ordem de Deploy

O campo priority define a ordem:

Camada Priority Exemplos
Infrastructure 1-4 Traefik, networks
Assets 5-10 MySQL, Redis
Applications 20+ WordPress, n8n

Serviços com priority menor são deployados primeiro.


Tipos de Dependência

Assets (Infraestrutura Compartilhada)

Assets são serviços que podem ser compartilhados entre múltiplas aplicações:

MySQL (Asset)
├── WordPress (usa banco 'wordpress')
├── Mautic (usa banco 'mautic')
└── App Custom (usa banco 'custom')

Características:

  • Um MySQL pode servir várias aplicações
  • Cada app tem seu próprio database
  • Network compartilhada para comunicação

Applications (Específicas)

Applications dependem de Assets mas não são compartilhadas:

WordPress
├── Depende de: MySQL (obrigatório)
├── Depende de: Redis (opcional)
└── Única instância por site

Network Topology

O DeployAlly cria networks Docker para isolamento e comunicação:

Docker Networks:
┌──────────────────────────────────────────────────┐
│ public (created by Traefik)                      │
│   └── Traefik, WordPress, n8n, Mautic           │
└──────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────┐
│ mysql (created by MySQL)                         │
│   └── MySQL, WordPress, Mautic                  │
└──────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────┐
│ redis (created by Redis)                         │
│   └── Redis, WordPress, n8n                     │
└──────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────┐
│ postgresql (created by PostgreSQL)               │
│   └── PostgreSQL, n8n, Chatwoot                 │
└──────────────────────────────────────────────────┘

Service Discovery

Dentro de uma network, containers se encontram por hostname:

Network Hostname Porta
mysql mysql 3306
redis redis 6379
postgresql postgresql 5432

Exemplo: WordPress conecta em mysql:3306 via DNS interno.


Fluxo de Resolução de Dependências

Quando você faz deploy de uma aplicação, o DeployAlly resolve dependências automaticamente:

Exemplo: Deploy WordPress

1. WordPress solicitado
   │
   ▼
2. Check: MySQL existe?
   ├── SIM → Pegar conexão (host, database, credentials)
   └── NÃO → Prompt: "MySQL não encontrado. Criar?"
              │
              ▼
3. Deploy MySQL (se necessário)
   ├── Criar network 'mysql'
   ├── Criar container
   ├── Aguardar healthcheck
   └── Retornar: hostname, credentials
   │
   ▼
4. Check: Redis existe? (opcional)
   ├── SIM → Configurar cache Redis
   ├── NÃO (user recusa) → Usar file cache
   └── NÃO (user aceita) → Deploy Redis primeiro
   │
   ▼
5. Deploy WordPress
   ├── Injetar variáveis de ambiente:
   │   ├── WORDPRESS_DB_HOST=mysql
   │   ├── WORDPRESS_DB_NAME=wordpress
   │   └── WORDPRESS_DB_PASSWORD=***
   ├── Juntar networks: public, mysql, redis
   └── Container conecta via DNS interno

Exports e Variáveis

Dependências exportam variáveis para as aplicações:

# Playbook do MySQL
exports:
  - container.name         # mysql
  - MYSQL_DATABASE         # app_db
  - MYSQL_USER             # app_user
  - MYSQL_PASSWORD         # ***

# Playbook do WordPress
dependencies:
  assets:
    - slug: mysql
      exports:
        - from: container.name
          to: WORDPRESS_DB_HOST
        - from: MYSQL_DATABASE
          to: WORDPRESS_DB_NAME
        - from: MYSQL_USER
          to: WORDPRESS_DB_USER
        - from: MYSQL_PASSWORD
          to: WORDPRESS_DB_PASSWORD
          secret: true

Resultado no container WordPress:

WORDPRESS_DB_HOST=mysql
WORDPRESS_DB_NAME=app_db
WORDPRESS_DB_USER=app_user
WORDPRESS_DB_PASSWORD=***

Dependências Alternativas

Algumas aplicações suportam múltiplas opções:

n8n: PostgreSQL ou MySQL

dependencies:
  assets:
    - slug: database
      alternatives:
        - slug: postgresql
          exports:
            - from: container.name
              to: DB_POSTGRESDB_HOST
        - slug: mysql
          exports:
            - from: container.name
              to: DB_MYSQLDB_HOST
      provision:
        action: prompt
        message: "Qual database usar?"
        options:
          - label: "PostgreSQL (recomendado)"
            template: postgresql
          - label: "MySQL"
            template: mysql

O usuário escolhe qual database usar durante o deploy.


Dependências Opcionais com Fallback

Quando uma dependência é opcional, defina comportamento alternativo:

WordPress: Redis Opcional

- slug: redis
  optional: true
  check:
    type: container
    label: "da_type=redis"
  provision:
    action: prompt
    message: "Redis melhora performance. Adicionar?"

  fallback:
    env:
      WP_CACHE_TYPE: "file"

  when_present:
    env:
      WP_CACHE_TYPE: "redis"
      WP_REDIS_HOST: "redis"
Cenário Resultado
Redis não existe, user recusa WP_CACHE_TYPE=file
Redis não existe, user aceita Deploy Redis, depois WP_CACHE_TYPE=redis
Redis já existe WP_CACHE_TYPE=redis

Exemplo Completo: Stack WordPress

                    ┌─────────────┐
                    │   Traefik   │
                    │  (Ingress)  │
                    └──────┬──────┘
                           │ public network
                           │
              ┌────────────┴────────────┐
              ▼                         ▼
       ┌─────────────┐          ┌─────────────┐
       │  WordPress  │          │  phpMyAdmin │
       └──────┬──────┘          └──────┬──────┘
              │                        │
    ┌─────────┴─────────┐              │
    │                   │              │
    ▼                   ▼              │
┌─────────┐       ┌─────────┐          │
│  MySQL  │◄──────│  Redis  │          │
│         │       │ (cache) │          │
└─────────┘       └─────────┘          │
    ▲                                  │
    │                                  │
    └──────────────────────────────────┘

Networks

Container Networks
Traefik public (host mode)
WordPress public, mysql, redis
phpMyAdmin public, mysql
MySQL mysql
Redis redis

Ordem de Deploy

  1. Traefik (priority: 1)
  2. MySQL (priority: 5)
  3. Redis (priority: 6)
  4. WordPress (priority: 20)
  5. phpMyAdmin (priority: 25)

Singleton Services

Alguns serviços só podem ter uma instância:

# Traefik playbook
rules:
  - name: singleton_check
    when:
      all:
        - context.containers_with_label("da_type=traefik").count > 0
    then:
      action: fail
      message: "Traefik já está rodando. Apenas uma instância permitida."

Serviços singleton:

  • Traefik: Um por servidor (gerencia todas as rotas)
  • Prometheus: Um por servidor (coleta métricas)

Labels CCS

O DeployAlly usa labels para identificar e relacionar containers:

labels:
  ccs.systems/project: wordpress-blog
  ccs.systems/type: application
  ccs.systems/env: production

  da_type: wordpress
  da_instance: wordpress_abc123
  da_depends_on: mysql_def456,redis_ghi789

Consultas por Label

# Containers de um projeto
docker ps --filter "label=ccs.systems/project=wordpress-blog"

# Todos os assets
docker ps --filter "label=da_type=mysql"
docker ps --filter "label=da_type=redis"

# Dependências de um container
docker inspect wordpress_abc123 --format '{{index .Config.Labels "da_depends_on"}}'

Ciclo de Vida

Deploy

1. Verificar dependências
2. Provisionar assets faltantes
3. Coletar exports das dependências
4. Criar networks necessárias
5. Deploy do container
6. Juntar networks
7. Executar post-deploy hooks

Update

1. Verificar estado atual
2. Backup se necessário
3. Atualizar configuração
4. Recriar container
5. Verificar healthcheck
6. Rollback se falhar

Delete

1. Verificar dependentes (quem usa este serviço?)
2. Avisar se há dependentes
3. Parar container
4. Remover volumes (opcional)
5. Limpar network se vazia
6. Remover manifesto

Dependentes

Antes de deletar, o DeployAlly verifica se outros serviços dependem:

deployally delete mysql_abc123
Warning: Os seguintes serviços dependem de mysql_abc123:
  - wordpress_def456
  - mautic_ghi789

Remover mesmo assim? [y/N]

Boas Práticas

  1. Use assets compartilhados: Um MySQL para várias apps é mais eficiente
  2. Defina networks claras: Cada asset cria sua network
  3. Ordem de deploy: Respeite as prioridades
  4. Dependências explícitas: Declare todas no playbook
  5. Fallbacks: Sempre defina comportamento para deps opcionais
  6. Labels consistentes: Use padrão CCS para rastreabilidade

Próximos Passos

By Borlot.com.br on 13/02/2026