- Dockerfile: golang:1.23-bookworm builder → distroless/static-debian12:nonroot - docker-compose.yml: host networking (required for mDNS), Traefik labels, resource limits - VERSION: 0.1.0 for image tagging - .dockerignore: excludes docs, build artifacts, IDE files - .gitignore: standard Go/ESP-IDF ignores Key decisions: - Host networking required: Docker bridge blocks mDNS multicast 224.0.0.251 - distroless/static-debian12:nonroot: no shell, minimal attack surface, UID 65532 - Firmware via volume mount: users provide their own binaries for OTA - Traefik labels disabled by default: enable SPAXEL_TRAEFIK_ENABLE=true for TLS Complete: Phase 1 Docker packaging — all foundation items now done Remaining: Phase 2 signal processing (baseline, deltaRMS, Fresnel zones)
87 lines
3 KiB
YAML
87 lines
3 KiB
YAML
# Spaxel Docker Compose
|
|
# Production deployment configuration
|
|
#
|
|
# IMPORTANT: network_mode: host is REQUIRED for mDNS to work.
|
|
# mDNS uses multicast address 224.0.0.251 (link-local), which Docker
|
|
# bridge networking blocks. With host networking, the container shares
|
|
# the host's network interfaces and mDNS multicasts reach the LAN.
|
|
#
|
|
# Side effect: 'ports' mapping is ignored in host mode — port 8080 is
|
|
# directly exposed on the host.
|
|
|
|
services:
|
|
spaxel:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
args:
|
|
VERSION: ${VERSION:-dev}
|
|
# Alternative: use pre-built image
|
|
# image: ghcr.io/spaxel/spaxel:latest
|
|
|
|
# Host networking required for mDNS discovery by ESP32 nodes
|
|
network_mode: host
|
|
|
|
# Alternative (if host mode is not desired): disable mDNS and require
|
|
# nodes to use cached ms_ip NVS key (manual IP entry during provisioning).
|
|
# Set SPAXEL_MDNS_ENABLED=false to skip the mDNS advertisement entirely.
|
|
|
|
volumes:
|
|
- spaxel-data:/data # SQLite, baselines, floor plans, CSI buffer
|
|
- ./firmware:/firmware:ro # Firmware binaries for OTA (read-only)
|
|
|
|
environment:
|
|
# Timezone - required for correct diurnal baseline hours
|
|
TZ: ${TZ:-UTC}
|
|
# mDNS service name (must match firmware ms_mdns NVS key)
|
|
SPAXEL_MDNS_NAME: ${SPAXEL_MDNS_NAME:-spaxel}
|
|
# Set to false if using bridge networking (nodes must use cached IP)
|
|
SPAXEL_MDNS_ENABLED: ${SPAXEL_MDNS_ENABLED:-true}
|
|
# Optional MQTT integration (uncomment to enable)
|
|
# SPAXEL_MQTT_BROKER: mqtt://homeassistant.local:1883
|
|
# SPAXEL_MQTT_USERNAME: mosquitto
|
|
# SPAXEL_MQTT_PASSWORD: secret
|
|
# Debug logging (uncomment for troubleshooting)
|
|
# SPAXEL_LOG_LEVEL: debug
|
|
|
|
restart: unless-stopped
|
|
|
|
# Allow full 30s graceful shutdown
|
|
stop_grace_period: 35s
|
|
|
|
ulimits:
|
|
nofile:
|
|
soft: 4096 # One fd per node connection + SQLite handles
|
|
hard: 8192
|
|
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8080/healthz"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 30s
|
|
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 512m # Increase to 1g for 16+ node fleets
|
|
cpus: "2.0"
|
|
reservations:
|
|
memory: 128m
|
|
cpus: "0.5"
|
|
|
|
# Traefik labels for reverse proxy with TLS
|
|
# Uncomment and customize for your Traefik setup
|
|
labels:
|
|
- "traefik.enable=${TRAEFIK_ENABLE:-false}"
|
|
# - "traefik.http.routers.spaxel.rule=Host(`spaxel.example.com`)"
|
|
# - "traefik.http.routers.spaxel.entrypoints=websecure"
|
|
# - "traefik.http.routers.spaxel.tls.certresolver=letsencrypt"
|
|
# - "traefik.http.services.spaxel.loadbalancer.server.port=8080"
|
|
# # Extend Traefik timeout for long-lived WebSocket connections
|
|
# - "traefik.http.routers.spaxel.middlewares=spaxel-ws-timeout"
|
|
# - "traefik.http.middlewares.spaxel-ws-timeout.headers.respondingTimeouts.readTimeout=3600s"
|
|
|
|
volumes:
|
|
spaxel-data:
|
|
driver: local
|