check / check (push) Successful in 11s
nginx.conf is now a template the nginx image renders into conf.d at container start. bin/entrypoint.sh gives nginx PORT, 8080 when unset or empty, and limits the rendering to PORT with NGINX_ENVSUBST_FILTER, so $uri, $host and every other nginx variable pass through unchanged. A PORT nginx cannot listen on stops the container non-zero. server_tokens off drops the version from the Server header and error pages. script/frontend-viewport-test renders the template the same way. EXPOSE still documents 8080; the backend stays on 127.0.0.1:8081. Model: opus-5-5
90 lines
3.2 KiB
Docker
90 lines
3.2 KiB
Docker
# The one image netwatch ships: nginx serves the built frontend and
|
|
# passes /api/ and /.well-known/healthcheck to netwatch-server, the Go
|
|
# backend, which runs in the same container on loopback only.
|
|
# bin/entrypoint.sh starts and watches both.
|
|
|
|
# Lint stage — fast feedback on formatting and lint issues. The
|
|
# golangci/golangci-lint image ships Go, gofmt, make and the linter, so
|
|
# nothing is installed here. The root make lint builds this stage alone.
|
|
# golangci/golangci-lint:v2.12.2 (2026-08-10)
|
|
FROM golangci/golangci-lint@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240 AS lint
|
|
|
|
WORKDIR /src
|
|
COPY backend/go.mod backend/go.sum ./
|
|
RUN go mod download
|
|
COPY backend/ .
|
|
RUN make fmt-check
|
|
RUN make lint
|
|
|
|
# Backend build stage
|
|
# golang:1.25-alpine (2026-02-27)
|
|
FROM golang:1.25-alpine@sha256:f6751d823c26342f9506c03797d2527668d095b0a15f1862cddb4d927a7a4ced AS builder
|
|
|
|
RUN apk add --no-cache make
|
|
|
|
WORKDIR /src
|
|
|
|
# Force BuildKit to run the lint stage before proceeding. BuildKit runs
|
|
# stages in parallel by default; without this no-op copy a lint failure
|
|
# would not gate compilation.
|
|
COPY --from=lint /src/go.sum /dev/null
|
|
|
|
COPY backend/go.mod backend/go.sum ./
|
|
RUN go mod download
|
|
COPY backend/ .
|
|
|
|
RUN make test
|
|
|
|
# make build is a shim around backend/script/build, the one definition
|
|
# of the build command:
|
|
# CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.Version=... -X main.Buildarch=..."
|
|
# That script reads VERSION from the environment, so it is handed over
|
|
# there rather than as a make variable.
|
|
ARG VERSION=dev
|
|
RUN VERSION="${VERSION}" make build
|
|
|
|
# Frontend stage
|
|
# node:22-alpine as of 2026-02-22
|
|
FROM node@sha256:e4bf2a82ad0a4037d28035ae71529873c069b13eb0455466ae0bc13363826e34 AS frontend
|
|
WORKDIR /app
|
|
COPY package.json yarn.lock ./
|
|
RUN yarn install --frozen-lockfile
|
|
RUN apk add --no-cache git make
|
|
COPY . .
|
|
# make frontend-check is the frontend half of make check (test + lint +
|
|
# fmt-check); its test step is the production yarn build, so this both
|
|
# produces dist/ and gates the image on lint/fmt-check/test regressions.
|
|
# This node stage has neither Go nor Docker; the lint and builder stages
|
|
# above gate the backend half.
|
|
RUN make frontend-check
|
|
|
|
# Runtime stage
|
|
# nginx:stable-alpine as of 2026-02-22
|
|
FROM nginx@sha256:15e96e59aa3b0aada3a121296e3bce117721f42d88f5f64217ef4b18f458c6ab
|
|
|
|
# netwatch-server runs as this user, which owns the report directory.
|
|
# nginx keeps the image's own arrangement: its main process runs as
|
|
# root, its worker processes as the nginx user.
|
|
RUN addgroup -g 1000 -S netwatch && \
|
|
adduser -u 1000 -S netwatch -G netwatch
|
|
|
|
# At start-up the nginx image renders every template here into
|
|
# conf.d; bin/entrypoint.sh says how.
|
|
RUN rm /etc/nginx/conf.d/default.conf
|
|
COPY nginx.conf /etc/nginx/templates/netwatch.conf.template
|
|
COPY --from=frontend /app/dist /usr/share/nginx/html
|
|
COPY --from=builder /src/netwatch-server /usr/local/bin/netwatch-server
|
|
COPY bin/entrypoint.sh /usr/local/bin/entrypoint.sh
|
|
|
|
ENV DATA_DIR=/data/reports
|
|
RUN mkdir -p /data/reports && chown -R netwatch:netwatch /data
|
|
VOLUME /data
|
|
|
|
# The default public port; PORT changes it.
|
|
EXPOSE 8080
|
|
|
|
# The nginx image stops its container with SIGQUIT; the entrypoint
|
|
# acts on TERM and INT.
|
|
STOPSIGNAL SIGTERM
|
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|