spaxel/Dockerfile
jedarden 3f2962f945 feat(deploy): Docker packaging with multi-stage build and compose orchestration
- 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)
2026-03-26 07:46:15 -04:00

44 lines
1.2 KiB
Docker

# Spaxel Mothership Dockerfile
# Multi-stage build for minimal production image
# Stage 1: Build the Go binary
FROM golang:1.23-bookworm AS builder
WORKDIR /app
# Copy Go module files first for better caching
COPY mothership/go.mod mothership/go.sum ./
RUN go mod download
# Copy source code
COPY mothership/ ./
# Build the binary
# CGO_ENABLED=0 because we use pure-Go SQLite (modernc.org/sqlite)
ARG VERSION=dev
RUN CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w -X main.version=${VERSION}" \
-o spaxel ./cmd/mothership
# Stage 2: Minimal runtime image
FROM gcr.io/distroless/static-debian12:nonroot
# Copy the binary
COPY --from=builder /app/spaxel /spaxel
# Copy dashboard static files (served from filesystem at runtime)
COPY dashboard/ /dashboard/
# Create firmware directory (users should mount their own firmware volume)
# The container will serve firmware binaries for OTA from /firmware/
VOLUME ["/data", "/firmware"]
# Expose HTTP/WebSocket port
EXPOSE 8080
# Health check (distroless has wget)
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
["wget", "-q", "-O-", "http://localhost:8080/healthz"]
# Run as non-root (distroless default is UID 65532)
ENTRYPOINT ["/spaxel"]