mirror of
https://github.com/tiennm99/noitu.git
synced 2026-10-06 04:14:49 +00:00
expvar counters for connections, rooms, games, submissions by rejection reason, eliminations, chat, joins and bot moves, served on a separate debug address so they never sit on the public mux, plus one structured word_rejected log line per refused word carrying the normalized word and its link. GET /readyz flips to 503 while draining; SIGTERM stops new rooms, waits up to NOITU_DRAIN_TIMEOUT for live games, then shuts down. GET /version and the startup log carry the build's git describe. Fuzz targets for the frame decoder, the text sanitizer and Vietnamese normalization; the last one found that composing before lowercasing could leave a non-NFC result, now recomposed after lowering. CI runs on dev as well as main, gates gofmt and golangci-lint, tracks the buf major instead of an exact pin, and dependabot watches every ecosystem. The lint findings that had been hidden by the default per-issue cap are fixed.
88 lines
3.6 KiB
Docker
88 lines
3.6 KiB
Docker
# One image: the binary, the built frontend, and the derived dictionary.
|
|
#
|
|
# The upstream dump is downloaded in a builder stage and never reaches the
|
|
# final image — only the few-MB database derived from it does. That
|
|
# derived database is CC BY-SA 4.0 while the code is Apache-2.0, so it is
|
|
# copied in as its own layer alongside its licence and attribution rather than
|
|
# being embedded in the binary.
|
|
|
|
# --- the frontend -----------------------------------------------------------
|
|
FROM node:24-alpine AS web
|
|
|
|
WORKDIR /src/web
|
|
COPY web/package.json web/package-lock.json ./
|
|
RUN npm ci
|
|
COPY web/ ./
|
|
RUN npm run build
|
|
|
|
# --- the binary -------------------------------------------------------------
|
|
FROM golang:1.25-alpine AS build
|
|
|
|
# What GET /version answers and the startup log line carries. .dockerignore
|
|
# deliberately keeps .git out of the build context — a stale copy should
|
|
# never ship — so git describe cannot run in here; a caller that wants a real
|
|
# version passes it in, the way `make image` does. Unset, this defaults to
|
|
# "dev", which is honest about an unstamped build.
|
|
ARG VERSION=dev
|
|
|
|
WORKDIR /src/server
|
|
COPY server/go.mod server/go.sum ./
|
|
RUN go mod download
|
|
COPY server/ ./
|
|
# CGO_ENABLED=0 is what makes a distroless static image possible, and it works
|
|
# because the SQLite driver is pure Go.
|
|
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w -X main.version=${VERSION}" -o /out/noitu-server ./cmd/noitu-server
|
|
RUN CGO_ENABLED=0 go build -trimpath -o /out/build-dictionary ./cmd/build-dictionary
|
|
|
|
# --- the dictionary ---------------------------------------------------------
|
|
FROM alpine:3.22 AS dict
|
|
|
|
# Fetched fresh, not pinned: Wikimedia regenerates the dump monthly and
|
|
# repoints `latest/`. The derived dictionary is the one thing in this image
|
|
# that cannot be rebuilt from the repository alone, so the builder records the
|
|
# SHA-256 of the file it read in the database's meta table. The Makefile uses
|
|
# the same URL for local builds, and a test asserts the two agree.
|
|
ARG DICT_URL=https://dumps.wikimedia.org/viwiktionary/latest/viwiktionary-latest-pages-articles.xml.bz2
|
|
|
|
# Set to 1 to build from the checked-in word sample instead of downloading the
|
|
# upstream dump. That produces a playable but tiny dictionary, and exists so
|
|
# the image itself can be smoke-tested without network access.
|
|
ARG FIXTURE_DICT=0
|
|
|
|
RUN apk add --no-cache curl
|
|
WORKDIR /work
|
|
COPY --from=build /out/build-dictionary /usr/local/bin/build-dictionary
|
|
COPY testdata/fixture-words.txt ./fixture-words.txt
|
|
|
|
RUN set -eu; \
|
|
mkdir -p /out; \
|
|
if [ "$FIXTURE_DICT" = "1" ]; then \
|
|
build-dictionary --words ./fixture-words.txt --out /out/noitu.db --min-words 150; \
|
|
else \
|
|
curl -fsSLR -o viwiktionary-latest-pages-articles.xml.bz2 "$DICT_URL"; \
|
|
build-dictionary --dump ./viwiktionary-latest-pages-articles.xml.bz2 --out /out/noitu.db; \
|
|
fi
|
|
|
|
# --- the image --------------------------------------------------------------
|
|
FROM gcr.io/distroless/static-debian12:nonroot
|
|
|
|
WORKDIR /app
|
|
COPY --from=build /out/noitu-server /app/noitu-server
|
|
COPY --from=web /src/web/build /app/web
|
|
|
|
# The share-alike half of the image. data/LICENSE and data/ATTRIBUTION.md ship
|
|
# with the derived wordlist because CC BY-SA 4.0 applies to it wherever it is
|
|
# distributed, and a container image is distribution.
|
|
COPY --from=dict /out/noitu.db /app/data/noitu.db
|
|
COPY data/LICENSE /app/data/LICENSE
|
|
COPY data/ATTRIBUTION.md /app/data/ATTRIBUTION.md
|
|
COPY NOTICE /app/NOTICE
|
|
|
|
ENV NOITU_ADDR=:8080 \
|
|
NOITU_DB_PATH=/app/data/noitu.db \
|
|
NOITU_WEB_DIR=/app/web
|
|
|
|
EXPOSE 8080
|
|
USER nonroot:nonroot
|
|
ENTRYPOINT ["/app/noitu-server"]
|