docker: set up the data directory in an entrypoint (closes #166)
check / check (push) Successful in 1m9s

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. An empty root-owned host directory, or one
holding a state file left by another uid, now works with no step on
the host, so the README's instruction to create and chown it is gone.
The startup check that the data directory is writable stays.

Model: opus-5-5
This commit is contained in:
2026-09-29 10:02:39 +00:00
parent 93c1fe15e3
commit d0ca6fbc81
4 changed files with 32 additions and 21 deletions
+8 -10
View File
@@ -41,18 +41,15 @@ RUN make build
# alpine 3.21, 2026-02-28
FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
RUN apk add --no-cache ca-certificates tzdata
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
# Run as an unprivileged user that owns the data directory. A fresh named
# volume inherits this ownership; a bind-mounted host directory must be
# owned by uid 10001 (see "Running under upaas" in README.md), or startup
# fails.
# 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 \
&& mkdir -p /var/lib/dnswatcher \
&& chown dnswatcher:dnswatcher /var/lib/dnswatcher
&& adduser -S -G dnswatcher -u 10001 dnswatcher
ENV DNSWATCHER_DATA_DIR=/var/lib/dnswatcher
@@ -62,7 +59,8 @@ ENV DNSWATCHER_DATA_DIR=/var/lib/dnswatcher
# data directory, or the binary's directory, the working directory.
WORKDIR /
USER dnswatcher
# No USER: the entrypoint must start as root to set up the data
# directory; it then runs dnswatcher as the dnswatcher user.
EXPOSE 8080
@@ -72,4 +70,4 @@ EXPOSE 8080
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/dnswatcher"]
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]