5.4 KiB
| title | description | published | date | tags | editor | dateCreated |
|---|---|---|---|---|---|---|
| Docker Template | Swarm and Compose Template | true | 2026-04-10T19:53:21.433Z | markdown | 2026-04-10T19:53:21.433Z |
Docker Swarm Template Standard — Netgrimoire
Template
# Run with docker stack deploy -c <service>.yaml <service>
services:
<servicename>:
image: <image>:latest
environment:
TZ: America/Chicago
volumes:
- /DockerVol/<servicename>:/config # use WITH placement constraint
# - /data/nfs/znas/Docker/<servicename>:/data # use for bulk/data or no constraint
networks:
- netgrimoire
deploy:
restart_policy:
condition: any
delay: 5s
max_attempts: 3
window: 120s
placement:
constraints:
- node.platform.arch != aarch64
- node.platform.arch != arm
labels:
# --- Caddy ---
caddy: <servicename>.netgrimoire.com
caddy.reverse_proxy: <servicename>:<PORT>
caddy.import: crowdsec
caddy.import_1: authentik
# --- Uptime Kuma ---
kuma.<servicename>.http.name: <Service Name>
kuma.<servicename>.http.url: https://<servicename>.netgrimoire.com
# --- Homepage ---
homepage.group: <Group>
homepage.name: <Service Name>
homepage.icon: <service>.png
homepage.href: https://<servicename>.netgrimoire.com
homepage.description: <Description>
# --- DIUN ---
diun.enable: "true"
networks:
netgrimoire:
external: true
Rules
Forbidden Fields
Never use these at the service level:
version:— deprecated in Compose v2+container_name:— incompatible with Swarm replicasrestart:— usedeploy.restart_policyinsteaddepends_on:— not supported in Swarm mode
Volume Path Rules
| Path | When to Use |
|---|---|
/DockerVol/<service> |
Config/state files. Only valid when a placement constraint pins the service to a specific host. |
/data/nfs/znas/Docker/<service> |
Data/bulk volumes, or any service without a specific hostname constraint |
Caddy Labels
caddy: service.netgrimoire.com
caddy.reverse_proxy: servicename:PORT
caddy.import: crowdsec
caddy.import_1: authentik
caddy.import_1is required for the second import — duplicate YAML keys cause deploy errorscaddy.reverse_proxyusesservicename:PORT(internal Docker DNS), never{{upstreams PORT}}- No
https://prefix on thecaddy:address line - Services managed by Caddyfile (static config) must not also have Caddy Docker labels — mixing causes caddy-docker-proxy to merge them into a malformed upstream pool
Networking
- Default VIP mode for services that publish ports
endpoint_mode: dnsrrfor internal-only services (no published ports) — avoids Swarm VIP stale DNS- Never use
dnsrron services with published ports — incompatible with ingress mesh routing
Placement Constraints
Architecture exclusions (always include unless ARM-specific):
constraints:
- node.platform.arch != aarch64 # Pi 4 reports aarch64
- node.platform.arch != arm # Pi 3 reports arm
Note: Docker Swarm uses the kernel's arch string. Pi 4 reports aarch64 not arm64. The constraint != arm64 does not exclude Pi 4s.
Verified node architectures in Netgrimoire:
DockerPi1: linux/aarch64
docker3: linux/x86_64
docker4: linux/x86_64
docker5: linux/x86_64
znas: linux/x86_64
Label Sections
Labels are organized with comment dividers in this order:
labels:
# --- Caddy ---
# --- Uptime Kuma ---
# --- Homepage ---
# --- DIUN ---
Use map syntax (not list syntax) for labels. List syntax (- key=value) and map syntax (key: value) both work, but map syntax is the standard.
Services Without a UI
Some services have no web interface and need no Caddy, Homepage, or Kuma labels:
Example: DIUN
deploy:
labels:
# --- DIUN ---
diun.enable: "true"
Services in this category: DIUN, background workers, one-shot jobs.
Kuma Label Format
kuma.<unique-id>.<monitor-type>.<field>: <value>
unique-id— must be unique across all services in the entire Swarmmonitor-type—http,tcp,ping,dns- Common fields:
name,url,interval,maxretries
Example:
kuma.forgejo.http.name: Forgejo
kuma.forgejo.http.url: https://git.netgrimoire.com
Homepage Label Format
homepage.group: Group Name
homepage.name: Display Name
homepage.icon: icon.png
homepage.href: https://service.netgrimoire.com
homepage.description: Short description
For services with widgets:
homepage.widget.type: radarr
homepage.widget.url: http://radarr:7878
homepage.widget.key: apikey
Important: Every homepage.group value must have a matching entry in settings.yaml with style: column, or the group will render full-width.
Secrets Approach
Docker Swarm native secrets are preferred. For services that support _FILE env vars:
environment:
MY_PASSWORD_FILE: /run/secrets/my_password
secrets:
- my_password
Plain credentials in environment vars are acceptable as an interim approach for services that don't support _FILE.
Never use env_file: in Swarm stacks — it's read by the Docker client at deploy time from the deploying machine, not injected into the container at runtime. Use environment: directly.