# syntax=docker/dockerfile:1 # # One image, three commands. docker-compose runs it three times with different # entrypoints (api / frontend / redirect). See docker-compose.yml. # --- 1. Build the SPA ------------------------------------------------------- FROM node:20-alpine AS frontend WORKDIR /app COPY package.json package-lock.json* ./ RUN npm ci 2>/dev/null || npm install COPY index.html vite.config.ts tsconfig*.json postcss.config.js tailwind.config.js ./ COPY src ./src COPY public ./public RUN npm run build # -> /app/dist # --- 2. Build the Go binary ------------------------------------------------- FROM golang:1.25-alpine AS backend WORKDIR /src COPY backend/go.mod backend/go.sum ./ RUN go mod download COPY backend/ . RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/snip ./cmd/snip # --- 3. Minimal runtime ----------------------------------------------------- FROM alpine:3.20 RUN apk add --no-cache ca-certificates wget && adduser -D -u 10001 snip WORKDIR /app COPY --from=backend /out/snip /usr/local/bin/snip COPY --from=frontend /app/dist ./web ENV FRONTEND_DIST=/app/web USER snip # Default command; compose overrides with api / frontend / redirect. ENTRYPOINT ["snip"] CMD ["api"]