2.7 KiB
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
# 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-stoppedon 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