From 7d875ea19a1e10ebb75ae3c2f5b4c64a0dd080b3 Mon Sep 17 00:00:00 2001 From: Vassiliy Yegorov Date: Sat, 4 Jul 2026 16:15:55 +0700 Subject: [PATCH] build: multi-stage Dockerfile (node build -> go embed -> distroless) Three-stage image: node:22-alpine builds the Vite SPA, golang:1.26.4-alpine compiles the server with the built SPA copied into the //go:embed path before build, distroless/static-debian12:nonroot runs the static binary as non-root on :8080. .dockerignore keeps node_modules/dist/docs/git out of the build context while preserving the internal/web/dist/index.html placeholder needed for a valid embed target pre-COPY. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3 --- .dockerignore | 9 +++++++++ Dockerfile | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7469d15 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.git +.superpowers +docs +web/node_modules +web/dist +internal/web/dist/assets +swarm-report +*.md +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7e0c0fc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +# syntax=docker/dockerfile:1 + +# --- web build --- +FROM node:22-alpine AS web +WORKDIR /src/web +COPY web/package.json web/package-lock.json ./ +RUN npm ci +COPY web/ ./ +RUN npm run build + +# --- go build --- +FROM golang:1.26.4-alpine AS build +WORKDIR /src +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +# SPA собрана на web-стадии — кладём в embed-путь ДО go build +COPY --from=web /src/web/dist ./internal/web/dist +RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/app ./cmd/server + +# --- runtime --- +FROM gcr.io/distroless/static-debian12:nonroot +COPY --from=build /out/app /app +EXPOSE 8080 +USER nonroot:nonroot +ENTRYPOINT ["/app"]