check / check (push) Waiting to run
The runtime image no longer sets USER. Its new entrypoint, deploy/docker-entrypoint.sh, runs as root: it creates the data directory if needed, gives it and everything in it to the dnswatcher user (uid 10001) with mode 700 on the directory, then runs dnswatcher as that user with su-exec. A bind-mounted host directory, whether empty and root-owned or holding a state file left by another uid, no longer has to be chowned first, and the README's upaas section now says only which path to mount. The startup check that the data directory is writable stays. Model: opus-5-5
74 lines
2.6 KiB
Docker
74 lines
2.6 KiB
Docker
# Lint stage - fast feedback on lint issues, before the build starts.
|
|
# The linter is invoked directly rather than through `make lint`: that
|
|
# target shells out to `docker build -f Dockerfile.lint`, and there is
|
|
# no docker daemon inside a docker build.
|
|
# script/cibuild and script/docker name this stage in --no-cache-filter.
|
|
# golangci/golangci-lint:v2.12.2 (Debian-based), 2026-08-10
|
|
FROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240 AS lint
|
|
|
|
WORKDIR /src
|
|
COPY go.mod go.sum ./
|
|
RUN go mod download
|
|
|
|
COPY . .
|
|
|
|
RUN make fmt-check
|
|
RUN golangci-lint run --config .golangci.yml ./...
|
|
|
|
# Build stage
|
|
# script/cibuild and script/docker name this stage in --no-cache-filter.
|
|
# golang 1.25-alpine, 2026-02-28
|
|
FROM golang@sha256:f6751d823c26342f9506c03797d2527668d095b0a15f1862cddb4d927a7a4ced AS builder
|
|
|
|
RUN apk add --no-cache git make gcc musl-dev binutils-gold
|
|
|
|
# Force BuildKit to run the lint stage before proceeding
|
|
COPY --from=lint /src/go.sum /dev/null
|
|
|
|
WORKDIR /src
|
|
COPY go.mod go.sum ./
|
|
RUN go mod download
|
|
|
|
COPY . .
|
|
|
|
# Run the tests - build fails if any test fails
|
|
RUN make test
|
|
|
|
# Build the binary
|
|
RUN make build
|
|
|
|
# Runtime stage
|
|
# alpine 3.21, 2026-02-28
|
|
FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
|
|
|
RUN apk add --no-cache ca-certificates tzdata su-exec
|
|
|
|
COPY --from=builder /src/bin/dnswatcher /usr/local/bin/dnswatcher
|
|
COPY deploy/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
|
|
|
# dnswatcher runs as this unprivileged user. The entrypoint creates the
|
|
# data directory and gives it to this user on every start.
|
|
RUN addgroup -S -g 10001 dnswatcher \
|
|
&& adduser -S -G dnswatcher -u 10001 dnswatcher
|
|
|
|
ENV DNSWATCHER_DATA_DIR=/var/lib/dnswatcher
|
|
|
|
# Config loading also reads a `.env` file and a file named `dnswatcher`
|
|
# (any config extension, or none) from the working directory. `/` holds
|
|
# neither, so every setting comes from the environment. Do not make the
|
|
# data directory, or the binary's directory, the working directory.
|
|
WORKDIR /
|
|
|
|
# No USER: the entrypoint must start as root to set up the data
|
|
# directory; it then runs dnswatcher as the dnswatcher user.
|
|
|
|
EXPOSE 8080
|
|
|
|
# busybox wget (already in alpine) probes the health endpoint every 10
|
|
# seconds, so the container is healthy well before upaas reads its health
|
|
# 60 seconds after a deploy and fails the deploy unless it is healthy.
|
|
HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 \
|
|
CMD wget -q -O /dev/null "http://127.0.0.1:${PORT:-8080}/.well-known/healthcheck" || exit 1
|
|
|
|
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|