# The frontend is built and published separately; override to pin a version. ARG FRONTEND_IMAGE=gitea.sanplex.xyz/sansan/musicfrontend:latest # Stage 1: Build the backend on the build machine and cross-compile for the target platform, # so multi-platform builds need no emulation. FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS build ARG TARGETOS TARGETARCH WORKDIR /app COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod go mod download COPY cmd/ ./cmd/ COPY internal/ ./internal/ RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ go tool templ generate RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ go build -trimpath -ldflags="-s -w" -tags timetzdata -o main ./cmd # Stage 2: Frontend static files (the same for every platform) FROM --platform=$BUILDPLATFORM ${FRONTEND_IMAGE} AS frontend # Empty API_HOSTNAME makes the frontend use relative paths RUN echo "window.__RUNTIME_CONFIG__ = { API_HOSTNAME: '' };" > /usr/share/nginx/html/config.js # Stage 3: Final image. No RUN steps here, so no emulation is needed for other architectures. FROM alpine:3.22 COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ WORKDIR /app COPY --from=build /app/main . COPY --from=frontend /usr/share/nginx/html /frontend COPY ./songs/ ./songs/ # The music volume must be readable by uid 1000, and writable for the .id file cleanup during sync. USER 1000:1000 EXPOSE 8080 VOLUME /sorted VOLUME /characters # Required: DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD, DB_NAME, MUSIC_PATH, CHARACTERS_PATH ENV PORT=8080 CMD ["./main"]