docker: run as non-root, add health check, document upaas (closes #147)
check / check (push) Successful in 53s
check / check (push) Successful in 53s
The runtime image runs as uid 10001, which owns /var/lib/dnswatcher. The working directory is /, so config loading finds no .env or dnswatcher config file there; the binary lives in /usr/local/bin. A Docker HEALTHCHECK probes /.well-known/healthcheck every 10 seconds with busybox wget, well inside the 60 seconds upaas waits. Startup now fails with an error naming the data directory when it cannot be written, instead of running with every save failing. The check creates the directory if needed and writes and removes the temp file Save uses; tests cover the create and the write failing. README gains "Running under upaas": the prod branch, host directory setup, network and port, environment and health check. Model: opus-5-5
This commit is contained in:
+24
-6
@@ -41,15 +41,33 @@ FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4
|
||||
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /src/bin/dnswatcher /usr/local/bin/dnswatcher
|
||||
|
||||
COPY --from=builder /src/bin/dnswatcher /app/dnswatcher
|
||||
|
||||
# Create data directory
|
||||
RUN mkdir -p /var/lib/dnswatcher
|
||||
# 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.
|
||||
RUN addgroup -S -g 10001 dnswatcher \
|
||||
&& adduser -S -G dnswatcher -u 10001 dnswatcher \
|
||||
&& mkdir -p /var/lib/dnswatcher \
|
||||
&& chown dnswatcher:dnswatcher /var/lib/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 /
|
||||
|
||||
USER dnswatcher
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["/app/dnswatcher"]
|
||||
# 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/dnswatcher"]
|
||||
|
||||
Reference in New Issue
Block a user