# Template Canônico — Stack Docker Swarm (Octal) ## Uso ```bash # 1. Copiar template cp runbooks/swarm-stack-template.yml runbooks/.yml # 2. Editar: services, imagens, réplicas, labels Caddy vim runbooks/.yml # 3. Deploy via Docker CLI (Swarm nativo — recomendado) docker stack deploy -c runbooks/.yml # 4. Aplicar labels Caddy via Docker CLI (obrigatório — Swarm não herda do compose) docker service update \ --label-add 'caddy=' \ --label-add 'caddy.reverse_proxy={{upstreams }}' \ _ ``` ## ⚠️ Rede `public` — Attachable=false | Método | Funciona? | Motivo | |--------|-----------|--------| | `docker stack deploy` (CLI) | ✅ SIM | Daemon Docker local ignora a restrição | | Portainer API (`POST /api/stacks`) | ❌ NÃO | Docker Remote API respeita `Attachable=false` | **Decisão**: Usar `docker stack deploy` CLI para todas as stacks. Stacks criadas por CLI aparecem no `docker stack ls` e no Swarm, mas NÃO aparecem como gerenciáveis no Portainer UI. Para ter controle total pelo Portainer, a rede `public` precisaria ser recriada com `--attachable`, o que causaria uma breve interrupção nos containers existentes. Atualmente não vale a pena — 19 containers em produção usam `public`. --- ## Template Completo (v3.9) ```yaml version: '3.9' networks: public: external: true # overlay swarm — Attachable=false (modelo atual) services: : image: : networks: - public deploy: replicas: 1 endpoint_mode: dnsrr # DNS round-robin — necessário para reverse proxy update_config: # zero-downtime deploy parallelism: 1 delay: 10s rollback_config: # rollback automático se falhar parallelism: 1 delay: 10s restart_policy: condition: on-failure max_attempts: 3 ``` --- ## Regras Obrigatórias ### 1. Rede `public` - É a **única rede overlay** do cluster Octal - Criada uma única vez: `docker network create --driver overlay --attachable public` - `Attachable: false` no modelo atual — não alterar sem planejamento - Nunca declarar `external: false` em services — quebra Swarm ### 2. Nomes de serviço - **SEM prefixo** no compose: Swarm injeta `_` automaticamente - Ex: `games-demo` no compose → `project_games-demo` no Swarm ✓ - Ex: `project_games-demo` no compose → `project_project_games-demo` ✗ (duplicado) ### 3. Labels Caddy - **NÃO funcionam pelo compose** — `deploy.labels` não vira `Config.Labels` - Aplicar **obrigatoriamente** via CLI após deploy: `docker service update --label-add 'caddy=' _` ### 4. Labels Traefik (fallback opcional) - Funcionam pelo compose via `deploy.labels`: ```yaml deploy: labels: - traefik.enable=true - traefik.http.routers..rule=Host(``) ``` --- ## Stacks Existentes (referência) | Stack | Criada por | Controlável Portainer? | |-------|------------|----------------------| | `git` | Portainer API | ✅ SIM | | `bot` | Portainer API | ✅ SIM | | `pro` | Portainer API | ✅ SIM | | `design` | Portainer API | ✅ SIM | | `proxy` | Portainer API | ✅ SIM | | `project` | `docker stack deploy` CLI | ⚠️ NÃO (Attachable=false) | | `dock` | Portainer API | ✅ SIM | | `code` | Portainer API | ✅ SIM | | `database` | Portainer API | ✅ SIM |