bindcar 0.7.2

HTTP REST API for managing BIND9 zones via rndc
# Copyright (c) 2025 Erick Bourgeois, firestoned
# SPDX-License-Identifier: MIT

# CHAINGUARD PRODUCTION DOCKERFILE - CVE-Free Base Images
# This Dockerfile uses Chainguard's hardened, zero-CVE base images designed for
# regulated environments (SOX, NIST 800-53, PCI-DSS, FedRAMP).
#
# Build time: ~30 seconds (just copies pre-built binaries)
#
# Base image: Chainguard glibc-dynamic (CVE-free, daily rebuilds, SBOMs included)
#
# Benefits:
# - Zero known CVEs (Chainguard rebuilds daily with security patches)
# - FIPS-validated images available (cgr.dev/chainguard/glibc-dynamic:latest-fips)
# - Included SBOMs for supply chain security
# - Designed for compliance (SOX, FedRAMP, PCI-DSS)
# - ~10-15MB image size
# - Non-root by default
#
# Usage in CI/CD:
#   1. Build binaries for both architectures using cargo (GNU targets)
#   2. Copy binaries to ./binaries/amd64/ and ./binaries/arm64/
#   3. Build multi-arch image:
#      docker buildx build --platform linux/amd64,linux/arm64 \
#        -f docker/Dockerfile.chainguard \
#        -t registry/image:tag-chainguard .
#
# The TARGETARCH build argument is automatically set by Docker BuildKit
# to match the target platform (amd64 or arm64).

# nsupdate builder stage — bindcar shells out to `nsupdate` (RFC 2136 dynamic
# DNS updates) for record management. Install it from Wolfi (the same distro as
# the glibc-dynamic runtime below) and stage the binary plus its shared-library
# dependencies (glibc core excluded — the runtime base provides it). `/lib` deps
# are remapped to `/usr/lib` because the runtime base's `/lib` is a usrmerge
# symlink (COPYing a real `/lib` dir onto it fails). The digest
# is pinned for reproducibility (A11); resolve with
#   docker buildx imagetools inspect cgr.dev/chainguard/wolfi-base:latest --raw | sha256sum
FROM cgr.dev/chainguard/wolfi-base:latest@sha256:2f7a5c164eafbdbe46fe1d91bd1ab4c8cb5c2bdbd10641c3d61bd39962384cdb AS nsupdate
RUN apk add --no-cache bind-tools \
 && mkdir -p /staging/usr/bin \
 && cp -L /usr/bin/nsupdate /staging/usr/bin/ \
 && LD_TRACE_LOADED_OBJECTS=1 /usr/bin/nsupdate 2>/dev/null \
      | awk '/=>/ { print $3 }' | grep -E '^/' \
      | grep -Ev '/(libc|libm|libpthread|libdl|librt|libresolv|libnsl)\.so' \
      | sort -u \
      | while read -r lib; do \
          dst="/staging$lib"; \
          case "$lib" in /lib/*|/lib64/*) dst="/staging/usr$lib" ;; esac; \
          mkdir -p "$(dirname "$dst")"; \
          cp -L "$lib" "$dst"; \
        done

# Runtime stage - Chainguard glibc-dynamic (zero CVEs)
# SECURITY (A11): pinned to the MULTI-ARCH manifest-list digest (OCI image index,
# linux/amd64 + linux/arm64), NOT a platform-specific digest — this preserves
# reproducibility/SLSA provenance and closes the supply-chain substitution window
# of the mutable `:latest` tag, matching the sibling docker/Dockerfile.
# NOTE: Chainguard rebuilds :latest daily for CVE fixes; pinning freezes those
# until the digest is bumped, so Dependabot's docker ecosystem must track it.
# Re-resolve with: docker buildx imagetools inspect <image> --raw | sha256sum
FROM cgr.dev/chainguard/glibc-dynamic:latest@sha256:ea9eab0adc5716fb9937ab60155a31bce9cbc8b56e6f2e21fb9af9218be195b7

ARG TARGETARCH
ARG VERSION=0.1.0

LABEL org.opencontainers.image.source="https://github.com/firestoned/bindcar"
LABEL org.opencontainers.image.description="BIND9 RNDC API Server (Chainguard - Zero CVEs)"
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.version="${VERSION}"
LABEL org.opencontainers.image.base.name="cgr.dev/chainguard/glibc-dynamic:latest@sha256:ea9eab0adc5716fb9937ab60155a31bce9cbc8b56e6f2e21fb9af9218be195b7"

# Copy the pre-built binary for the target architecture
# TARGETARCH is automatically set by BuildKit (amd64 or arm64)
# Map docker architectures to our binary paths:
# - amd64 → binaries/amd64/bindcar (x86_64-unknown-linux-gnu)
# - arm64 → binaries/arm64/bindcar (aarch64-unknown-linux-gnu)
COPY --chmod=755 binaries/${TARGETARCH}/bindcar /usr/local/bin/bindcar

# nsupdate + its shared libraries (for dynamic DNS record management)
COPY --from=nsupdate /staging/ /

# Chainguard images run as nonroot user (UID 65532) by default
USER 65532:65532

# Expose API port
EXPOSE 8080

# Set default environment variables
ENV BIND_ZONE_DIR=/var/cache/bind
ENV API_PORT=8080
ENV RUST_LOG=info
# DISABLE_AUTH is intentionally not baked in: the binary defaults it to false,
# and an ENV whose name matches "AUTH" trips BuildKit's SecretsUsedInArgOrEnv
# lint. Set it explicitly at run time if ever required.

# Start the API server
ENTRYPOINT ["/usr/local/bin/bindcar"]