| 1 | # syntax=docker/dockerfile:1.7 |
| 2 | |
| 3 | # ---- Build stage ---- |
| 4 | FROM rust:1.96-bookworm AS builder |
| 5 | |
| 6 | WORKDIR /app |
| 7 | |
| 8 | # Cache dependencies: copy the manifest first, build a dummy target, then sources. |
| 9 | # Cargo.lock is committed in CI; if present it is honored, otherwise generated. |
| 10 | COPY Cargo.toml ./ |
| 11 | COPY Cargo.lock* ./ |
| 12 | RUN mkdir -p src \ |
| 13 | && echo 'fn main() {}' > src/main.rs \ |
| 14 | && echo '' > src/lib.rs \ |
| 15 | && cargo build --release || true \ |
| 16 | && rm -rf src |
| 17 | |
| 18 | # Now copy the real sources and migrations and build for real. |
| 19 | COPY src ./src |
| 20 | COPY migrations ./migrations |
| 21 | # SQLx uses runtime queries (no compile-time DB checks), so no DB is needed here. |
| 22 | # Drop the dummy-crate fingerprint and artifacts so cargo recompiles the real |
| 23 | # sources (replacing src/ in place does not always invalidate the cached binary). |
| 24 | RUN rm -f target/release/drophawk-backend \ |
| 25 | && rm -rf target/release/deps/drophawk_backend-* target/release/deps/drophawk-backend-* \ |
| 26 | && find target/release/.fingerprint -maxdepth 1 -name 'drophawk*' -exec rm -rf {} + 2>/dev/null || true \ |
| 27 | && cargo build --release --bin drophawk-backend \ |
| 28 | && strip target/release/drophawk-backend |
| 29 | |
| 30 | # ---- Runtime stage ---- |
| 31 | # Distroless: minimal, no shell, runs as nonroot. cc variant provides libgcc/libc |
| 32 | # needed by the dynamically linked binary. |
| 33 | FROM gcr.io/distroless/cc-debian12:nonroot AS runtime |
| 34 | |
| 35 | WORKDIR /app |
| 36 | |
| 37 | # The binary and the migrations it applies at startup. |
| 38 | COPY --from=builder /app/target/release/drophawk-backend /usr/local/bin/drophawk-backend |
| 39 | COPY --from=builder /app/migrations /app/migrations |
| 40 | |
| 41 | EXPOSE 8080 |
| 42 | USER nonroot:nonroot |
| 43 | |
| 44 | ENTRYPOINT ["/usr/local/bin/drophawk-backend"] |