# Builder stage FROM golang:1.26-alpine AS builder # Install C compiler and musl headers required for CGO + go-sqlite3 RUN apk add --no-cache gcc musl-dev # Enable CGO (required by github.com/mattn/go-sqlite3) ENV CGO_ENABLED=1 # Cache build and module caches for faster rebuilds ENV GOCACHE=/go-cache ENV GOMODCACHE=/go/pkg/mod # Set working directory WORKDIR /build # Copy dependency manifests first and download modules (cache layer) COPY go.mod go.sum ./ RUN go mod download # Copy the rest of the source code COPY . . # Build a static-ish binary (C code for SQLite is compiled in; musl libc stays dynamic) RUN go build -o /app/server ./cmd/server/ # Runtime stage FROM alpine:3.20 # ca-certificates for TLS, tzdata for timezone support RUN apk add --no-cache ca-certificates tzdata # Create non-root user for better security RUN addgroup -S app && adduser -S app -G app # Set working directory WORKDIR /app # Copy the binary from the builder stage COPY --from=builder /app/server /app/server RUN chmod +x /app/server # Copy static and template assets from the project source COPY --from=builder /build/static /app/static COPY --from=builder /build/templates /app/templates # Ensure the app user owns the working dir RUN chown -R app:app /app # Create data directory owned by app user (for named volume mount) RUN mkdir -p /data && chown app:app /data USER app # Expose the HTTP port EXPOSE 8080 # Default command (runs as 'app' user, DB stored in named volume) CMD ["/app/server", "-addr", ":8080", "-db", "/data/state.db"]