check / check (push) Failing after 1m54s
A plain `docker build .`, which is how upaas builds, stamped `dev`: `.dockerignore` left out `.git` and the builder declared `ARG VERSION=dev`. `.dockerignore` now sends `.git` without `.git/config`, which can hold a credential, and lists no tracked file, which git in the build would count as deleted and mark `-dirty`. `ARG VERSION` has no default. The Makefile takes a non-empty `VERSION` from the command line or the environment, so a build arg still wins (`script/docker` keeps passing one); otherwise `git describe` runs in the builder. A new `make version` prints the version, and the builder fails when the context carries `.git`, directory or file, and it comes out empty, `dev` or `unknown`. Model: opus-5-5
94 lines
3.4 KiB
Docker
94 lines
3.4 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. For the same reason this stage
|
|
# runs only the Go half of `make fmt-check`; script/cibuild runs the
|
|
# markdown half after this 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 script/fmt-check-go
|
|
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
|
|
|
|
# Version stamped into the binary: the VERSION build arg when one is
|
|
# given and not empty (script/docker passes one), otherwise what
|
|
# `git describe` says of the .git in the build context, so a plain
|
|
# `docker build .` of a clone stamps its tag or short commit. The build
|
|
# arg reaches make through the environment.
|
|
ARG VERSION
|
|
|
|
# A context that carries .git, as a directory or as a file, must yield a
|
|
# real version: one that is empty, `dev` or `unknown` cannot be traced
|
|
# back to a commit.
|
|
RUN version="$(make version)"; \
|
|
if [ -e .git ]; then \
|
|
case "$version" in \
|
|
"" | dev | unknown) \
|
|
echo "version is \"$version\" although the build context carries .git" >&2; \
|
|
exit 1 ;; \
|
|
esac; \
|
|
fi
|
|
|
|
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"]
|