# Multi-stage optimized Dockerfile with caching and minimal size # Build: docker build --build-arg SERVICE_NAME=users -f Dockerfile.fast . # Stage 1: Chef - Prepare dependency recipe FROM rust:alpine AS chef RUN apk add --no-cache musl-dev pkgconfig openssl-dev && \ rustup target add x86_64-unknown-linux-musl && \ cargo install cargo-chef WORKDIR /app # Stage 2: Planner - Analyze dependencies FROM chef AS planner COPY Cargo.toml Cargo.lock ./ COPY crates/ ./crates/ COPY apps/ ./apps/ RUN cargo chef prepare --recipe-path recipe.json # Stage 3: Builder - Compile with caching FROM chef AS builder ARG SERVICE_NAME ARG RUSTFLAGS="-C target-feature=+crt-static -C link-arg=-s" # Copy recipe and build dependencies (cached layer!) COPY --from=planner /app/recipe.json recipe.json RUN cargo chef cook --release --target x86_64-unknown-linux-musl --recipe-path recipe.json # Copy source and build specific service COPY Cargo.toml Cargo.lock ./ COPY crates/ ./crates/ COPY apps/ ./apps/ # Build with size optimizations ENV RUSTFLAGS="${RUSTFLAGS}" ENV CARGO_NET_OFFLINE=false ENV CARGO_NET_RETRY=10 # Use single job for better caching RUN cargo build --release \ --bin ${SERVICE_NAME} \ --target x86_64-unknown-linux-musl \ --locked # Stage 4: Minimal runtime - Scratch (even smaller than distroless!) FROM scratch AS runtime ARG SERVICE_NAME # Copy CA certificates for HTTPS COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ # Copy static binary COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/${SERVICE_NAME} /app/service # Expose port (will be overridden by env) EXPOSE 8000 # Run as non-root (numeric uid for scratch) USER 65532:65532 ENTRYPOINT ["/app/service"]