1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# ── Build stage ───────────────────────────────────────────────────────────────
# Uses musl for a fully static binary — no glibc dependency in the runtime image.
FROM rust:alpine AS builder
RUN apk add --no-cache musl-dev
WORKDIR /build
# Cache dependencies before copying source.
# Stub binaries allow `cargo build` to cache all crate downloads and compilation
# without re-running when only application source changes.
COPY Cargo.toml Cargo.lock ./
RUN mkdir -p src/bin \
&& echo "fn main() {}" > src/bin/arbit.rs \
&& echo "fn main() {}" > src/bin/dummy_server.rs \
&& echo "" > src/lib.rs \
&& cargo build --release --bin arbit \
&& rm -rf src
# Build the real binary
COPY src ./src
RUN touch src/lib.rs \
&& cargo build --release --bin arbit
# ── Runtime stage ─────────────────────────────────────────────────────────────
# Static binary + ca-certificates in a minimal image.
# Uses debian:bookworm-slim (not scratch) to have /etc/passwd and CA certs
# available without manual setup — simplifies Kubernetes RunAsNonRoot.
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates wget \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd --gid 10001 arbit \
&& useradd --uid 10001 --gid arbit --no-create-home --shell /sbin/nologin arbit
WORKDIR /app
COPY --from=builder /build/target/release/arbit /usr/local/bin/arbit
# Default config location — override with -v or ConfigMap mount
COPY gateway.yml /app/gateway.yml
EXPOSE 4000
# Run as non-root by default
USER arbit
# LOG_FORMAT=json → structured JSON logs (recommended for log aggregators)
# LOG_LEVEL=info → log verbosity (debug | info | warn | error)
ENV LOG_FORMAT=json \
LOG_LEVEL=info
ENTRYPOINT ["arbit"]
CMD ["start", "/app/gateway.yml"]