Files
doctate/server/Dockerfile
T
Brummel cf80bc7e97 feat: containerize doctate-server for minerva deployment
Multi-stage Dockerfile, host-network compose, idempotent deploy script.
Configs and persistent data bind-mounted from /opt/stacks/doctate-server.
deploy-server.sh handles bootstrap + re-deploy in one command with
auto-prune (keep 5 last SHA-tagged images).

See docs/deployment.md for bootstrap, rollback, and TLS-proxy notes.
2026-05-04 11:14:31 +02:00

64 lines
2.6 KiB
Docker

# 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"]