1# syntax=docker/dockerfile:1.723# Keep the checked-in web source readable and only minify the production copy.4FROM node:24-bookworm-slim AS web56WORKDIR /src78# Versions are exact in the lock file.9COPY package.json package-lock.json tsconfig.json biome.json ./10RUN npm ci1112# Tool installation is independent of the source, so ordinary web edits only13# invalidate the small minification layer below.14COPY web ./web15RUN npm run check:web \16 && mkdir /out \17 && cp -R web/. /out/ \18 && rm /out/*.ts /out/pkg/app.js.map \19 && npx --no-install esbuild web/pkg/app.js \20 --format=esm \21 --legal-comments=none \22 --minify \23 --outfile=/out/pkg/app.js \24 --target=es2022 \25 && npx --no-install esbuild web/site.css \26 --legal-comments=none \27 --minify \28 --outfile=/out/site.css \29 && npx --no-install html-minifier-terser web/index.html \30 --collapse-whitespace \31 --remove-comments \32 --remove-redundant-attributes \33 --remove-script-type-attributes \34 --remove-style-link-type-attributes \35 --use-short-doctype \36 --output /out/index.html3738# The control plane. Web and documentation edits never enter this stage, while39# registry and target caches keep Rust changes incremental across remote builds.40FROM rust:1.96-bookworm AS build4142WORKDIR /src43COPY Cargo.toml Cargo.lock ./44COPY crates ./crates4546RUN --mount=type=cache,id=devsite-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \47 --mount=type=cache,id=devsite-cargo-git,target=/usr/local/cargo/git,sharing=locked \48 --mount=type=cache,id=devsite-cargo-target,target=/src/target,sharing=locked \49 cargo build --release --locked -p devsite-server \50 && install -Dm755 target/release/devsite-server /out/devsite-server5152FROM debian:bookworm-slim5354# TLS roots, for OIDC code exchange and JWKS verification.55RUN apt-get update \56 && apt-get install -y --no-install-recommends ca-certificates \57 && rm -rf /var/lib/apt/lists/*5859COPY --from=build /out/devsite-server /usr/local/bin/devsite-server60COPY --from=web /out /app/web6162# Defaults for running in a container. Everything that differs per deployment —63# the public origin above all — is set in fly.toml or as a secret.64ENV DEVSITE_BIND=0.0.0.0:8080 \65 DEVSITE_WEB_ROOT=/app/web \66 DEVSITE_DB=/data/devsite.db \67 DEVSITE_STATE_DIR=/data/state6869EXPOSE 808070CMD ["devsite-server"]