check / check (push) Successful in 10s
The root Dockerfile builds the only image; Dockerfile.backend is gone. Its stages: lint, a Go stage that runs the tests and builds netwatch-server, the node stage, and an nginx runtime. nginx serves dist/ on 8080 and proxies /api/ and /.well-known/healthcheck to the backend on 127.0.0.1:8081. bin/entrypoint.sh starts both, turns TERM or INT into a stop of both, and exits non-zero when either exits on its own. The backend runs as user netwatch and keeps reports on the /data volume. New setting BIND_ADDRESS (empty: every interface). STOPSIGNAL is SIGTERM, since the nginx image's SIGQUIT would miss the entrypoint. script/docker is the org model verbatim. Model: opus-5-5
87 lines
3.1 KiB
Docker
87 lines
3.1 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
|
|
|
|
RUN rm /etc/nginx/conf.d/default.conf
|
|
COPY nginx.conf /etc/nginx/conf.d/netwatch.conf
|
|
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
|
|
|
|
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"]
|