feat: initial sunbeam-proxy implementation
Custom Pingora-based edge proxy for the Sunbeam infrastructure stack. - HTTPS termination: mkcert file-based (local dev) or rustls-acme ACME (production) - Host-prefix routing with path-based sub-routing (auth virtual host) - HTTP→HTTPS redirect, WebSocket passthrough - cert-manager HTTP-01 challenge routing via Kubernetes Ingress watcher - TLS cert auto-reload via K8s Secret watcher - JSON structured audit logging (tracing-subscriber) - OpenTelemetry OTLP stub (disabled by default) - Multi-stage Dockerfile: musl static binary on chainguard/static distroless image Signed-off-by: Sienna Meridian Satterwhite <sienna@sunbeam.pt>
This commit is contained in:
67
Dockerfile
Normal file
67
Dockerfile
Normal file
@@ -0,0 +1,67 @@
|
||||
# ── Stage 1: build ──────────────────────────────────────────────
|
||||
# rust:slim tracks the latest stable Rust release.
|
||||
# Multi-arch image; Docker buildx selects the native platform image.
|
||||
FROM rust:slim AS builder
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
# musl-tools: musl-gcc for static linking.
|
||||
# curl: download tini init binary.
|
||||
# No cmake/go needed: we use the rustls feature flag (pure Rust TLS).
|
||||
RUN apt-get update && apt-get install -y musl-tools curl cmake && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Map Docker TARGETARCH to the appropriate Rust musl target,
|
||||
# then configure Cargo to use musl-gcc as the linker for that target.
|
||||
RUN case "${TARGETARCH}" in \
|
||||
"amd64") RUST_TARGET="x86_64-unknown-linux-musl" ;; \
|
||||
"arm64") RUST_TARGET="aarch64-unknown-linux-musl" ;; \
|
||||
*) echo "Unsupported arch: ${TARGETARCH}" && exit 1 ;; \
|
||||
esac && \
|
||||
echo "${RUST_TARGET}" > /rust-target && \
|
||||
rustup target add "${RUST_TARGET}" && \
|
||||
mkdir -p /root/.cargo && \
|
||||
printf '[target.%s]\nlinker = "musl-gcc"\n' "${RUST_TARGET}" \
|
||||
>> /root/.cargo/config.toml
|
||||
|
||||
ENV RUSTFLAGS="-C target-feature=+crt-static"
|
||||
WORKDIR /build
|
||||
|
||||
# Cache dependency compilation separately from source changes.
|
||||
# RUSTFLAGS must match the real build or Cargo will recompile everything.
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
RUN mkdir src && \
|
||||
echo 'fn main() {}' > src/main.rs && \
|
||||
cargo build --release --target "$(cat /rust-target)" ; \
|
||||
rm -rf src
|
||||
|
||||
# Build the real binary.
|
||||
COPY src/ ./src/
|
||||
RUN touch src/main.rs && \
|
||||
cargo build --release --target "$(cat /rust-target)" && \
|
||||
cp "target/$(cat /rust-target)/release/sunbeam-proxy" /sunbeam-proxy
|
||||
|
||||
# Download tini static init binary (musl, no glibc dependency).
|
||||
# tini as PID 1 ensures the container stays alive when Pingora re-execs itself
|
||||
# during a graceful upgrade: the new process is re-parented to tini, and tini
|
||||
# correctly reaps the old process when it exits after draining connections.
|
||||
RUN case "${TARGETARCH}" in \
|
||||
"amd64") TINI_ARCH="amd64" ;; \
|
||||
"arm64") TINI_ARCH="arm64" ;; \
|
||||
*) echo "Unsupported arch: ${TARGETARCH}" && exit 1 ;; \
|
||||
esac && \
|
||||
curl -fsSL -o /tini \
|
||||
"https://github.com/krallin/tini/releases/download/v0.19.0/tini-static-${TINI_ARCH}" && \
|
||||
chmod +x /tini
|
||||
|
||||
# ── Stage 2: distroless final ────────────────────────────────────
|
||||
# cgr.dev/chainguard/static is multi-arch (amd64 + arm64).
|
||||
# No shell, no package manager — minimal attack surface.
|
||||
FROM cgr.dev/chainguard/static:latest
|
||||
|
||||
COPY --from=builder /tini /tini
|
||||
COPY --from=builder /sunbeam-proxy /usr/local/bin/sunbeam-proxy
|
||||
|
||||
EXPOSE 80 443
|
||||
|
||||
# tini as PID 1 so Pingora's graceful-upgrade re-exec doesn't kill the container.
|
||||
ENTRYPOINT ["/tini", "--", "/usr/local/bin/sunbeam-proxy"]
|
||||
Reference in New Issue
Block a user