83 lines
2.7 KiB
Markdown
83 lines
2.7 KiB
Markdown
# Docker Swarm
|
|
|
|
**Last updated:** 2026-08-11
|
|
|
|
## Overview
|
|
|
|
Container orchestration uses Docker Swarm managed through Portainer. All
|
|
production services are deployed as Swarm stacks, not standalone containers.
|
|
|
|
## Topology
|
|
|
|
| Role | Hostname | IP |
|
|
|------|----------|----|
|
|
| Swarm manager | impulse-controller | 192.168.50.120 |
|
|
| Database node | memory-archives | 192.168.50.107 |
|
|
| Hypervisor | *(Xen Orchestra)* | 192.168.50.100 |
|
|
|
|
- **Portainer:** https://192.168.50.120:9443
|
|
- **Hypervisor:** Xen (Xen Orchestra UI at 192.168.50.100)
|
|
|
|
## Databases
|
|
|
|
All databases are centralised on `memory-archives` (192.168.50.107):
|
|
|
|
| Engine | Notes |
|
|
|--------|-------|
|
|
| PostgreSQL 16 + pgvector | Primary relational store; vector extension enabled |
|
|
| MySQL | Legacy / compatibility workloads |
|
|
|
|
Services should connect to `memory-archives` by hostname, not IP, where
|
|
Swarm DNS resolves within the overlay network.
|
|
|
|
## Stack YAML Conventions
|
|
|
|
```yaml
|
|
# No top-level 'version:' field — Swarm ignores it and modern Compose drops it
|
|
services:
|
|
myservice:
|
|
image: example/myservice:latest
|
|
restart: unless-stopped # required on all services
|
|
networks:
|
|
- master-proxy-overlay
|
|
deploy:
|
|
labels:
|
|
# Traefik labels go under deploy:, not at the service root
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.myservice.rule=Host(`myservice.pldyn.net`)"
|
|
- "traefik.http.routers.myservice.entrypoints=websecure"
|
|
- "traefik.http.routers.myservice.tls.certresolver=cloudflare"
|
|
# HTTP → HTTPS redirect
|
|
- "traefik.http.routers.myservice-http.rule=Host(`myservice.pldyn.net`)"
|
|
- "traefik.http.routers.myservice-http.entrypoints=web"
|
|
- "traefik.http.routers.myservice-http.middlewares=redirect-to-https@docker"
|
|
|
|
networks:
|
|
master-proxy-overlay:
|
|
external: true
|
|
```
|
|
|
|
Key conventions:
|
|
- No `version:` field at the top of the file
|
|
- `restart: unless-stopped` on every service
|
|
- Traefik labels placed under `deploy:` (not at service root)
|
|
- HTTP→HTTPS redirect middleware included for every public-facing service
|
|
|
|
## Service Discovery
|
|
|
|
Swarm services are referenced by **service name**, not container name.
|
|
Container names are non-deterministic across replicas; service names are
|
|
stable within the overlay network.
|
|
|
|
## Sharp Edges
|
|
|
|
### Portainer env UI passes literal quotes
|
|
|
|
When setting environment variables via the Portainer UI, the value field
|
|
passes content verbatim — including any quotes you type. Do **not** wrap
|
|
values in `"..."` or `'...'` in the UI; the quotes become part of the value
|
|
and will break the application.
|
|
|
|
**Correct:** `MY_VAR=somevalue`
|
|
**Wrong:** `MY_VAR="somevalue"` ← the quotes are included in the string
|