milestone 14: build, package, sign and publish releases

This commit is contained in:
2026-08-08 12:38:29 +02:00
parent 6c507992e4
commit cdacc560b7
48 changed files with 7272 additions and 543 deletions
+54 -24
View File
@@ -1,39 +1,69 @@
# The binary is NOT compiled here. Build it first, from the repository root:
#
# (cd web && npm ci && npm run build)
# zig build cross -Dweb-dist=web/dist -Doptimize=ReleaseSafe
# zig build dist -Dversion-string=<V> -Dgit-commit=<SHA> \
# -Dweb-dist=web/dist -Doptimize=ReleaseSafe
#
# then build the image with the repository root as context:
#
# docker build -t nxdns -f deploy/docker/Dockerfile .
#
# The builder stage stages the CA bundle (upstream DoH/DoT verification rescans
# the system store; a scratch image without one breaks every TLS upstream) and
# maps the buildx TARGETARCH onto the zig cross-target directory. The legacy
# builder leaves TARGETARCH empty, so the arch falls back to the build host's
# `uname -m`: a plain `docker build` must never package a foreign binary that
# only fails at `docker run` with exec-format.
# The builder stage only copies files, so it is pinned to $BUILDPLATFORM: the
# arm64 image is assembled natively and needs no qemu under buildx. That makes
# BuildKit a requirement, not a preference. `DOCKER_BUILDKIT=0` fails at the
# first FROM, because the classic builder defines no BUILDPLATFORM and rejects
# the empty `--platform=`. Do not "fix" that by declaring
# `ARG BUILDPLATFORM=<default>`: a declared default shadows BuildKit's built-in
# and silently drags the builder stage back under emulation on cross builds.
#
# It stages the CA bundle that the pinned base already ships (upstream DoH/DoT
# verification rescans the system store; a scratch image without one breaks
# every TLS upstream) and maps TARGETARCH onto the zig target triple. A builder
# that leaves TARGETARCH empty falls back to the build host's `uname -m`: no
# build may package a foreign binary that only fails at `docker run` with
# exec-format.
FROM alpine:3.22 AS builder
RUN apk add --no-cache ca-certificates
FROM --platform=$BUILDPLATFORM alpine:3.22@sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dce AS builder
ARG TARGETARCH
COPY zig-out/cross /cross
RUN mkdir -p /rootfs/etc/ssl/certs /rootfs/etc/nxdns /rootfs/var/lib/nxdns \
&& cp /etc/ssl/certs/ca-certificates.crt /rootfs/etc/ssl/certs/ \
&& arch="${TARGETARCH:-}" \
&& if [ -z "$arch" ]; then case "$(uname -m)" in \
x86_64) arch=amd64 ;; \
aarch64) arch=arm64 ;; \
*) echo "unsupported build host $(uname -m); use buildx" >&2; exit 1 ;; \
esac; fi \
&& case "$arch" in \
amd64) cp /cross/x86_64-linux-musl/nxdns /rootfs/nxdns ;; \
arm64) cp /cross/aarch64-linux-musl/nxdns /rootfs/nxdns ;; \
*) echo "unsupported TARGETARCH '${TARGETARCH}'" >&2; exit 1 ;; \
esac \
&& chown 65532:65532 /rootfs/var/lib/nxdns
COPY zig-out/dist/bin /dist/bin
COPY zig-out/dist/stage /dist/stage
RUN set -eu; \
mkdir -p /rootfs/etc/ssl/certs /rootfs/etc/nxdns /rootfs/var/lib/nxdns; \
cp /etc/ssl/certs/ca-certificates.crt /rootfs/etc/ssl/certs/; \
arch="${TARGETARCH:-}"; \
if [ -z "$arch" ]; then \
case "$(uname -m)" in \
x86_64) arch=amd64 ;; \
aarch64) arch=arm64 ;; \
*) echo "unsupported build host $(uname -m); use buildx" >&2; exit 1 ;; \
esac; \
fi; \
case "$arch" in \
amd64) triple=x86_64-linux-musl ;; \
arm64) triple=aarch64-linux-musl ;; \
*) echo "unsupported TARGETARCH '${TARGETARCH}'" >&2; exit 1 ;; \
esac; \
cp "/dist/bin/$triple/nxdns" /rootfs/nxdns; \
chmod 0755 /rootfs/nxdns; \
stage=$(find /dist/stage -mindepth 1 -maxdepth 1 -type d -name "nxdns-*-$triple"); \
if [ "$(printf '%s' "$stage" | grep -c '^')" != 1 ]; then \
echo "expected exactly one /dist/stage dir for $triple, found: $stage" >&2; exit 1; \
fi; \
cp "$stage/LICENSE" "$stage/THIRD-PARTY-NOTICES" /rootfs/; \
chmod 0644 /rootfs/LICENSE /rootfs/THIRD-PARTY-NOTICES; \
chown 65532:65532 /rootfs/var/lib/nxdns
FROM scratch
ARG VERSION=0.0.0-dev
ARG REVISION=unknown
ARG CREATED=1970-01-01T00:00:00Z
LABEL org.opencontainers.image.source="https://git.mial.net/mokhtar/nxdns" \
org.opencontainers.image.revision="$REVISION" \
org.opencontainers.image.version="$VERSION" \
org.opencontainers.image.licenses="EUPL-1.2" \
org.opencontainers.image.created="$CREATED" \
org.opencontainers.image.title="nxdns" \
org.opencontainers.image.description="Self-hosted DNS sinkhole for a household LAN"
COPY --from=builder /rootfs/ /
USER 65532:65532
VOLUME /var/lib/nxdns