# Client/frontend build in an isolated stage # We use node:latest as the base image. # Essentially we build the frontend SPA with vite and # make it available in the public directory. FROM docker.io/node:alpine as client WORKDIR /build ADD frontend ./ RUN npm install RUN npm run build # Builds the server in an isolated stage FROM docker.io/golang:alpine as go RUN apk add gcompat RUN apk add gcc RUN apk add musl-dev RUN apk add sqlite WORKDIR /build ADD backend/go.mod backend/go.sum ./ # Get the dependencies RUN go mod download # Add the source code ADD backend . RUN go build -o server RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o ./server ./main.go # Strip the binary for a smaller image RUN strip ./server # The final stage for building a minimal image FROM docker.io/alpine:latest as runner RUN adduser -D nonroot RUN addgroup nonroot nonroot WORKDIR /app RUN chown nonroot:nonroot /app # Copy the frontend SPA build into public COPY --from=client /build/dist static # Copy the server binary COPY --from=go /build/server server # Expose port 8080 EXPOSE 8080 # Set the user to nonroot USER nonroot:nonroot # Run the server CMD ["./server"]