# syntax=docker/dockerfile:1.7 # Multi-stage build for doctate-server. Stage 1 compiles the Rust binary; # stage 2 ships only the binary + runtime tools (ffmpeg, hunspell dict). # ----------------------------------------------------------------------- # Stage 1: builder # ----------------------------------------------------------------------- FROM rust:1.94-slim-bookworm AS builder # pkg-config + ca-certificates suffice — reqwest uses rustls-tls # (no libssl-dev needed), and our other crates don't probe native libs. RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config ca-certificates && \ rm -rf /var/lib/apt/lists/* WORKDIR /build # Copy `common/` AND `server/` so the path dependency resolves # (server/Cargo.toml references `../common`). COPY common/ ./common/ COPY server/ ./server/ WORKDIR /build/server # BuildKit cache mounts: registry/ and target/ persist between builds # but are NOT part of the resulting image layers. Output binaries # therefore have to be copied to /out (outside the cache mount) so # stage 2 can pick them up via COPY --from=builder. RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/build/server/target \ cargo build --release --bin doctate-server --bin hash-password && \ mkdir -p /out && \ cp target/release/doctate-server /out/ && \ cp target/release/hash-password /out/ # ----------------------------------------------------------------------- # Stage 2: runtime # ----------------------------------------------------------------------- FROM debian:bookworm-slim AS runtime # ffmpeg/ffprobe are invoked as subprocesses by server/src/transcribe/ffmpeg.rs. # hunspell-de-de installs the dict files /usr/share/hunspell/de_DE.{dic,aff} # which the `spellbook` Rust library reads via the HUNSPELL_DICT env var. # tzdata gives us proper local-time formatting in logs. # curl is required by HEALTHCHECK below. RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg hunspell-de-de ca-certificates curl tzdata && \ rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=builder /out/doctate-server /usr/local/bin/ COPY --from=builder /out/hash-password /usr/local/bin/ # Default vocab ships with the image; operator can override via bind-mount. COPY server/vocab/ /app/vocab/ EXPOSE 3000 # Container-level health probe. SERVER_PORT defaults to 3000 if unset # (matches the value in server/.env.example). HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD curl -fsS "http://127.0.0.1:${SERVER_PORT:-3000}/api/health" || exit 1 CMD ["doctate-server"]