Single-binary self-hosted uptime monitoring and status pages on Rust axum: HTTP probes, Lighthouse audits, SEO crawler, and PDF reports.
axumdockerrustself-hostedsqlitestatus-pageuptime-monitoringvite
1# syntax=docker/dockerfile:1
2# ----- builder -----
3FROM rust:alpine AS builder
4
5RUN apk add --no-cache musl-dev pkgconfig openssl-dev
6
7COPY --from=oven/bun:alpine /usr/local/bin/bun /usr/local/bin/bun
8
9WORKDIR /app
10
11COPY Cargo.toml Cargo.lock ./
12COPY src ./src
13COPY migrations ./migrations
14COPY frontend ./frontend
15COPY templates ./templates
16
17RUN cd frontend && bun install --frozen-lockfile && bun run build
18
19RUN --mount=type=cache,target=/usr/local/cargo/registry \
20 --mount=type=cache,target=/app/target \
21 cargo build --release && \
22 cp target/release/status /app/status
23
24# ----- runtime -----
25FROM alpine:3.23
26
27# chromium for the lighthouse CLI to drive (lighthouse never bundled a browser).
28# PDF reports are rendered in-process via embedded Typst, so the chromium dep is
29# lighthouse-only. Fonts are for the Typst renderer (it scans system fonts at
30# boot and embeds the listed families into output PDFs).
31RUN apk add --no-cache \
32 chromium ca-certificates \
33 font-jetbrains-mono ttf-dejavu ttf-liberation fontconfig
34
35# bun in the runtime stage runs the lighthouse CLI via `bun run --bun`, which
36# symlinks nodeābun so the shim's `#!/usr/bin/env node` shebang resolves to bun.
37COPY --from=oven/bun:alpine /usr/local/bin/bun /usr/local/bin/bun
38
39WORKDIR /app
40
41COPY --from=builder /app/status ./status
42COPY --from=builder /app/dist ./dist
43COPY templates ./templates
44COPY migrations ./migrations
45COPY package.json bun.lock ./
46
47# Lighthouse package is required at runtime: the rust binary shells out to
48# /app/node_modules/.bin/lighthouse via `bun run --bun` for site audits.
49RUN bun install --frozen-lockfile --production
50
51RUN addgroup -S -g 1000 app && \
52 adduser -S -h /app -s /sbin/nologin -u 1000 -G app app && \
53 mkdir -p /data && chown -R app:app /app /data
54USER app
55
56ENV PORT=8000
57ENV STATUS_DATA_DIR=/data
58ENV CHROMIUM_BIN=/usr/bin/chromium-browser
59EXPOSE 8000
60
61CMD ["./status"]