Containerfile
⎇
Raw
1# One image: the Rust binary with the web UI compiled into it.
2#
3# Named Containerfile, so podman finds it without -f. The just recipes pass -f
4# anyway, because the docker CLI only looks for Dockerfile.
5#
6# `rust-embed` pulls web/dist into the binary in release mode, so the runtime
7# stage carries no assets and no web server — just the one executable.
8
9FROM oven/bun:1.4 AS web
10WORKDIR /web
11COPY web/package.json web/bun.lock ./
12RUN bun install --frozen-lockfile
13COPY web/ ./
14RUN bun run build
15
16FROM rust:1-slim-trixie AS server
17WORKDIR /src
18# libsqlite3-sys is vendored, so the build needs a C toolchain but no dev headers.
19RUN apt-get update && apt-get install -y --no-install-recommends gcc libc6-dev && rm -rf /var/lib/apt/lists/*
20COPY Cargo.toml Cargo.lock ./
21COPY crates/ crates/
22COPY --from=web /web/dist/ web/dist/
23RUN cargo build --release -p otserver
24
25FROM debian:trixie-slim
26# ca-certificates is not optional: the tile proxy fetches over HTTPS.
27RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \
28 && rm -rf /var/lib/apt/lists/* \
29 && useradd --system --uid 10001 --home /data opentracker \
30 && mkdir -p /data && chown opentracker /data
31COPY --from=server /src/target/release/otserver /usr/local/bin/otserver
32
33USER opentracker
34WORKDIR /data
35ENV OT_HTTP_ADDR=0.0.0.0:7372 \
36 OT_UDP_ADDR=0.0.0.0:7373 \
37 OT_DB_PATH=/data/opentracker.db \
38 OT_CACHE_DIR=/data/cache
39VOLUME /data
40
41# THE TRAP: 7373 is UDP and HTTP reverse proxies do not forward it. It needs its
42# own published port and its own firewall rule, or every phone silently falls
43# back to TLS-over-TCP and the whole point of the protocol is lost.
44EXPOSE 7372/tcp 7373/udp
45
46ENTRYPOINT ["otserver"]
47